diff --git a/.env.example b/.env.example index 731321b..8b5511f 100644 --- a/.env.example +++ b/.env.example @@ -4,9 +4,13 @@ NODE_ENV=development LOG_LEVEL=debug +# LOG_PRETTY=false # --- Datastores ------------------------------------------------------------- DATABASE_URL=postgres://atlas:atlas@localhost:5432/atlas +# Connections each function instance may open (1-100). Keep it small on serverless: every warm +# instance holds its own pool, and the database allows a fixed number in all. +# DATABASE_POOL_MAX=10 REDIS_URL=redis://localhost:6379 # Used by integration tests. When unset, DB-backed tests self-skip. @@ -19,7 +23,11 @@ ATLAS_TEST_DATABASE_URL=postgres://atlas:atlas@localhost:5432/atlas_test # delivers events across Vercel functions. Consumers (matching, # referrals, learning, analytics) only run when their # /internal/drain route is hit, so CRON_SECRET must be set there. +# On Vercel `memory` is ignored (the outbox is used): a function is its own process, so an +# in-memory broker would silently drop every cross-service event. MESSAGING_DRIVER=memory +# MESSAGING_EXCHANGE=atlas.events +# MESSAGING_MAX_RETRIES=5 RABBITMQ_URL=amqp://atlas:atlas@localhost:5672 # Bearer secret for POST|GET /internal/drain on the four consumer services and # for POST|GET /internal/jobs/ingest-sources on the jobs service (a scheduler @@ -75,6 +83,24 @@ SUPABASE_ACCESS_TOKEN= # jobs-service, referrals-service and learning-service only. PLATFORM_ADMIN_USER_IDS= +# --- HTTP (every service) ------------------------------------------------------ +# Largest request body in bytes, at least 1024. Resume uploads are limited by it too. +# BODY_LIMIT_BYTES=1048576 +# HOST=0.0.0.0 + +# --- Browser access (every service) --------------------------------------------- +# Origins allowed to call the API from a browser, comma separated: scheme and host only, with no +# path (https://app.example.com). A trailing slash is forgiven; an entry that can never match, such +# as a bare host or a URL with a path, stops the service from starting. Leave empty to allow none. +# CORS_ORIGINS=https://app.example.com,https://admin.example.com + +# --- Rate limiting (every service) -------------------------------------------- +# At most RATE_LIMIT_MAX requests per client address in each RATE_LIMIT_WINDOW. The window is a +# number and a unit between 1 second and 7 days ("30 seconds", "1 minute", "1 hour"). A bare number +# such as 60, or text the limiter cannot read, stops the service from starting. +# RATE_LIMIT_MAX=300 +# RATE_LIMIT_WINDOW=1 minute + # --- Account privacy (auth service) ------------------------------------------- # Per-client-address budgets for GET /v1/auth/me/export and DELETE /v1/auth/me. They replace # (do not add to) the general RATE_LIMIT_* budget on those two routes. Counters live in each diff --git a/NEXT.md b/NEXT.md new file mode 100644 index 0000000..72b9e46 --- /dev/null +++ b/NEXT.md @@ -0,0 +1,61 @@ +# NEXT + +Working list for the autonomous stretch that started 2026-10-31. Most valuable first. + +**Goal for this stretch:** break the project locally, find real defects, fix them, and record what held, so +the 2026-11-17 launch (individuals plus one university pilot) rests on tested behaviour. The brief that +describes the attack areas (A to G) lives outside the repo; each task below names its area. + +**Ground rules for this stretch** +- Local only: tests and scripts run against a private Postgres (`atlas_integ`) and in-process Fastify apps. Nothing is run against Vercel, Supabase or any live system. +- No secrets or `.env` files touched. No new dependencies unless a task says why. +- Work happens on `work/` branches cut from `claude/blissful-darwin-2n33wv` (the unmerged launch branch). Nothing is committed to `main`, nothing is merged. +- A task that needs a decision goes under "Needs Nikshey" and is skipped. +- Checks per task: `pnpm typecheck`, `npx eslint . --ignore-pattern '.claude/worktrees/**'`, and the affected tests (`ATLAS_TEST_DATABASE_URL=postgres://atlas:atlas@localhost:5432/atlas_integ npx vitest run `). `node scripts/bundle-backend.mjs` when service or package sources change. + +## Queue + +3. [ ] **Env boot fuzz, last part (F).** Done: rate limit, CORS, `SUPABASE_URL`, `CRON_SECRET`, `MESSAGING_DRIVER` on Vercel, `.env.example` drift. Still to do: `STORAGE_DRIVER` combinations (supabase needs URL, key and bucket; local driver on serverless), `DATABASE_URL` oddities (pooler/prepared statements), and a per-service boot with every variable blank. +4. [ ] **Authorization matrix, runtime part (A).** Token forgery and the ownership checks were attacked and read (see Done). Still to do: run every route against anonymous, other user, other org staff, same-org roles and platform admin as a table-driven test, and mass assignment (extra keys such as `user_id`, `organization_id`, `role`, `status`) on every create and update body; RLS as the `anon`/`authenticated` roles on every table. +5. [ ] **Validation fuzz, rest of it (B).** Cursors are done (see Done). Still to do: malformed JSON bodies, wrong types and oversized bodies on every POST, `__proto__` keys, odd UUIDs in paths and query filters (`location=%`, `remote_type`), duplicate query keys (`?limit=1&limit=2`), content-type mismatches, and the error envelope for each. +7. [ ] **ReDoS audit, last part (D).** Everything with user-supplied text is done (`packages/ai`, services, both CSV parsers, the web description cleaner). Still to do: `scripts/` (the smoke script parses only responses from our own deployment, so low priority). +8. [ ] **Upload parsers, last part (D).** Still to do: multipart edge cases (no boundary, duplicate or many parts, a field larger than the limit) and a wall-clock limit on PDF text extraction (pdf.js can also be slow without being large). Also: a failed insert after the file was stored leaves the blob behind (cleanup on error). +9. [ ] **Races, rest of it (C).** Applications are done (see Done). Still to do: double drains (each event's effects applied once), double account deletion and deletion during activity, parallel roster imports, concurrent job ingest of the same posting, and `setScheduled` in outreach (unconditional update; only matters if delivery is ever enabled). +10. [ ] **Committed bundles, last flows (G).** Main loop, drains, roster import and account deletion are done (see Done). Still to do: an outreach draft through the outreach bundle (needs a contact from a platform admin) and referrals. +12. [ ] **Frontends, signed in (E).** Static review, redirect, link and header checks, and a browser sweep of the signed-out pages are done (see Done). Still to do: a stand-in Supabase (token and user endpoints, session cookie) so Playwright can open the signed-in pages with script-like, oversized, RTL and null data, API 500 / 429 / malformed JSON, double submit on mutating buttons, and a Content-Security-Policy with nonces. + +## Done + +- [x] **Rate limiter vs real client IP (F)** — `work/break-fix-1`. Found and fixed: a bad `RATE_LIMIT_WINDOW` booted and then 500'd every request, or silently disabled limiting. Checked and held: store is a bounded LRU, exempt routes are by scope not path. Spoofable `X-Forwarded-For` is safe on Vercel (it overwrites the header); noted in `docs/17_break_report.md`. Typecheck, lint, full suite (119 files, 1,730 tests) pass; bundles rebuilt. +- [x] **Internal routes and rewrites (A/F)** — `work/break-fix-1`. Held. Added `packages/utils/test/vercel-routing.test.ts`, which fails if a public route stops resolving to its own function. +- [x] **Env boot fuzz, first half (F)** — `work/break-fix-1`. `CORS_ORIGINS` entries that can never match now stop the boot (trailing slash is forgiven). Rate-limit window done earlier. +- [x] **Token forgery and ownership checks (A)** — `work/break-fix-1`. 13 forgery vectors held. Fixed: a Supabase key-set outage answered 401 (the web app then signs everyone out), now 503; tokens without `exp` were accepted, now refused. New `packages/auth-kit/test/tokens-attacks.test.ts`. Suite: 122 files, 1,783 tests. +- [x] **Job-source fetchers and hostile postings (D)** — `work/break-fix-1`. SSRF, redirect, size and time limits all held. Fixed: a NUL byte in a posting made it unstorable, which also blocked the board's closed-role cleanup; control and bidi characters are now stripped. Suite: 123 files, 1,785 tests. +- [x] **ReDoS audit of `packages/ai` (D)** — `work/break-fix-1`. Found a real one: the resume email pattern was quadratic, so a 200 KB one-word text upload pinned a function for minutes. Fixed by bounding the pattern; new growth test over 37 hostile shapes. Suite: 124 files, 1,901 tests. +- [x] **PDF decompression bombs (D)** — `work/break-fix-1`. A 299 KB PDF cost 3 s and ~670 MB, and the size limit allows ~1 GB inflated. Added a capped pre-inflate of every stream (32 MB each, 128 MB total), 413 on excess. Suite: 124 files, 1,907 tests. +- [x] **Races in applications (C)** — `work/break-fix-1`. Real bugs: status moves could be applied twice, `submitted` published repeatedly, and a rejected application could become `offer`; identical simultaneous creates sometimes got a 409. Fixed with a conditional update and replay handling. Suite: 125 files, 1,912 tests. +- [x] **Forged pagination cursors (B)** — `work/break-fix-1`. A cursor with a bad timestamp or id gave a 500 on six list endpoints; other bad shapes were silently the first page. One shared validator, 400 for anything not issued by the API. Also: six simultaneous account deletions hold. Suite: 126 files, 1,961 tests. +- [x] **Config that starts fine and then breaks (F)** — `work/break-fix-1`. `SUPABASE_URL` with a trailing slash refused every token; `MESSAGING_DRIVER=memory` (the `.env.example` value) would drop events on Vercel; `CRON_SECRET` with a pasted newline could never match. All now normalized or refused at boot. `.env.example` now lists every variable and a test keeps it so. Also: request body / query / path fuzz on applications held (76 cases). Suite: 130 files, 2,070 tests. +- [x] **Frontend headers and static review (E)** — `work/break-fix-1`. The web app sent no security headers; added framing protection, nosniff, referrer and permissions policies, hid `X-Powered-By`; admin tightened to match. Both apps build; headers checked on a running build. Suite: 132 files, 2,080 tests. +- [x] **Deployed bundles, end to end (G)** — `work/break-fix-1`. **Found a launch blocker:** PDF resumes could not be parsed in the deployed profile bundle (pdf.js could not find its worker file), though all source-level tests passed. Fixed with pdf-parse's embedded worker. New test boots all ten committed bundles over HTTP against Postgres. Suite: 133 files, 2,099 tests. +- [x] **Secrets and logging hygiene (F)** — `work/break-fix-1`. History, tree and bundles clean. Log redaction was thin (only exact paths); widened and tested, including log-line forgery. Suite: 134 files, 2,112 tests. +- [x] **Upload filenames and CSV parsing (D)** — `work/break-fix-1`. A NUL byte or a 400+ character filename made an upload 500 after the file was already stored; control and bidi characters were shown back. Names are now sanitized. Roster CSV parsing held on 15 hostile shapes. Suite: 136 files, 2,162 tests. +- [x] **Every route requires sign-in (A)** — `work/break-fix-1`. The bundle test now walks each booted bundle's real route table and checks anonymous and forged-token requests get 401 everywhere except the probes. All pass. PR [#10](https://github.com/NiksheyYadav/autoapply/pull/10) is open (draft, base is the launch branch) and its CI is green. +- [x] **Database outage reads as 503, not 500 (C)** — `work/break-fix-1`. Connection failures and "too many connections" now answer 503 with a fixed message. Over-posting checked: schemas strip unknown keys. Suite: 136 files, 2,178 tests. +- [x] **Main product loop through the deployed bundles (G)** — `work/break-fix-1`. Resume upload, job ingest, matching drain and recommendations work across four bundles and the outbox; the other consumers' drains behave. Suite: 136 files, 2,180 tests. +- [x] **Account deletion and the university roster through the bundles (G)** — `work/break-fix-1`. Found: a deleted account's old token could still upload, leaving a stored file (and a 500). The record now comes first; a deleted account gets 401. Roster import/read/export/funnel and non-member isolation work in the admin bundle. Suite: 136 files, 2,182 tests. +- [x] **Browser sweep of signed-out pages, workflows review, outreach race (E/F/C)** — `work/break-fix-1`. Nothing broke: pages render with the API down, guarded pages redirect, the bad-code and open-redirect URLs stay on the site; workflows keep secrets out of scripts; twenty simultaneous identical drafts make one. +- [x] **Browser-side description cleaner (D/E)** — `work/break-fix-1`. The web app's regex chain was quadratic: a 200,000-character job description of `<` froze the tab for about 25 s for every visitor of that job. Replaced with one linear pass; same output as before on ordinary markup. Suite: 137 files, 2,227 tests. + +## Blocked + +(nothing yet) + +## Needs Nikshey + +- [ ] **Goal line was blank.** The goal in your message was still the placeholder text. I assumed "break the project locally, fix what I find, get ready for the 2026-11-17 launch". Tell me if you want a different focus. +- [ ] **Google Fonts at build time.** `next/font/google` made the admin build fail once in CI. The fix is to ship the font files with the repo (`next/font/local`) or use a system font stack. That changes how the site looks or adds font files, so it is your call. +- [ ] **`CORS_ORIGINS=*` in production.** `docs/16` says never, but nothing enforces it. Enforcing it would stop a service from starting if your Vercel settings use `*` today (for example on previews). Tell me whether to enforce it, or whether `*` is fine on previews and only production should refuse it. +- [ ] **Check your live Vercel settings against four things.** (1) `SUPABASE_URL` should be the project origin; a trailing slash is now forgiven, but `http://` or a stray path is refused at boot. (2) `MESSAGING_DRIVER` is ignored if it is `memory` on Vercel. (3) `CRON_SECRET` must have no spaces inside. (4) `CORS_ORIGINS` entries must be `https://host` only (a trailing slash is forgiven). If any of these is wrong today, the matching service will now stop with a message naming the variable instead of starting and misbehaving. +- [ ] **This repository is public.** `docs/17_break_report.md` (in PR #10) describes weaknesses that stay live on the deployed site until that PR is merged and deployed: mostly availability problems that need a signed-in account (the slow email pattern, PDF bombs, a deleted account's token storing a file). They are not remotely exploitable without an account, and launch is not until 2026-11-17, but I would merge soon, or move that one file out of the public history. I did not rewrite any history. +- [ ] **Pushing branches.** Every push of any branch builds twelve Vercel projects and the free plan allows 100 deployments a day. I will commit locally and push only at clean points, in batches. Say if you want a different rhythm. diff --git a/api/admin/index.js b/api/admin/index.js index c393443..25a48a5 100644 --- a/api/admin/index.js +++ b/api/admin/index.js @@ -45969,11 +45969,47 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } +function pgErrorCode(cause) { + if (typeof cause !== "object" || cause === null) return void 0; + const direct = cause.code; + if (typeof direct === "string") return direct; + return pgErrorCode(cause.cause); +} // packages/utils/src/ids.ts import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; @@ -45995,6 +46031,33 @@ function decodeCursor(cursor) { return null; } } +var PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +function isPostgresTimestamp(text2) { + const match = PG_TIMESTAMP.exec(text2); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number); + const date6 = new Date(Date.UTC(year, month - 1, day)); + const realDate = year >= 1e3 && date6.getUTCFullYear() === year && date6.getUTCMonth() === month - 1 && date6.getUTCDate() === day; + const offsetHours = match[7] === void 0 ? 0 : Number(match[7]); + const offsetMinutes = match[8] === void 0 ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseTimeCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== "string" || typeof id !== "string" || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -46003,39 +46066,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/trace.ts @@ -46052,12 +46137,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -67489,14 +67578,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -77393,18 +77494,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -77428,8 +77621,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -77478,10 +77670,10 @@ function metricsRoute(app2, metrics2) { } // packages/observability/src/timestamps.ts -var PG_TIMESTAMP = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; +var PG_TIMESTAMP2 = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; var TIMESTAMP_KEY = /_at$/; function toIsoTimestamp(value) { - const match = PG_TIMESTAMP.exec(value); + const match = PG_TIMESTAMP2.exec(value); if (!match) return void 0; const [, date6, time4, fraction = "", zone = "Z"] = match; const millis = fraction.slice(0, 3).padEnd(3, "0"); @@ -77631,12 +77823,10 @@ var { students: students2, users: users2, organizationMembers: organizationMembe function escapeLike(term) { return term.replace(/[\\%_]/g, (char2) => `\\${char2}`); } -var PG_TIMESTAMP2 = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(\.\d{1,6})?(Z|[+-]\d{2}(:?\d{2})?)$/; -var cursorSchema = external_exports.object({ createdAt: external_exports.string().regex(PG_TIMESTAMP2), id: uuidSchema }); function decodeRosterCursor(cursor) { - const parsed = cursorSchema.safeParse(decodeCursor(cursor)); - if (!parsed.success) throw new AppError("VALIDATION_ERROR", "Invalid cursor"); - return parsed.data; + const parsed = parseTimeCursor(cursor); + if (parsed === null) throw new AppError("VALIDATION_ERROR", "Invalid cursor"); + return parsed; } function rosterSelect(db2) { return db2.select({ diff --git a/api/analytics/index.js b/api/analytics/index.js index de157a5..492b409 100644 --- a/api/analytics/index.js +++ b/api/analytics/index.js @@ -53881,8 +53881,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -53906,39 +53936,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53962,12 +54014,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75390,14 +75446,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86031,18 +86099,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86066,8 +86226,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86376,7 +86535,7 @@ var analyticsServiceEnvSchema = external_exports.object({ * `Authorization: Bearer $CRON_SECRET` when this variable is set. Unset, the * route answers 503 and never runs a drain. */ - CRON_SECRET: external_exports.string().min(16, "CRON_SECRET must be at least 16 characters").optional() + CRON_SECRET: cronSecretSchema.optional() }); function loadAnalyticsServiceEnv(source = process.env) { const normalized = { ...source, PORT: source.PORT ?? source.ANALYTICS_SERVICE_PORT }; diff --git a/api/applications/index.js b/api/applications/index.js index 7902cf7..1bee9f3 100644 --- a/api/applications/index.js +++ b/api/applications/index.js @@ -53881,8 +53881,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -53910,6 +53940,33 @@ function decodeCursor(cursor) { return null; } } +var PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +function isPostgresTimestamp(text2) { + const match = PG_TIMESTAMP.exec(text2); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number); + const date6 = new Date(Date.UTC(year, month - 1, day)); + const realDate = year >= 1e3 && date6.getUTCFullYear() === year && date6.getUTCMonth() === month - 1 && date6.getUTCDate() === day; + const offsetHours = match[7] === void 0 ? 0 : Number(match[7]); + const offsetMinutes = match[8] === void 0 ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseTimeCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== "string" || typeof id !== "string" || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -53918,39 +53975,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53985,12 +54064,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75416,14 +75499,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86049,18 +86144,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86084,8 +86271,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86171,10 +86357,10 @@ function registerRateLimitedRoutes(app2, options, declareRoutes) { } // packages/observability/src/timestamps.ts -var PG_TIMESTAMP = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; +var PG_TIMESTAMP2 = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; var TIMESTAMP_KEY = /_at$/; function toIsoTimestamp(value) { - const match = PG_TIMESTAMP.exec(value); + const match = PG_TIMESTAMP2.exec(value); if (!match) return void 0; const [, date6, time4, fraction = "", zone = "Z"] = match; const millis = fraction.slice(0, 3).padEnd(3, "0"); @@ -86321,9 +86507,9 @@ async function insertApplication(db2, input2) { return row; } function pageCondition(scopeCondition, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === "string" ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = [scopeCondition]; if (cursorCreatedAt && cursorId) { const tieBreak = or( @@ -86364,8 +86550,13 @@ async function appendEvent(db2, input2) { status: input2.toStatus, lastEventAt: now, submittedAt: input2.toStatus === "submitted" ? now : void 0 - }).where(eq(schema_exports.applications.applicationId, input2.applicationId)).returning(); - if (!updated) throw new Error("appendEvent: application disappeared mid-transaction"); + }).where( + and( + eq(schema_exports.applications.applicationId, input2.applicationId), + eq(schema_exports.applications.status, input2.fromStatus) + ) + ).returning(); + if (!updated) return null; await tx.insert(schema_exports.applicationEvents).values({ applicationId: input2.applicationId, fromStatus: input2.fromStatus, @@ -86426,6 +86617,9 @@ function appendEventRoute(app2, deps) { toStatus: body.to_status, note: body.note ?? null }); + if (updated === null) { + throw new AppError("CONFLICT", "This application was just changed by another request. Reload it and try again."); + } if (body.to_status === "submitted") { await deps.broker.publish( createEvent( @@ -86446,6 +86640,9 @@ function appendEventRoute(app2, deps) { var UNIQUE_VIOLATION = "23505"; var idempotencyKeySchema = external_exports.string().min(8).max(200); var AUTO_MODE_UNAVAILABLE_MESSAGE = 'Mode "auto" cannot be used: automatic submission is not available yet. Use "manual" or "review" instead.'; +function isSameRequest(existing, body) { + return existing.jobId === body.job_id && existing.resumeId === body.resume_id && existing.mode === body.mode; +} function createApplicationRoute(app2, deps) { async function ownerView(row, knownJob) { const job = knownJob === void 0 ? await findJobSummary(deps.db, row.jobId) : knownJob; @@ -86466,8 +86663,7 @@ function createApplicationRoute(app2, deps) { } const existingByKey = await findByUserAndIdempotencyKey(deps.db, actor.user_id, idempotencyKey); if (existingByKey) { - const sameRequest = existingByKey.jobId === body.job_id && existingByKey.resumeId === body.resume_id && existingByKey.mode === body.mode; - if (!sameRequest) { + if (!isSameRequest(existingByKey, body)) { throw new AppError("IDEMPOTENCY_KEY_REUSED", "This idempotency key was already used for a different request"); } reply.status(200).send(await ownerView(existingByKey)); @@ -86483,6 +86679,10 @@ function createApplicationRoute(app2, deps) { } const existingForJob = await findByUserAndJob(deps.db, actor.user_id, body.job_id); if (existingForJob) { + if (existingForJob.idempotencyKey === idempotencyKey && isSameRequest(existingForJob, body)) { + reply.status(200).send(await ownerView(existingForJob)); + return; + } throw new AppError("CONFLICT", "You already have an application for this job", { details: { existing_application_id: existingForJob.applicationId } }); @@ -86516,6 +86716,10 @@ function createApplicationRoute(app2, deps) { return; } const racedByJob = await findByUserAndJob(deps.db, actor.user_id, body.job_id); + if (racedByJob && racedByJob.idempotencyKey === idempotencyKey && isSameRequest(racedByJob, body)) { + reply.status(200).send(await ownerView(racedByJob)); + return; + } if (racedByJob) { throw new AppError("CONFLICT", "You already have an application for this job", { details: { existing_application_id: racedByJob.applicationId } diff --git a/api/auth/index.js b/api/auth/index.js index e99cc3f..a514004 100644 --- a/api/auth/index.js +++ b/api/auth/index.js @@ -45969,11 +45969,47 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } +function pgErrorCode(cause) { + if (typeof cause !== "object" || cause === null) return void 0; + const direct = cause.code; + if (typeof direct === "string") return direct; + return pgErrorCode(cause.cause); +} // packages/utils/src/ids.ts import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; @@ -45988,39 +46024,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/vercel.ts @@ -46034,12 +46092,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -67464,14 +67526,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -77567,18 +77641,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -77602,8 +77768,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -78559,7 +78724,7 @@ var authServiceEnvSchema = external_exports.object({ */ PRIVACY_EXPORT_RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(10), PRIVACY_DELETE_RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(3), - PRIVACY_RATE_LIMIT_WINDOW: external_exports.string().min(1).default("1 hour") + PRIVACY_RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 hour") }); function loadAuthServiceEnv(source = process.env) { const normalized = { ...source, PORT: source.PORT ?? source.AUTH_SERVICE_PORT }; diff --git a/api/jobs/index.js b/api/jobs/index.js index b9dc9ee..e941494 100644 --- a/api/jobs/index.js +++ b/api/jobs/index.js @@ -53881,8 +53881,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -53913,6 +53943,44 @@ function decodeCursor(cursor) { return null; } } +var PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +var MAX_CURSOR_SCORE = 1e9; +function isPostgresTimestamp(text2) { + const match = PG_TIMESTAMP.exec(text2); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number); + const date6 = new Date(Date.UTC(year, month - 1, day)); + const realDate = year >= 1e3 && date6.getUTCFullYear() === year && date6.getUTCMonth() === month - 1 && date6.getUTCDate() === day; + const offsetHours = match[7] === void 0 ? 0 : Number(match[7]); + const offsetMinutes = match[8] === void 0 ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseTimeCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== "string" || typeof id !== "string" || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} +function parseScoreCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const score = decoded?.score; + const id = decoded?.id; + if (typeof score !== "number" || !Number.isFinite(score) || Math.abs(score) > MAX_CURSOR_SCORE || typeof id !== "string" || !UUID.test(id)) { + throw invalidCursor(); + } + return { score, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -53921,39 +53989,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53987,12 +54077,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75418,14 +75512,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86080,18 +86186,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86115,8 +86313,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86202,10 +86399,10 @@ function registerRateLimitedRoutes(app2, options, declareRoutes) { } // packages/observability/src/timestamps.ts -var PG_TIMESTAMP = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; +var PG_TIMESTAMP2 = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; var TIMESTAMP_KEY = /_at$/; function toIsoTimestamp(value) { - const match = PG_TIMESTAMP.exec(value); + const match = PG_TIMESTAMP2.exec(value); if (!match) return void 0; const [, date6, time4, fraction = "", zone = "Z"] = match; const millis = fraction.slice(0, 3).padEnd(3, "0"); @@ -86345,9 +86542,9 @@ async function deactivateUnseenSince(db2, scope, before) { return rows.length; } async function listActive(db2, filters, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === "string" ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = []; if (filters.isActive !== void 0) conditions.push(eq(schema_exports.jobs.isActive, filters.isActive)); if (filters.remoteType) conditions.push(eq(schema_exports.jobs.remoteType, filters.remoteType)); @@ -86803,9 +87000,13 @@ var SourcePayloadError = class extends Error { this.name = "SourcePayloadError"; } }; +var UNSAFE_TEXT_CHARS = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g; +function stripUnsafeChars(text2) { + return text2.replace(UNSAFE_TEXT_CHARS, ""); +} function clampText(value, max) { if (typeof value !== "string") return null; - const trimmed = value.trim(); + const trimmed = stripUnsafeChars(value).trim(); if (trimmed === "") return null; return trimmed.length > max ? trimmed.slice(0, max).trimEnd() : trimmed; } @@ -87578,9 +87779,9 @@ function listJobsRoute(app2, deps) { // services/jobs/src/repo/scores.ts async function listForUser(db2, userId, filters, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorScore = typeof cursorValue?.score === "number" ? cursorValue.score : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseScoreCursor(pagination.cursor); + const cursorScore = cursor?.score ?? null; + const cursorId = cursor?.id ?? null; const conditions = [eq(schema_exports.jobScores.userId, userId), eq(schema_exports.jobs.isActive, true)]; if (filters.remoteType) conditions.push(eq(schema_exports.jobs.remoteType, filters.remoteType)); if (filters.location) conditions.push(ilike(schema_exports.jobs.location, `%${filters.location}%`)); @@ -87768,7 +87969,7 @@ var jobsServiceEnvSchema = external_exports.object({ * ingestion (a scheduler sends `Authorization: Bearer $CRON_SECRET`). Unset, * the route answers 503 and never runs. */ - CRON_SECRET: external_exports.string().min(16, "CRON_SECRET must be at least 16 characters").optional(), + CRON_SECRET: cronSecretSchema.optional(), /** * An email address or URL where the operator of a job board can reach whoever * runs this reader, appended to the User-Agent it sends. Printable ASCII only diff --git a/api/learning/index.js b/api/learning/index.js index f851db4..17e18da 100644 --- a/api/learning/index.js +++ b/api/learning/index.js @@ -53881,11 +53881,47 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } +function pgErrorCode(cause) { + if (typeof cause !== "object" || cause === null) return void 0; + const direct = cause.code; + if (typeof direct === "string") return direct; + return pgErrorCode(cause.cause); +} // packages/utils/src/ids.ts import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; @@ -53900,39 +53936,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53966,12 +54024,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75397,14 +75459,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86107,18 +86181,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86142,8 +86308,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86527,7 +86692,7 @@ var learningServiceEnvSchema = external_exports.object({ * `Authorization: Bearer $CRON_SECRET` when this variable is set. Unset, the * route answers 503 and never runs a drain. */ - CRON_SECRET: external_exports.string().min(16, "CRON_SECRET must be at least 16 characters").optional(), + CRON_SECRET: cronSecretSchema.optional(), /** * Comma-separated `auth.users` ids allowed to read cross-tenant aggregates * (see `requirePlatformAdmin` in @atlas/auth-kit). Empty/unset means nobody. diff --git a/api/matching/index.js b/api/matching/index.js index c887141..9d25950 100644 --- a/api/matching/index.js +++ b/api/matching/index.js @@ -84350,11 +84350,47 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message, { cause: value, exposeMessage: false }); } +function pgErrorCode(cause) { + if (typeof cause !== "object" || cause === null) return void 0; + const direct = cause.code; + if (typeof direct === "string") return direct; + return pgErrorCode(cause.cause); +} // packages/utils/src/ids.ts import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; @@ -84369,39 +84405,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -84435,12 +84493,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -85274,18 +85336,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -85309,8 +85463,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -85586,7 +85739,7 @@ var matchingServiceEnvSchema = external_exports.object({ * `Authorization: Bearer $CRON_SECRET` when this variable is set. Unset, the * route answers 503 and never runs a drain. */ - CRON_SECRET: external_exports.string().min(16, "CRON_SECRET must be at least 16 characters").optional() + CRON_SECRET: cronSecretSchema.optional() }); function loadMatchingServiceEnv(source = process.env) { const normalized = { ...source, PORT: source.PORT ?? source.MATCHING_SERVICE_PORT }; diff --git a/api/outreach/index.js b/api/outreach/index.js index 62003bf..887b503 100644 --- a/api/outreach/index.js +++ b/api/outreach/index.js @@ -53881,8 +53881,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -53910,6 +53940,33 @@ function decodeCursor(cursor) { return null; } } +var PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +function isPostgresTimestamp(text2) { + const match = PG_TIMESTAMP.exec(text2); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number); + const date6 = new Date(Date.UTC(year, month - 1, day)); + const realDate = year >= 1e3 && date6.getUTCFullYear() === year && date6.getUTCMonth() === month - 1 && date6.getUTCDate() === day; + const offsetHours = match[7] === void 0 ? 0 : Number(match[7]); + const offsetMinutes = match[8] === void 0 ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseTimeCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== "string" || typeof id !== "string" || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -53918,39 +53975,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53985,12 +54064,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75416,14 +75499,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86063,18 +86158,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86098,8 +86285,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86185,10 +86371,10 @@ function registerRateLimitedRoutes(app2, options, declareRoutes) { } // packages/observability/src/timestamps.ts -var PG_TIMESTAMP = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; +var PG_TIMESTAMP2 = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; var TIMESTAMP_KEY = /_at$/; function toIsoTimestamp(value) { - const match = PG_TIMESTAMP.exec(value); + const match = PG_TIMESTAMP2.exec(value); if (!match) return void 0; const [, date6, time4, fraction = "", zone = "Z"] = match; const millis = fraction.slice(0, 3).padEnd(3, "0"); @@ -86331,9 +86517,9 @@ async function setFailed(db2, messageId) { return row; } async function listForUser(db2, userId, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === "string" ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = [eq(schema_exports.messages.userId, userId)]; if (cursorCreatedAt && cursorId) { const tieBreak = or( diff --git a/api/profile/index.js b/api/profile/index.js index 5fd821b..4fac783 100644 --- a/api/profile/index.js +++ b/api/profile/index.js @@ -302,8 +302,8 @@ var require_req = __commonJS({ if (req.originalUrl) { _req.url = req.originalUrl; } else { - const path = req.path; - _req.url = typeof path === "string" ? path : req.url ? req.url.path || req.url : void 0; + const path2 = req.path; + _req.url = typeof path2 === "string" ? path2 : req.url ? req.url.path || req.url : void 0; } if (req.query) { _req.query = req.query; @@ -468,14 +468,14 @@ var require_redact = __commonJS({ } return obj2; } - function parsePath(path) { + function parsePath(path2) { const parts = []; let current = ""; let inBrackets = false; let inQuotes = false; let quoteChar = ""; - for (let i = 0; i < path.length; i++) { - const char2 = path[i]; + for (let i = 0; i < path2.length; i++) { + const char2 = path2[i]; if (!inBrackets && char2 === ".") { if (current) { parts.push(current); @@ -606,10 +606,10 @@ var require_redact = __commonJS({ return current; } function redactPaths(obj2, paths, censor, remove = false) { - for (const path of paths) { - const parts = parsePath(path); + for (const path2 of paths) { + const parts = parsePath(path2); if (parts.includes("*")) { - redactWildcardPath(obj2, parts, censor, path, remove); + redactWildcardPath(obj2, parts, censor, path2, remove); } else { if (remove) { removeKey(obj2, parts); @@ -694,8 +694,8 @@ var require_redact = __commonJS({ } } else { if (afterWildcard.includes("*")) { - const wrappedCensor = typeof censor === "function" ? (value, path) => { - const fullPath = [...pathArray.slice(0, pathLength), ...path]; + const wrappedCensor = typeof censor === "function" ? (value, path2) => { + const fullPath = [...pathArray.slice(0, pathLength), ...path2]; return censor(value, fullPath); } : censor; redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove); @@ -730,8 +730,8 @@ var require_redact = __commonJS({ return null; } const pathStructure = /* @__PURE__ */ new Map(); - for (const path of pathsToClone) { - const parts = parsePath(path); + for (const path2 of pathsToClone) { + const parts = parsePath(path2); let current = pathStructure; for (let i = 0; i < parts.length; i++) { const part = parts[i]; @@ -783,24 +783,24 @@ var require_redact = __commonJS({ } return cloneSelectively(obj2, pathStructure); } - function validatePath(path) { - if (typeof path !== "string") { + function validatePath(path2) { + if (typeof path2 !== "string") { throw new Error("Paths must be (non-empty) strings"); } - if (path === "") { + if (path2 === "") { throw new Error("Invalid redaction path ()"); } - if (path.includes("..")) { - throw new Error(`Invalid redaction path (${path})`); + if (path2.includes("..")) { + throw new Error(`Invalid redaction path (${path2})`); } - if (path.includes(",")) { - throw new Error(`Invalid redaction path (${path})`); + if (path2.includes(",")) { + throw new Error(`Invalid redaction path (${path2})`); } let bracketCount = 0; let inQuotes = false; let quoteChar = ""; - for (let i = 0; i < path.length; i++) { - const char2 = path[i]; + for (let i = 0; i < path2.length; i++) { + const char2 = path2[i]; if ((char2 === '"' || char2 === "'") && bracketCount > 0) { if (!inQuotes) { inQuotes = true; @@ -814,20 +814,20 @@ var require_redact = __commonJS({ } else if (char2 === "]" && !inQuotes) { bracketCount--; if (bracketCount < 0) { - throw new Error(`Invalid redaction path (${path})`); + throw new Error(`Invalid redaction path (${path2})`); } } } if (bracketCount !== 0) { - throw new Error(`Invalid redaction path (${path})`); + throw new Error(`Invalid redaction path (${path2})`); } } function validatePaths(paths) { if (!Array.isArray(paths)) { throw new TypeError("paths must be an array"); } - for (const path of paths) { - validatePath(path); + for (const path2 of paths) { + validatePath(path2); } } function slowRedact(options = {}) { @@ -995,8 +995,8 @@ var require_redaction = __commonJS({ if (shape[k] === null) { o[k] = (value) => topCensor(value, [k]); } else { - const wrappedCensor = typeof censor === "function" ? (value, path) => { - return censor(value, [k, ...path]); + const wrappedCensor = typeof censor === "function" ? (value, path2) => { + return censor(value, [k, ...path2]); } : censor; o[k] = Redact({ paths: shape[k], @@ -1217,9 +1217,9 @@ var require_sonic_boom = __commonJS({ var fs2 = __require("fs"); var EventEmitter = __require("events"); var inherits2 = __require("util").inherits; - var path = __require("path"); + var path2 = __require("path"); var sleep = require_atomic_sleep(); - var assert3 = __require("assert"); + var assert4 = __require("assert"); var BUSY_WRITE_TIMEOUT = 100; var kEmptyBuffer = Buffer.allocUnsafe(0); var MAX_WRITE = 16 * 1024; @@ -1271,7 +1271,7 @@ var require_sonic_boom = __commonJS({ const mode = sonic.mode; if (sonic.sync) { try { - if (sonic.mkdir) fs2.mkdirSync(path.dirname(file2), { recursive: true }); + if (sonic.mkdir) fs2.mkdirSync(path2.dirname(file2), { recursive: true }); const fd = fs2.openSync(file2, flags, mode); fileOpened(null, fd); } catch (err) { @@ -1279,7 +1279,7 @@ var require_sonic_boom = __commonJS({ throw err; } } else if (sonic.mkdir) { - fs2.mkdir(path.dirname(file2), { recursive: true }, (err) => { + fs2.mkdir(path2.dirname(file2), { recursive: true }, (err) => { if (err) return fileOpened(err); fs2.open(file2, flags, mode, fileOpened); }); @@ -1768,7 +1768,7 @@ var require_sonic_boom = __commonJS({ sonic.destroyed = true; sonic._bufs = []; sonic._lens = []; - assert3(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`); + assert4(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`); try { fs2.fsync(sonic.fd, closeWrapped); } catch { @@ -2037,7 +2037,7 @@ var require_thread_stream = __commonJS({ SEQ_INDEX } = require_indexes(); var buffer2 = __require("buffer"); - var assert3 = __require("assert"); + var assert4 = __require("assert"); var kImpl = Symbol("kImpl"); var MAX_STRING = buffer2.constants.MAX_STRING_LENGTH; function noop4() { @@ -2103,7 +2103,7 @@ var require_thread_stream = __commonJS({ return worker; } function drain(stream) { - assert3(!stream[kImpl].sync); + assert4(!stream[kImpl].sync); if (stream[kImpl].needDrain) { stream[kImpl].needDrain = false; stream.emit("drain"); @@ -2548,7 +2548,7 @@ var require_transport = __commonJS({ var { existsSync } = __require("node:fs"); var getCallers = require_caller(); var { join: join2, isAbsolute, sep: sep2 } = __require("node:path"); - var { fileURLToPath } = __require("node:url"); + var { fileURLToPath: fileURLToPath2 } = __require("node:url"); var sleep = require_atomic_sleep(); var onExit = require_on_exit_leak_free(); var ThreadStream = require_thread_stream(); @@ -2607,21 +2607,21 @@ var require_transport = __commonJS({ return changed ? sanitized.join(" ") : nodeOptions; } function shouldDropPreload(value) { - const unquoted = stripQuotes(value); + const unquoted = stripQuotes2(value); if (!unquoted) { return false; } - let path = unquoted; - if (path.startsWith("file://")) { + let path2 = unquoted; + if (path2.startsWith("file://")) { try { - path = fileURLToPath(path); + path2 = fileURLToPath2(path2); } catch { return false; } } - return isAbsolute(path) && !existsSync(path); + return isAbsolute(path2) && !existsSync(path2); } - function stripQuotes(value) { + function stripQuotes2(value) { const first2 = value[0]; const last2 = value[value.length - 1]; if (first2 === '"' && last2 === '"' || first2 === "'" && last2 === "'") { @@ -4619,7 +4619,7 @@ var require_url_parse = __commonJS({ ["?", "query"], // Extract from the back. function sanitize(address, url2) { - return isSpecial(url2.protocol) ? address.replace(/\\/g, "/") : address; + return isSpecial2(url2.protocol) ? address.replace(/\\/g, "/") : address; }, ["/", "pathname"], // Extract from the back. @@ -4658,7 +4658,7 @@ var require_url_parse = __commonJS({ } return finaldestination; } - function isSpecial(scheme) { + function isSpecial2(scheme) { return scheme === "file:" || scheme === "ftp:" || scheme === "http:" || scheme === "https:" || scheme === "ws:" || scheme === "wss:"; } function extractProtocol(address, location) { @@ -4691,40 +4691,40 @@ var require_url_parse = __commonJS({ if (slashesCount >= 2) { rest2 = rest2.slice(2); } - } else if (isSpecial(protocol)) { + } else if (isSpecial2(protocol)) { rest2 = match[4]; } else if (protocol) { if (forwardSlashes) { rest2 = rest2.slice(2); } - } else if (slashesCount >= 2 && isSpecial(location.protocol)) { + } else if (slashesCount >= 2 && isSpecial2(location.protocol)) { rest2 = match[4]; } return { protocol, - slashes: forwardSlashes || isSpecial(protocol), + slashes: forwardSlashes || isSpecial2(protocol), slashesCount, rest: rest2 }; } function resolve2(relative, base) { if (relative === "") return base; - var path = (base || "/").split("/").slice(0, -1).concat(relative.split("/")), i = path.length, last2 = path[i - 1], unshift = false, up = 0; + var path2 = (base || "/").split("/").slice(0, -1).concat(relative.split("/")), i = path2.length, last2 = path2[i - 1], unshift = false, up = 0; while (i--) { - if (path[i] === ".") { - path.splice(i, 1); - } else if (path[i] === "..") { - path.splice(i, 1); + if (path2[i] === ".") { + path2.splice(i, 1); + } else if (path2[i] === "..") { + path2.splice(i, 1); up++; } else if (up) { if (i === 0) unshift = true; - path.splice(i, 1); + path2.splice(i, 1); up--; } } - if (unshift) path.unshift(""); - if (last2 === "." || last2 === "..") path.push(""); - return path.join("/"); + if (unshift) path2.unshift(""); + if (last2 === "." || last2 === "..") path2.push(""); + return path2.join("/"); } function Url(address, location, parser) { address = trimLeft(address); @@ -4744,7 +4744,7 @@ var require_url_parse = __commonJS({ url2.slashes = extracted.slashes || relative && location.slashes; url2.protocol = extracted.protocol || location.protocol || ""; address = extracted.rest; - if (extracted.protocol === "file:" && (extracted.slashesCount !== 2 || windowsDriveLetter.test(address)) || !extracted.slashes && (extracted.protocol || extracted.slashesCount < 2 || !isSpecial(url2.protocol))) { + if (extracted.protocol === "file:" && (extracted.slashesCount !== 2 || windowsDriveLetter.test(address)) || !extracted.slashes && (extracted.protocol || extracted.slashesCount < 2 || !isSpecial2(url2.protocol))) { instructions[3] = [/(.*)/, "pathname"]; } for (; i < instructions.length; i++) { @@ -4779,7 +4779,7 @@ var require_url_parse = __commonJS({ if (relative && location.slashes && url2.pathname.charAt(0) !== "/" && (url2.pathname !== "" || location.pathname !== "")) { url2.pathname = resolve2(url2.pathname, location.pathname); } - if (url2.pathname.charAt(0) !== "/" && isSpecial(url2.protocol)) { + if (url2.pathname.charAt(0) !== "/" && isSpecial2(url2.protocol)) { url2.pathname = "/" + url2.pathname; } if (!required2(url2.port, url2.protocol)) { @@ -4799,7 +4799,7 @@ var require_url_parse = __commonJS({ } url2.auth = url2.password ? url2.username + ":" + url2.password : url2.username; } - url2.origin = url2.protocol !== "file:" && isSpecial(url2.protocol) && url2.host ? url2.protocol + "//" + url2.host : "null"; + url2.origin = url2.protocol !== "file:" && isSpecial2(url2.protocol) && url2.host ? url2.protocol + "//" + url2.host : "null"; url2.href = url2.toString(); } function set2(part, value, fn) { @@ -4869,7 +4869,7 @@ var require_url_parse = __commonJS({ if (ins[4]) url2[ins[1]] = url2[ins[1]].toLowerCase(); } url2.auth = url2.password ? url2.username + ":" + url2.password : url2.username; - url2.origin = url2.protocol !== "file:" && isSpecial(url2.protocol) && url2.host ? url2.protocol + "//" + url2.host : "null"; + url2.origin = url2.protocol !== "file:" && isSpecial2(url2.protocol) && url2.host ? url2.protocol + "//" + url2.host : "null"; url2.href = url2.toString(); return url2; } @@ -4877,7 +4877,7 @@ var require_url_parse = __commonJS({ if (!stringify2 || "function" !== typeof stringify2) stringify2 = qs.stringify; var query, url2 = this, host = url2.host, protocol = url2.protocol; if (protocol && protocol.charAt(protocol.length - 1) !== ":") protocol += ":"; - var result2 = protocol + (url2.protocol && url2.slashes || isSpecial(url2.protocol) ? "//" : ""); + var result2 = protocol + (url2.protocol && url2.slashes || isSpecial2(url2.protocol) ? "//" : ""); if (url2.username) { result2 += url2.username; if (url2.password) result2 += ":" + url2.password; @@ -4885,7 +4885,7 @@ var require_url_parse = __commonJS({ } else if (url2.password) { result2 += ":" + url2.password; result2 += "@"; - } else if (url2.protocol !== "file:" && isSpecial(url2.protocol) && !host && url2.pathname !== "/") { + } else if (url2.protocol !== "file:" && isSpecial2(url2.protocol) && !host && url2.pathname !== "/") { result2 += "@"; } if (host[host.length - 1] === ":" || port.test(url2.hostname) && !url2.port) { @@ -10325,7 +10325,7 @@ var require_frame = __commonJS({ var require_mux = __commonJS({ "node_modules/.pnpm/amqplib@0.10.9/node_modules/amqplib/lib/mux.js"(exports2, module2) { "use strict"; - var assert3 = __require("assert"); + var assert4 = __require("assert"); var schedule = typeof setImmediate === "function" ? setImmediate : process.nextTick; var Mux = class { constructor(downstream) { @@ -10365,10 +10365,10 @@ var require_mux = __commonJS({ } roundrobin(this.newStreams); if (accepting) { - assert3.equal(0, this.newStreams.length); + assert4.equal(0, this.newStreams.length); roundrobin(this.oldStreams); } else { - assert3(this.newStreams.length > 0, "Expect some new streams to remain"); + assert4(this.newStreams.length > 0, "Expect some new streams to remain"); Array.prototype.push.apply(this.oldStreams, this.newStreams); this.newStreams = []; } @@ -10485,10 +10485,10 @@ var require_format = __commonJS({ frame.size ); } else { - var info2 = defs.info(frame.id); + var info3 = defs.info(frame.id); return format( "<%s channel:%d%s>", - info2.name, + info3.name, frame.channel, showFields ? " " + JSON.stringify(frame.fields, void 0, 2) : "" ); @@ -10929,23 +10929,23 @@ var require_connection = __commonJS({ } _closeChannels(capturedStack) { for (var i = 1; i < this.channels.length; i++) { - var ch = this.channels[i]; - if (ch !== null) { - ch.channel.toClosed(capturedStack); + var ch2 = this.channels[i]; + if (ch2 !== null) { + ch2.channel.toClosed(capturedStack); } } } // A close has been confirmed. Cease all communication. toClosed(capturedStack, maybeErr) { this._closeChannels(capturedStack); - var info2 = fmt( + var info3 = fmt( "Connection closed (%s)", maybeErr ? maybeErr.toString() : "by client" ); - invalidateSend(this, info2, capturedStack); - this.accept = invalidOp(info2, capturedStack); + invalidateSend(this, info3, capturedStack); + this.accept = invalidOp(info3, capturedStack); this.close = function(cb2) { - cb2 && cb2(new IllegalOperationError(info2, capturedStack)); + cb2 && cb2(new IllegalOperationError(info3, capturedStack)); }; if (this.heartbeater) this.heartbeater.clear(); @@ -11455,7 +11455,7 @@ var require_channel = __commonJS({ var closeMsg = require_format().closeMessage; var inspect = require_format().inspect; var methodName = require_format().methodName; - var assert3 = __require("assert"); + var assert4 = __require("assert"); var EventEmitter = __require("events"); var fmt = __require("util").format; var IllegalOperationError = require_error().IllegalOperationError; @@ -11512,7 +11512,7 @@ var require_channel = __commonJS({ // and in `accept`. sendOrEnqueue(method, fields, reply) { if (!this.reply) { - assert3(this.pending.length === 0); + assert4(this.pending.length === 0); this.reply = reply; this.sendImmediately(method, fields); } else { @@ -11760,8 +11760,8 @@ var require_channel = __commonJS({ throw new IllegalOperationError(msg, stack); }; } - function invalidateSend(ch, msg, stack) { - ch.sendImmediately = ch.sendOrEnqueue = ch.sendMessage = invalidOp(msg, stack); + function invalidateSend(ch2, msg, stack) { + ch2.sendImmediately = ch2.sendOrEnqueue = ch2.sendMessage = invalidOp(msg, stack); } function acceptDeliveryOrReturn(f) { var event; @@ -12181,8 +12181,8 @@ var require_channel_model = __commonJS({ } // Do the remarkably simple channel open handshake async open() { - const ch = await this.allocate.bind(this)(); - return ch.rpc( + const ch2 = await this.allocate.bind(this)(); + return ch2.rpc( defs.ChannelOpen, { outOfBand: "" }, defs.ChannelOpenOk @@ -13568,17 +13568,17 @@ var require_sbmh = __commonJS({ const needleLastCharIndex = needleLength - 1; const needleLastChar = needle[needleLastCharIndex]; let pos = -this._lookbehind_size; - let ch; + let ch2; if (pos < 0) { while (pos < 0 && pos <= len - needleLength) { - ch = data[pos + needleLastCharIndex]; - if (ch === needleLastChar && this._sbmh_memcmp(data, pos, needleLastCharIndex)) { + ch2 = data[pos + needleLastCharIndex]; + if (ch2 === needleLastChar && this._sbmh_memcmp(data, pos, needleLastCharIndex)) { this._lookbehind_size = 0; ++this.matches; this.emit("info", true); return this._bufpos = pos + needleLength; } - pos += this._occ[ch]; + pos += this._occ[ch2]; } while (pos < 0 && !this._sbmh_memcmp(data, pos, len - pos)) { ++pos; @@ -14101,7 +14101,7 @@ var require_decodeText = __commonJS({ } } } - function isAscii(data) { + function isAscii2(data) { for (var i = 0, len = data.length; i < len; ++i) { if (data.charCodeAt(i) > 127) { return false; @@ -14115,7 +14115,7 @@ var require_decodeText = __commonJS({ return ""; } if (typeof data === "string") { - if (isAscii(data)) { + if (isAscii2(data)) { return data; } data = Buffer.from(data, sourceEncoding); @@ -14827,20 +14827,20 @@ var require_parseParams = __commonJS({ var require_basename = __commonJS({ "node_modules/.pnpm/@fastify+busboy@3.2.2/node_modules/@fastify/busboy/lib/utils/basename.js"(exports2, module2) { "use strict"; - module2.exports = function basename(path) { - if (typeof path !== "string") { + module2.exports = function basename(path2) { + if (typeof path2 !== "string") { return ""; } - for (var i = path.length - 1; i >= 0; --i) { - switch (path.charCodeAt(i)) { + for (var i = path2.length - 1; i >= 0; --i) { + switch (path2.charCodeAt(i)) { case 47: // '/' case 92: - path = path.slice(i + 1); - return path === ".." || path === "." ? "" : path; + path2 = path2.slice(i + 1); + return path2 === ".." || path2 === "." ? "" : path2; } } - return path === ".." || path === "." ? "" : path; + return path2 === ".." || path2 === "." ? "" : path2; }; } }); @@ -15897,7 +15897,7 @@ var require_error2 = __commonJS({ return `${this.name} [${this.code}]: ${this.message}`; } var FastifyGenericErrorSymbol = Symbol.for("fastify-error-generic"); - function createError(code, message2, statusCode = 500, Base = Error, captureStackTrace2 = createError.captureStackTrace) { + function createError(code, message2, statusCode = 500, Base2 = Error, captureStackTrace2 = createError.captureStackTrace) { const shouldCreateFastifyGenericError = code === FastifyGenericErrorSymbol; if (shouldCreateFastifyGenericError) { code = "FST_ERR"; @@ -15921,7 +15921,7 @@ var require_error2 = __commonJS({ this.message = format(message2, ...args); Error.stackTraceLimit && captureStackTrace2 && Error.captureStackTrace(this, FastifyError); } - FastifyError.prototype = Object.create(Base.prototype, { + FastifyError.prototype = Object.create(Base2.prototype, { constructor: { value: FastifyError, enumerable: false, @@ -16249,7 +16249,7 @@ var require_multipart2 = __commonJS({ var fp = require_fastify_plugin(); var { createWriteStream } = __require("node:fs"); var { unlink } = __require("node:fs/promises"); - var path = __require("node:path"); + var path2 = __require("node:path"); var { generateId } = require_generateId(); var createError = require_error2(); var streamToNull = require_stream_consumer(); @@ -16416,7 +16416,7 @@ var require_multipart2 = __commonJS({ this.log.debug("starting multipart parsing"); let values3 = []; let pendingHandler = null; - const ch = (val) => { + const ch2 = (val) => { if (pendingHandler) { pendingHandler(val); pendingHandler = null; @@ -16518,7 +16518,7 @@ var require_multipart2 = __commonJS({ } else { body[name] = [body[name], value]; } - ch(value); + ch2(value); } function onFile(name, file2, filename, encoding, mimetype) { if (name in Object.prototype) { @@ -16584,7 +16584,7 @@ var require_multipart2 = __commonJS({ body[name] = [body[name], value]; } currentFile = file2; - ch(value); + ch2(value); } function onError(err) { lastError = err; @@ -16600,7 +16600,7 @@ var require_multipart2 = __commonJS({ currentFile.destroy(); currentFile = null; } - ch(err || lastError || null); + ch2(err || lastError || null); } return parts; } @@ -16627,7 +16627,7 @@ var require_multipart2 = __commonJS({ if (!part.file) { continue; } - const filepath = path.join(tmpdir2, generateId() + path.extname(part.filename || "file" + i++)); + const filepath = path2.join(tmpdir2, generateId() + path2.extname(part.filename || "file" + i++)); target = createWriteStream(filepath); this.tmpUploads.push(filepath); await pump(part.file, target); @@ -17723,7 +17723,7 @@ var require_ipv6 = __commonJS({ var address_error_1 = require_address_error(); var common_1 = require_common(); var isCorrect6 = common.isCorrect(constants6.BITS); - function assert3(condition) { + function assert4(condition) { if (!condition) { throw new Error("Assertion failed."); } @@ -18916,8 +18916,8 @@ var require_ipv6 = __commonJS({ if (this.elidedGroups === 0) { return helpers.simpleGroup(this.addressMinusSuffix).join(":"); } - assert3(typeof this.elidedGroups === "number"); - assert3(typeof this.elisionBegin === "number"); + assert4(typeof this.elidedGroups === "number"); + assert4(typeof this.elisionBegin === "number"); const output2 = []; const [left, right] = this.addressMinusSuffix.split("::"); if (left.length) { @@ -18936,7 +18936,7 @@ var require_ipv6 = __commonJS({ output2.push(""); } if (this.is4()) { - assert3(this.address4 instanceof ipv4_1.Address4); + assert4(this.address4 instanceof ipv4_1.Address4); output2.pop(); output2.push(this.address4.groupForV6()); } @@ -18962,7 +18962,7 @@ var require_ipv6 = __commonJS({ if (halves[0].length) { output2.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(":"))); } - assert3(typeof address6.elidedGroups === "number"); + assert4(typeof address6.elidedGroups === "number"); output2.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0)); if (halves[1].length) { output2.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(":"))); @@ -27541,7 +27541,7 @@ var require_request = __commonJS({ querystring: kSchemaQuerystring, query: kSchemaQuerystring }; - function Request(id, params, req, query, log, context2) { + function Request2(id, params, req, query, log, context2) { this.id = id; this[kRouteContext] = context2; this.params = params; @@ -27550,8 +27550,8 @@ var require_request = __commonJS({ this.log = log; this.body = void 0; } - Request.props = []; - Request.instanceProperties = /* @__PURE__ */ new Set(["id", "params", "raw", "query", "log", "body"]); + Request2.props = []; + Request2.instanceProperties = /* @__PURE__ */ new Set(["id", "params", "raw", "query", "log", "body"]); function getTrustProxyFn(tp) { if (typeof tp === "function") { return tp; @@ -27648,7 +27648,7 @@ var require_request = __commonJS({ throw new FST_ERR_DEC_UNDECLARED(name, "request"); } } - Object.defineProperties(Request.prototype, { + Object.defineProperties(Request2.prototype, { server: { get() { return this[kRouteContext].server; @@ -27845,7 +27845,7 @@ var require_request = __commonJS({ } } }); - module2.exports = Request; + module2.exports = Request2; module2.exports.buildRequest = buildRequest; } }); @@ -27974,8 +27974,8 @@ var require_content_type_parser = __commonJS({ function ContentTypeParser(bodyLimit, onProtoPoisoning, onConstructorPoisoning) { this[kDefaultJsonParse] = getDefaultJsonParser(onProtoPoisoning, onConstructorPoisoning); this.customParsers = /* @__PURE__ */ new Map(); - this.customParsers.set("application/json", new Parser(true, false, bodyLimit, this[kDefaultJsonParse])); - this.customParsers.set("text/plain", new Parser(true, false, bodyLimit, defaultPlainTextParser)); + this.customParsers.set("application/json", new Parser2(true, false, bodyLimit, this[kDefaultJsonParse])); + this.customParsers.set("text/plain", new Parser2(true, false, bodyLimit, defaultPlainTextParser)); this.parserList = ["application/json", "text/plain"]; this.parserRegExpList = []; this.cache = new Fifo(100); @@ -27999,7 +27999,7 @@ var require_content_type_parser = __commonJS({ throw new FST_ERR_CTP_INVALID_PARSE_TYPE(opts.parseAs); } } - const parser = new Parser( + const parser = new Parser2( opts.parseAs === "string", opts.parseAs === "buffer", opts.bodyLimit, @@ -28218,7 +28218,7 @@ var require_content_type_parser = __commonJS({ function defaultPlainTextParser(req, body, done) { done(null, body); } - function Parser(asString, asBuffer, bodyLimit, fn) { + function Parser2(asString, asBuffer, bodyLimit, fn) { this.asString = asString; this.asBuffer = asBuffer; this.bodyLimit = bodyLimit; @@ -28301,7 +28301,7 @@ var require_code = __commonJS({ }; exports2._CodeOrName = _CodeOrName; exports2.IDENTIFIER = /^[a-z$_][a-z$_0-9]*$/i; - var Name2 = class extends _CodeOrName { + var Name3 = class extends _CodeOrName { constructor(s) { super(); if (!exports2.IDENTIFIER.test(s)) @@ -28318,7 +28318,7 @@ var require_code = __commonJS({ return { [this.str]: 1 }; } }; - exports2.Name = Name2; + exports2.Name = Name3; var _Code = class extends _CodeOrName { constructor(code) { super(); @@ -28340,7 +28340,7 @@ var require_code = __commonJS({ get names() { var _a3; return (_a3 = this._names) !== null && _a3 !== void 0 ? _a3 : this._names = this._items.reduce((names, c) => { - if (c instanceof Name2) + if (c instanceof Name3) names[c.str] = (names[c.str] || 0) + 1; return names; }, {}); @@ -28374,7 +28374,7 @@ var require_code = __commonJS({ function addCodeArg(code, arg) { if (arg instanceof _Code) code.push(...arg._items); - else if (arg instanceof Name2) + else if (arg instanceof Name3) code.push(arg); else code.push(interpolate(arg)); @@ -28400,7 +28400,7 @@ var require_code = __commonJS({ if (a === '""') return b2; if (typeof a == "string") { - if (b2 instanceof Name2 || a[a.length - 1] !== '"') + if (b2 instanceof Name3 || a[a.length - 1] !== '"') return; if (typeof b2 != "string") return `${a.slice(0, -1)}${b2}"`; @@ -28408,7 +28408,7 @@ var require_code = __commonJS({ return a.slice(0, -1) + b2.slice(1); return; } - if (typeof b2 == "string" && b2[0] === '"' && !(a instanceof Name2)) + if (typeof b2 == "string" && b2[0] === '"' && !(a instanceof Name3)) return `"${a}${b2.slice(1)}`; return; } @@ -28719,7 +28719,7 @@ var require_codegen = __commonJS({ return `${this.label}:` + _n; } }; - var Break = class extends Node2 { + var Break2 = class extends Node2 { constructor(label) { super(); this.label = label; @@ -28804,7 +28804,7 @@ var require_codegen = __commonJS({ return "{" + opts._n + super.render(opts) + "}" + opts._n; } }; - var Root = class extends ParentNode { + var Root2 = class extends ParentNode { }; var Else = class extends BlockNode { }; @@ -28993,7 +28993,7 @@ var require_codegen = __commonJS({ this.opts = { ...opts, _n: opts.lines ? "\n" : "" }; this._extScope = extScope; this._scope = new scope_1.Scope({ parent: extScope }); - this._nodes = [new Root()]; + this._nodes = [new Root2()]; } toString() { return this._root.render(this.opts); @@ -29144,7 +29144,7 @@ var require_codegen = __commonJS({ } // `break` statement break(label) { - return this._leafNode(new Break(label)); + return this._leafNode(new Break2(label)); } // `return` statement return(value) { @@ -29365,8 +29365,8 @@ var require_util = __commonJS({ return false; } exports2.schemaHasRulesButRef = schemaHasRulesButRef; - function schemaRefOrVal({ topSchemaRef, schemaPath }, schema, keyword, $data) { - if (!$data) { + function schemaRefOrVal({ topSchemaRef, schemaPath }, schema, keyword, $data2) { + if (!$data2) { if (typeof schema == "number" || typeof schema == "boolean") return schema; if (typeof schema == "string") @@ -29452,14 +29452,14 @@ var require_util = __commonJS({ }); } exports2.useFunc = useFunc; - var Type; - (function(Type2) { - Type2[Type2["Num"] = 0] = "Num"; - Type2[Type2["Str"] = 1] = "Str"; - })(Type || (exports2.Type = Type = {})); + var Type2; + (function(Type3) { + Type3[Type3["Num"] = 0] = "Num"; + Type3[Type3["Str"] = 1] = "Str"; + })(Type2 || (exports2.Type = Type2 = {})); function getErrorPath(dataProp, dataPropType, jsPropertySyntax) { if (dataProp instanceof codegen_1.Name) { - const isNumber = dataPropType === Type.Num; + const isNumber = dataPropType === Type2.Num; return jsPropertySyntax ? isNumber ? (0, codegen_1._)`"[" + ${dataProp} + "]"` : (0, codegen_1._)`"['" + ${dataProp} + "']"` : isNumber ? (0, codegen_1._)`"/" + ${dataProp}` : (0, codegen_1._)`"/" + ${dataProp}.replace(/~/g, "~0").replace(/\\//g, "~1")`; } return jsPropertySyntax ? (0, codegen_1.getProperty)(dataProp).toString() : "/" + escapeJsonPointer(dataProp); @@ -29754,43 +29754,43 @@ var require_dataType = __commonJS({ var errors_1 = require_errors3(); var codegen_1 = require_codegen(); var util_1 = require_util(); - var DataType; - (function(DataType2) { - DataType2[DataType2["Correct"] = 0] = "Correct"; - DataType2[DataType2["Wrong"] = 1] = "Wrong"; - })(DataType || (exports2.DataType = DataType = {})); + var DataType2; + (function(DataType3) { + DataType3[DataType3["Correct"] = 0] = "Correct"; + DataType3[DataType3["Wrong"] = 1] = "Wrong"; + })(DataType2 || (exports2.DataType = DataType2 = {})); function getSchemaTypes(schema) { - const types2 = getJSONTypes(schema.type); - const hasNull = types2.includes("null"); + const types3 = getJSONTypes(schema.type); + const hasNull = types3.includes("null"); if (hasNull) { if (schema.nullable === false) throw new Error("type: null contradicts nullable: false"); } else { - if (!types2.length && schema.nullable !== void 0) { + if (!types3.length && schema.nullable !== void 0) { throw new Error('"nullable" cannot be used without "type"'); } if (schema.nullable === true) - types2.push("null"); + types3.push("null"); } - return types2; + return types3; } exports2.getSchemaTypes = getSchemaTypes; function getJSONTypes(ts) { - const types2 = Array.isArray(ts) ? ts : ts ? [ts] : []; - if (types2.every(rules_1.isJSONType)) - return types2; - throw new Error("type must be JSONType or JSONType[]: " + types2.join(",")); + const types3 = Array.isArray(ts) ? ts : ts ? [ts] : []; + if (types3.every(rules_1.isJSONType)) + return types3; + throw new Error("type must be JSONType or JSONType[]: " + types3.join(",")); } exports2.getJSONTypes = getJSONTypes; - function coerceAndCheckDataType(it, types2) { + function coerceAndCheckDataType(it, types3) { const { gen, data, opts } = it; - const coerceTo = coerceToTypes(types2, opts.coerceTypes); - const checkTypes = types2.length > 0 && !(coerceTo.length === 0 && types2.length === 1 && (0, applicability_1.schemaHasRulesForType)(it, types2[0])); + const coerceTo = coerceToTypes(types3, opts.coerceTypes); + const checkTypes = types3.length > 0 && !(coerceTo.length === 0 && types3.length === 1 && (0, applicability_1.schemaHasRulesForType)(it, types3[0])); if (checkTypes) { - const wrongType = checkDataTypes(types2, data, opts.strictNumbers, DataType.Wrong); + const wrongType = checkDataTypes(types3, data, opts.strictNumbers, DataType2.Wrong); gen.if(wrongType, () => { if (coerceTo.length) - coerceData(it, types2, coerceTo); + coerceData(it, types3, coerceTo); else reportTypeError(it); }); @@ -29799,15 +29799,15 @@ var require_dataType = __commonJS({ } exports2.coerceAndCheckDataType = coerceAndCheckDataType; var COERCIBLE = /* @__PURE__ */ new Set(["string", "number", "integer", "boolean", "null"]); - function coerceToTypes(types2, coerceTypes) { - return coerceTypes ? types2.filter((t) => COERCIBLE.has(t) || coerceTypes === "array" && t === "array") : []; + function coerceToTypes(types3, coerceTypes) { + return coerceTypes ? types3.filter((t) => COERCIBLE.has(t) || coerceTypes === "array" && t === "array") : []; } - function coerceData(it, types2, coerceTo) { + function coerceData(it, types3, coerceTo) { const { gen, data, opts } = it; const dataType = gen.let("dataType", (0, codegen_1._)`typeof ${data}`); const coerced = gen.let("coerced", (0, codegen_1._)`undefined`); if (opts.coerceTypes === "array") { - gen.if((0, codegen_1._)`${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen.assign(data, (0, codegen_1._)`${data}[0]`).assign(dataType, (0, codegen_1._)`typeof ${data}`).if(checkDataTypes(types2, data, opts.strictNumbers), () => gen.assign(coerced, data))); + gen.if((0, codegen_1._)`${dataType} == 'object' && Array.isArray(${data}) && ${data}.length == 1`, () => gen.assign(data, (0, codegen_1._)`${data}[0]`).assign(dataType, (0, codegen_1._)`typeof ${data}`).if(checkDataTypes(types3, data, opts.strictNumbers), () => gen.assign(coerced, data))); } gen.if((0, codegen_1._)`${coerced} !== undefined`); for (const t of coerceTo) { @@ -29851,8 +29851,8 @@ var require_dataType = __commonJS({ function assignParentData({ gen, parentData, parentDataProperty }, expr) { gen.if((0, codegen_1._)`${parentData} !== undefined`, () => gen.assign((0, codegen_1._)`${parentData}[${parentDataProperty}]`, expr)); } - function checkDataType(dataType, data, strictNums, correct = DataType.Correct) { - const EQ = correct === DataType.Correct ? codegen_1.operators.EQ : codegen_1.operators.NEQ; + function checkDataType(dataType, data, strictNums, correct = DataType2.Correct) { + const EQ = correct === DataType2.Correct ? codegen_1.operators.EQ : codegen_1.operators.NEQ; let cond; switch (dataType) { case "null": @@ -29872,7 +29872,7 @@ var require_dataType = __commonJS({ default: return (0, codegen_1._)`typeof ${data} ${EQ} ${dataType}`; } - return correct === DataType.Correct ? cond : (0, codegen_1.not)(cond); + return correct === DataType2.Correct ? cond : (0, codegen_1.not)(cond); function numCond(_cond = codegen_1.nil) { return (0, codegen_1.and)((0, codegen_1._)`typeof ${data} == "number"`, _cond, strictNums ? (0, codegen_1._)`isFinite(${data})` : codegen_1.nil); } @@ -29883,19 +29883,19 @@ var require_dataType = __commonJS({ return checkDataType(dataTypes[0], data, strictNums, correct); } let cond; - const types2 = (0, util_1.toHash)(dataTypes); - if (types2.array && types2.object) { + const types3 = (0, util_1.toHash)(dataTypes); + if (types3.array && types3.object) { const notObj = (0, codegen_1._)`typeof ${data} != "object"`; - cond = types2.null ? notObj : (0, codegen_1._)`!${data} || ${notObj}`; - delete types2.null; - delete types2.array; - delete types2.object; + cond = types3.null ? notObj : (0, codegen_1._)`!${data} || ${notObj}`; + delete types3.null; + delete types3.array; + delete types3.object; } else { cond = codegen_1.nil; } - if (types2.number) - delete types2.integer; - for (const t in types2) + if (types3.number) + delete types3.integer; + for (const t in types3) cond = (0, codegen_1.and)(cond, checkDataType(t, data, strictNums, correct)); return cond; } @@ -30126,9 +30126,9 @@ var require_keyword = __commonJS({ exports2.macroKeywordCode = macroKeywordCode; function funcKeywordCode(cxt, def) { var _a3; - const { gen, keyword, schema, parentSchema, $data, it } = cxt; + const { gen, keyword, schema, parentSchema, $data: $data2, it } = cxt; checkAsyncKeyword(it, def); - const validate2 = !$data && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate; + const validate2 = !$data2 && def.compile ? def.compile.call(it.self, schema, parentSchema, it) : def.validate; const validateRef = useKeyword(gen, keyword, validate2); const valid = gen.let("valid"); cxt.block$data(valid, validateKeyword); @@ -30159,7 +30159,7 @@ var require_keyword = __commonJS({ } function assignValid(_await = def.async ? (0, codegen_1._)`await ` : codegen_1.nil) { const passCxt = it.opts.passContext ? names_1.default.this : names_1.default.self; - const passSchema = !("compile" in def && !$data || def.schema === false); + const passSchema = !("compile" in def && !$data2 || def.schema === false); gen.assign(valid, (0, codegen_1._)`${_await}${(0, code_1.callValidateCode)(cxt, validateRef, passCxt, passSchema)}`, def.modifying); } function reportErrs(errors) { @@ -30700,9 +30700,9 @@ var require_validate = __commonJS({ function typeAndKeywords(it, errsCount) { if (it.opts.jtd) return schemaKeywords(it, [], false, errsCount); - const types2 = (0, dataType_1.getSchemaTypes)(it.schema); - const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types2); - schemaKeywords(it, types2, !checkedTypes, errsCount); + const types3 = (0, dataType_1.getSchemaTypes)(it.schema); + const checkedTypes = (0, dataType_1.coerceAndCheckDataType)(it, types3); + schemaKeywords(it, types3, !checkedTypes, errsCount); } function checkRefsAndKeywords(it) { const { schema, errSchemaPath, opts, self: self2 } = it; @@ -30752,7 +30752,7 @@ var require_validate = __commonJS({ if (items instanceof codegen_1.Name) gen.assign((0, codegen_1._)`${evaluated}.items`, items); } - function schemaKeywords(it, types2, typeErrors, errsCount) { + function schemaKeywords(it, types3, typeErrors, errsCount) { const { gen, schema, data, allErrors, opts, self: self2 } = it; const { RULES } = self2; if (schema.$ref && (opts.ignoreKeywordsWithRef || !(0, util_1.schemaHasRulesButRef)(schema, RULES))) { @@ -30760,7 +30760,7 @@ var require_validate = __commonJS({ return; } if (!opts.jtd) - checkStrictTypes(it, types2); + checkStrictTypes(it, types3); gen.block(() => { for (const group2 of RULES.rules) groupKeywords(group2); @@ -30772,7 +30772,7 @@ var require_validate = __commonJS({ if (group2.type) { gen.if((0, dataType_2.checkDataType)(group2.type, data, opts.strictNumbers)); iterateKeywords(it, group2); - if (types2.length === 1 && types2[0] === group2.type && typeErrors) { + if (types3.length === 1 && types3[0] === group2.type && typeErrors) { gen.else(); (0, dataType_2.reportTypeError)(it); } @@ -30796,27 +30796,27 @@ var require_validate = __commonJS({ } }); } - function checkStrictTypes(it, types2) { + function checkStrictTypes(it, types3) { if (it.schemaEnv.meta || !it.opts.strictTypes) return; - checkContextTypes(it, types2); + checkContextTypes(it, types3); if (!it.opts.allowUnionTypes) - checkMultipleTypes(it, types2); + checkMultipleTypes(it, types3); checkKeywordTypes(it, it.dataTypes); } - function checkContextTypes(it, types2) { - if (!types2.length) + function checkContextTypes(it, types3) { + if (!types3.length) return; if (!it.dataTypes.length) { - it.dataTypes = types2; + it.dataTypes = types3; return; } - types2.forEach((t) => { + types3.forEach((t) => { if (!includesType(it.dataTypes, t)) { strictTypesError(it, `type "${t}" not allowed by context "${it.dataTypes.join(",")}"`); } }); - narrowSchemaTypes(it, types2); + narrowSchemaTypes(it, types3); } function checkMultipleTypes(it, ts) { if (ts.length > 1 && !(ts.length === 2 && ts.includes("null"))) { @@ -30872,7 +30872,7 @@ var require_validate = __commonJS({ this.it = it; this.def = def; if (this.$data) { - this.schemaCode = it.gen.const("vSchema", getData(this.$data, it)); + this.schemaCode = it.gen.const("vSchema", getData2(this.$data, it)); } else { this.schemaCode = this.schemaValue; if (!(0, keyword_1.validSchemaType)(this.schema, def.schemaType, def.allowUndefined)) { @@ -31041,20 +31041,20 @@ var require_validate = __commonJS({ } var JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/; var RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; - function getData($data, { dataLevel, dataNames, dataPathArr }) { + function getData2($data2, { dataLevel, dataNames, dataPathArr }) { let jsonPointer; let data; - if ($data === "") + if ($data2 === "") return names_1.default.rootData; - if ($data[0] === "/") { - if (!JSON_POINTER.test($data)) - throw new Error(`Invalid JSON-pointer: ${$data}`); - jsonPointer = $data; + if ($data2[0] === "/") { + if (!JSON_POINTER.test($data2)) + throw new Error(`Invalid JSON-pointer: ${$data2}`); + jsonPointer = $data2; data = names_1.default.rootData; } else { - const matches = RELATIVE_JSON_POINTER.exec($data); + const matches = RELATIVE_JSON_POINTER.exec($data2); if (!matches) - throw new Error(`Invalid JSON-pointer: ${$data}`); + throw new Error(`Invalid JSON-pointer: ${$data2}`); const up = +matches[1]; jsonPointer = matches[2]; if (jsonPointer === "#") { @@ -31081,7 +31081,7 @@ var require_validate = __commonJS({ return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`; } } - exports2.getData = getData; + exports2.getData = getData2; } }); @@ -31520,8 +31520,8 @@ var require_utils = __commonJS({ } return ind; } - function removeDotSegments(path) { - let input2 = path; + function removeDotSegments(path2) { + let input2 = path2; const output2 = []; let nextSlash = -1; let len = 0; @@ -31601,7 +31601,7 @@ var require_utils = __commonJS({ function reescapeHostDelimiters(host, isIP) { const re2 = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE; re2.lastIndex = 0; - return host.replace(re2, (ch) => HOST_DELIMS[ch]); + return host.replace(re2, (ch2) => HOST_DELIMS[ch2]); } function normalizePercentEncoding(input2, decodeUnreserved = false) { if (input2.indexOf("%") === -1) { @@ -31630,8 +31630,8 @@ var require_utils = __commonJS({ function normalizePathEncoding(input2) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { const normalizedHex = hex3.toUpperCase(); @@ -31645,12 +31645,12 @@ var require_utils = __commonJS({ continue; } } - if (isPathCharacter(ch)) { - output2 += ch; + if (isPathCharacter(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { - output2 += isEscapeSafe(code) ? ch : BYTE_HEX[code]; + output2 += isEscapeSafe(code) ? ch2 : BYTE_HEX[code]; } else if (code < 55296 || code > 57343) { output2 += percentEncodeNonAscii(code); } else if (code <= 56319 && i + 1 < input2.length) { @@ -31672,8 +31672,8 @@ var require_utils = __commonJS({ let output2 = ""; let firstSegment = pathNoScheme && input2[0] !== "/"; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { output2 += "%" + hex3.toUpperCase(); @@ -31681,11 +31681,11 @@ var require_utils = __commonJS({ continue; } } - if (ch === "/") { + if (ch2 === "/") { firstSegment = false; } - if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) { - output2 += ch; + if (isPathCharacter(ch2) && (ch2 !== ":" || !firstSegment)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { @@ -31710,8 +31710,8 @@ var require_utils = __commonJS({ function encodeComponent(input2, isAllowed) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { output2 += "%" + hex3.toUpperCase(); @@ -31719,8 +31719,8 @@ var require_utils = __commonJS({ continue; } } - if (isAllowed(ch)) { - output2 += ch; + if (isAllowed(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { @@ -31757,8 +31757,8 @@ var require_utils = __commonJS({ function normalizeQueryFragmentEncoding(input2) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { const normalizedHex = hex3.toUpperCase(); @@ -31772,12 +31772,12 @@ var require_utils = __commonJS({ continue; } } - if (isQueryFragmentCharacter(ch)) { - output2 += ch; + if (isQueryFragmentCharacter(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { - output2 += isEscapeSafe(code) ? ch : BYTE_HEX[code]; + output2 += isEscapeSafe(code) ? ch2 : BYTE_HEX[code]; } else if (code < 55296 || code > 57343) { output2 += percentEncodeNonAscii(code); } else if (code <= 56319 && i + 1 < input2.length) { @@ -31930,8 +31930,8 @@ var require_schemes = __commonJS({ } if (wsComponent.resourceName) { const queryIndex = wsComponent.resourceName.indexOf("?"); - const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex); - wsComponent.path = path && path !== "/" ? path : void 0; + const path2 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex); + wsComponent.path = path2 && path2 !== "/" ? path2 : void 0; wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1); wsComponent.resourceName = void 0; } @@ -32632,14 +32632,14 @@ var require_core = __commonJS({ this.addKeyword("$async"); } _addDefaultMetaSchema() { - const { $data, meta: meta3, schemaId } = this.opts; + const { $data: $data2, meta: meta3, schemaId } = this.opts; let _dataRefSchema = $dataRefSchema; if (schemaId === "id") { _dataRefSchema = { ...$dataRefSchema }; _dataRefSchema.id = _dataRefSchema.$id; delete _dataRefSchema.$id; } - if (meta3 && $data) + if (meta3 && $data2) this.addMetaSchema(_dataRefSchema, _dataRefSchema[schemaId], false); } defaultMeta() { @@ -32897,9 +32897,9 @@ var require_core = __commonJS({ const rule = rules[key]; if (typeof rule != "object") continue; - const { $data } = rule.definition; + const { $data: $data2 } = rule.definition; const schema = keywords[key]; - if ($data && schema) + if ($data2 && schema) keywords[key] = schemaOrData(schema); } } @@ -33397,9 +33397,9 @@ var require_pattern = __commonJS({ $data: true, error: error62, code(cxt) { - const { gen, data, $data, schema, schemaCode, it } = cxt; + const { gen, data, $data: $data2, schema, schemaCode, it } = cxt; const u = it.opts.unicodeRegExp ? "u" : ""; - if ($data) { + if ($data2) { const { regExp } = it.opts.code; const regExpCode = regExp.code === "new RegExp" ? (0, codegen_1._)`new RegExp` : (0, util_1.useFunc)(gen, regExp); const valid = gen.let("valid"); @@ -33463,9 +33463,9 @@ var require_required = __commonJS({ $data: true, error: error62, code(cxt) { - const { gen, schema, schemaCode, data, $data, it } = cxt; + const { gen, schema, schemaCode, data, $data: $data2, it } = cxt; const { opts } = it; - if (!$data && schema.length === 0) + if (!$data2 && schema.length === 0) return; const useLoop = schema.length >= opts.loopRequired; if (it.allErrors) @@ -33484,7 +33484,7 @@ var require_required = __commonJS({ } } function allErrorsMode() { - if (useLoop || $data) { + if (useLoop || $data2) { cxt.block$data(codegen_1.nil, loopAllRequired); } else { for (const prop of schema) { @@ -33494,7 +33494,7 @@ var require_required = __commonJS({ } function exitOnErrorMode() { const missing = gen.let("missing"); - if (useLoop || $data) { + if (useLoop || $data2) { const valid = gen.let("valid", true); cxt.block$data(valid, () => loopUntilMissing(missing, valid)); cxt.ok(valid); @@ -33586,8 +33586,8 @@ var require_uniqueItems = __commonJS({ $data: true, error: error62, code(cxt) { - const { gen, data, $data, schema, parentSchema, schemaCode, it } = cxt; - if (!$data && !schema) + const { gen, data, $data: $data2, schema, parentSchema, schemaCode, it } = cxt; + if (!$data2 && !schema) return; const valid = gen.let("valid"); const itemTypes = parentSchema.items ? (0, dataType_1.getSchemaTypes)(parentSchema.items) : []; @@ -33650,8 +33650,8 @@ var require_const = __commonJS({ $data: true, error: error62, code(cxt) { - const { gen, data, $data, schemaCode, schema } = cxt; - if ($data || schema && typeof schema == "object") { + const { gen, data, $data: $data2, schemaCode, schema } = cxt; + if ($data2 || schema && typeof schema == "object") { cxt.fail$data((0, codegen_1._)`!${(0, util_1.useFunc)(gen, equal_1.default)}(${data}, ${schemaCode})`); } else { cxt.fail((0, codegen_1._)`${schema} !== ${data}`); @@ -33680,14 +33680,14 @@ var require_enum = __commonJS({ $data: true, error: error62, code(cxt) { - const { gen, data, $data, schema, schemaCode, it } = cxt; - if (!$data && schema.length === 0) + const { gen, data, $data: $data2, schema, schemaCode, it } = cxt; + if (!$data2 && schema.length === 0) throw new Error("enum must have non-empty array"); const useLoop = schema.length >= it.opts.loopEnum; let eql; const getEql = () => eql !== null && eql !== void 0 ? eql : eql = (0, util_1.useFunc)(gen, equal_1.default); let valid; - if (useLoop || $data) { + if (useLoop || $data2) { valid = gen.let("valid"); cxt.block$data(valid, loopEnum); } else { @@ -34665,11 +34665,11 @@ var require_format2 = __commonJS({ $data: true, error: error62, code(cxt, ruleType) { - const { gen, data, $data, schema, schemaCode, it } = cxt; + const { gen, data, $data: $data2, schema, schemaCode, it } = cxt; const { opts, errSchemaPath, schemaEnv, self: self2 } = it; if (!opts.validateFormats) return; - if ($data) + if ($data2) validate$DataFormat(); else validateFormat(); @@ -36983,8 +36983,8 @@ var require_utils2 = __commonJS({ } return ind; } - function removeDotSegments(path) { - let input2 = path; + function removeDotSegments(path2) { + let input2 = path2; const output2 = []; let nextSlash = -1; let len = 0; @@ -37064,7 +37064,7 @@ var require_utils2 = __commonJS({ function reescapeHostDelimiters(host, isIP) { const re2 = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE; re2.lastIndex = 0; - return host.replace(re2, (ch) => HOST_DELIMS[ch]); + return host.replace(re2, (ch2) => HOST_DELIMS[ch2]); } function normalizePercentEncoding(input2, decodeUnreserved = false) { if (input2.indexOf("%") === -1) { @@ -37112,8 +37112,8 @@ var require_utils2 = __commonJS({ function normalizePathEncoding(input2) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { const normalizedHex = hex3.toUpperCase(); @@ -37127,12 +37127,12 @@ var require_utils2 = __commonJS({ continue; } } - if (isPathCharacter(ch)) { - output2 += ch; + if (isPathCharacter(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { - output2 += isEscapeSafe(code) ? ch : BYTE_HEX[code]; + output2 += isEscapeSafe(code) ? ch2 : BYTE_HEX[code]; } else if (code < 55296 || code > 57343) { output2 += percentEncodeNonAscii(code); } else if (code <= 56319 && i + 1 < input2.length) { @@ -37154,8 +37154,8 @@ var require_utils2 = __commonJS({ let output2 = ""; let firstSegment = pathNoScheme && input2[0] !== "/"; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { output2 += "%" + hex3.toUpperCase(); @@ -37163,11 +37163,11 @@ var require_utils2 = __commonJS({ continue; } } - if (ch === "/") { + if (ch2 === "/") { firstSegment = false; } - if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) { - output2 += ch; + if (isPathCharacter(ch2) && (ch2 !== ":" || !firstSegment)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { @@ -37192,8 +37192,8 @@ var require_utils2 = __commonJS({ function normalizeQueryFragmentEncoding(input2) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { const normalizedHex = hex3.toUpperCase(); @@ -37207,12 +37207,12 @@ var require_utils2 = __commonJS({ continue; } } - if (isQueryFragmentCharacter(ch)) { - output2 += ch; + if (isQueryFragmentCharacter(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { - output2 += isEscapeSafe(code) ? ch : BYTE_HEX[code]; + output2 += isEscapeSafe(code) ? ch2 : BYTE_HEX[code]; } else if (code < 55296 || code > 57343) { output2 += percentEncodeNonAscii(code); } else if (code <= 56319 && i + 1 < input2.length) { @@ -37233,8 +37233,8 @@ var require_utils2 = __commonJS({ function encodeComponent(input2, isAllowed) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { output2 += "%" + hex3.toUpperCase(); @@ -37242,8 +37242,8 @@ var require_utils2 = __commonJS({ continue; } } - if (isAllowed(ch)) { - output2 += ch; + if (isAllowed(ch2)) { + output2 += ch2; } else { const code = input2.charCodeAt(i); if (code < 128) { @@ -37277,8 +37277,8 @@ var require_utils2 = __commonJS({ function escapePreservingEscapes(input2) { let output2 = ""; for (let i = 0; i < input2.length; i++) { - const ch = input2[i]; - if (ch === "%" && i + 2 < input2.length) { + const ch2 = input2[i]; + if (ch2 === "%" && i + 2 < input2.length) { const hex3 = input2.slice(i + 1, i + 3); if (isHexPair(hex3)) { output2 += "%" + hex3.toUpperCase(); @@ -37288,7 +37288,7 @@ var require_utils2 = __commonJS({ } const code = input2.charCodeAt(i); if (code < 128) { - output2 += isEscapeSafe(code) ? ch : BYTE_HEX[code]; + output2 += isEscapeSafe(code) ? ch2 : BYTE_HEX[code]; } else if (code < 55296 || code > 57343) { output2 += percentEncodeNonAscii(code); } else if (code <= 56319 && i + 1 < input2.length) { @@ -37448,8 +37448,8 @@ var require_schemes2 = __commonJS({ } if (wsComponent.resourceName) { const queryIndex = wsComponent.resourceName.indexOf("?"); - const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex); - wsComponent.path = path && path !== "/" ? path : void 0; + const path2 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex); + wsComponent.path = path2 && path2 !== "/" ? path2 : void 0; wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1); wsComponent.resourceName = void 0; } @@ -37565,12 +37565,12 @@ var require_schemes2 = __commonJS({ var LOCAL_PART_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+="; var HFNAME_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+,;:@"; var DTEXT_ALLOWED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+;:"; - function allowSet(chars, allowNonAscii = false) { + function allowSet(chars2, allowNonAscii = false) { const table2 = new Uint8Array(128); - for (let i = 0; i < chars.length; i++) { - table2[chars.charCodeAt(i)] = 1; + for (let i = 0; i < chars2.length; i++) { + table2[chars2.charCodeAt(i)] = 1; } - const escaped = chars.replace(/[\\\]^-]/gu, "\\$&"); + const escaped = chars2.replace(/[\\\]^-]/gu, "\\$&"); const cls = allowNonAscii ? `[${escaped}]|[^\\0-\\x7F\\uD800-\\uDFFF]` : `[${escaped}]`; return { all: new RegExp(`^(?:${cls})*$`, "u"), table: table2, allowNonAscii }; } @@ -38846,7 +38846,7 @@ var require_ajv_compiler = __commonJS({ var require_dist3 = __commonJS({ "node_modules/.pnpm/dequal@2.0.3/node_modules/dequal/dist/index.js"(exports2) { var has3 = Object.prototype.hasOwnProperty; - function find2(iter, tar, key) { + function find3(iter, tar, key) { for (key of iter.keys()) { if (dequal(key, tar)) return key; } @@ -38870,7 +38870,7 @@ var require_dist3 = __commonJS({ for (len of foo) { tmp = len; if (tmp && typeof tmp === "object") { - tmp = find2(bar, tmp); + tmp = find3(bar, tmp); if (!tmp) return false; } if (!bar.has(tmp)) return false; @@ -38884,7 +38884,7 @@ var require_dist3 = __commonJS({ for (len of foo) { tmp = len[0]; if (tmp && typeof tmp === "object") { - tmp = find2(bar, tmp); + tmp = find3(bar, tmp); if (!tmp) return false; } if (!dequal(len[1], bar.get(tmp))) { @@ -41154,7 +41154,7 @@ ${contextFunctionCode}`, const sanitizedKey = JSON.stringify(key); const value = `value_${key.replace(/[^a-zA-Z0-9]/g, "_")}_${context2.uid++}`; const defaultValue = resolvedLocation.schema.default; - const isRequired = requiredProperties.includes(key); + const isRequired2 = requiredProperties.includes(key); const currentAddComma = i === 0 ? "" : "json += JSON_STR_COMMA"; code += ` const ${value} = ${objVar}[${sanitizedKey}] @@ -41169,7 +41169,7 @@ ${contextFunctionCode}`, json += ${JSON.stringify(sanitizedKey + ":" + JSON.stringify(defaultValue))} } `; - } else if (isRequired) { + } else if (isRequired2) { code += ` else { throw new Error('${sanitizedKey.replace(/'/g, "\\'")} is required!') } @@ -41194,7 +41194,7 @@ ${contextFunctionCode}`, const sanitizedKey = JSON.stringify(key); const value = `value_${key.replace(/[^a-zA-Z0-9]/g, "_")}_${context2.uid++}`; const defaultValue = propertyLocation.schema.default; - const isRequired = requiredProperties.includes(key); + const isRequired2 = requiredProperties.includes(key); code += ` const ${value} = ${objVar}[${sanitizedKey}] if (${value} !== undefined) { @@ -41208,7 +41208,7 @@ ${contextFunctionCode}`, json += ${JSON.stringify(sanitizedKey + ":" + JSON.stringify(defaultValue))} } `; - } else if (isRequired) { + } else if (isRequired2) { code += ` else { throw new Error('${sanitizedKey.replace(/'/g, "\\'")} is required!') } @@ -41539,9 +41539,9 @@ ${contextFunctionCode}`, } function buildMultiTypeSerializer(context2, location, input2) { const schema = location.schema; - const types2 = schema.type.sort((t1) => t1 === "null" ? -1 : 1); + const types3 = schema.type.sort((t1) => t1 === "null" ? -1 : 1); let code = ""; - types2.forEach((type, index2) => { + types3.forEach((type, index2) => { location.schema = { ...location.schema, type }; const nestedResult = buildSingleTypeSerializer(context2, location, input2); const statement = index2 === 0 ? "if" : "else if"; @@ -43040,7 +43040,7 @@ var require_range = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/classes/range.js"(exports2, module2) { "use strict"; var SPACE_CHARACTERS = /\s+/g; - var Range2 = class _Range { + var Range3 = class _Range { constructor(range2, options) { options = parseOptions2(options); if (range2 instanceof _Range) { @@ -43179,7 +43179,7 @@ var require_range = __commonJS({ return false; } }; - module2.exports = Range2; + module2.exports = Range3; var LRU = require_lrucache(); var cache2 = new LRU(); var parseOptions2 = require_parse_options(); @@ -43491,12 +43491,12 @@ var require_comparator = __commonJS({ if (this.value === "") { return true; } - return new Range2(comp.value, options).test(this.value); + return new Range3(comp.value, options).test(this.value); } else if (comp.operator === "") { if (comp.value === "") { return true; } - return new Range2(this.value, options).test(comp.semver); + return new Range3(this.value, options).test(comp.semver); } options = parseOptions2(options); if (options.includePrerelease && (this.value === "<0.0.0-0" || comp.value === "<0.0.0-0")) { @@ -43529,7 +43529,7 @@ var require_comparator = __commonJS({ var cmp = require_cmp(); var debug = require_debug2(); var SemVer = require_semver(); - var Range2 = require_range(); + var Range3 = require_range(); } }); @@ -43537,10 +43537,10 @@ var require_comparator = __commonJS({ var require_satisfies = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/satisfies.js"(exports2, module2) { "use strict"; - var Range2 = require_range(); + var Range3 = require_range(); var satisfies = (version4, range2, options) => { try { - range2 = new Range2(range2, options); + range2 = new Range3(range2, options); } catch (er) { return false; } @@ -43554,8 +43554,8 @@ var require_satisfies = __commonJS({ var require_to_comparators = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/to-comparators.js"(exports2, module2) { "use strict"; - var Range2 = require_range(); - var toComparators = (range2, options) => new Range2(range2, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); + var Range3 = require_range(); + var toComparators = (range2, options) => new Range3(range2, options).set.map((comp) => comp.map((c) => c.value).join(" ").trim().split(" ")); module2.exports = toComparators; } }); @@ -43565,13 +43565,13 @@ var require_max_satisfying = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/max-satisfying.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var Range2 = require_range(); + var Range3 = require_range(); var maxSatisfying = (versions, range2, options) => { let max2 = null; let maxSV = null; let rangeObj = null; try { - rangeObj = new Range2(range2, options); + rangeObj = new Range3(range2, options); } catch (er) { return null; } @@ -43594,13 +43594,13 @@ var require_min_satisfying = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/min-satisfying.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var Range2 = require_range(); + var Range3 = require_range(); var minSatisfying = (versions, range2, options) => { let min2 = null; let minSV = null; let rangeObj = null; try { - rangeObj = new Range2(range2, options); + rangeObj = new Range3(range2, options); } catch (er) { return null; } @@ -43623,10 +43623,10 @@ var require_min_version = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/min-version.js"(exports2, module2) { "use strict"; var SemVer = require_semver(); - var Range2 = require_range(); + var Range3 = require_range(); var gt2 = require_gt(); var minVersion = (range2, loose) => { - range2 = new Range2(range2, loose); + range2 = new Range3(range2, loose); let minver = new SemVer("0.0.0"); if (range2.test(minver)) { return minver; @@ -43681,10 +43681,10 @@ var require_min_version = __commonJS({ var require_valid2 = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/valid.js"(exports2, module2) { "use strict"; - var Range2 = require_range(); + var Range3 = require_range(); var validRange = (range2, options) => { try { - return new Range2(range2, options).range || "*"; + return new Range3(range2, options).range || "*"; } catch (er) { return null; } @@ -43700,7 +43700,7 @@ var require_outside = __commonJS({ var SemVer = require_semver(); var Comparator = require_comparator(); var { ANY } = Comparator; - var Range2 = require_range(); + var Range3 = require_range(); var satisfies = require_satisfies(); var gt2 = require_gt(); var lt2 = require_lt(); @@ -43708,7 +43708,7 @@ var require_outside = __commonJS({ var gte2 = require_gte(); var outside = (version4, range2, hilo, options) => { version4 = new SemVer(version4, options); - range2 = new Range2(range2, options); + range2 = new Range3(range2, options); let gtfn, ltefn, ltfn, comp, ecomp; switch (hilo) { case ">": @@ -43786,10 +43786,10 @@ var require_ltr = __commonJS({ var require_intersects = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/intersects.js"(exports2, module2) { "use strict"; - var Range2 = require_range(); + var Range3 = require_range(); var intersects = (r1, r2, options) => { - r1 = new Range2(r1, options); - r2 = new Range2(r2, options); + r1 = new Range3(r1, options); + r2 = new Range3(r2, options); return r1.intersects(r2, options); }; module2.exports = intersects; @@ -43850,7 +43850,7 @@ var require_simplify = __commonJS({ var require_subset = __commonJS({ "node_modules/.pnpm/semver@7.8.5/node_modules/semver/ranges/subset.js"(exports2, module2) { "use strict"; - var Range2 = require_range(); + var Range3 = require_range(); var Comparator = require_comparator(); var { ANY } = Comparator; var satisfies = require_satisfies(); @@ -43859,8 +43859,8 @@ var require_subset = __commonJS({ if (sub === dom) { return true; } - sub = new Range2(sub, options); - dom = new Range2(dom, options); + sub = new Range3(sub, options); + dom = new Range3(dom, options); let sawNonNull = false; OUTER: for (const simpleSub of sub.set) { for (const simpleDom of dom.set) { @@ -44041,7 +44041,7 @@ var require_semver2 = __commonJS({ var coerce = require_coerce(); var truncate = require_truncate(); var Comparator = require_comparator(); - var Range2 = require_range(); + var Range3 = require_range(); var satisfies = require_satisfies(); var toComparators = require_to_comparators(); var maxSatisfying = require_max_satisfying(); @@ -44080,7 +44080,7 @@ var require_semver2 = __commonJS({ coerce, truncate, Comparator, - Range: Range2, + Range: Range3, satisfies, toComparators, maxSatisfying, @@ -44110,7 +44110,7 @@ var require_plugin_utils = __commonJS({ "node_modules/.pnpm/fastify@5.12.5/node_modules/fastify/lib/plugin-utils.js"(exports2, module2) { "use strict"; var semver = require_semver2(); - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); var kRegisteredPlugins = Symbol.for("registered-plugin"); var { kTestInternals @@ -44160,7 +44160,7 @@ var require_plugin_utils = __commonJS({ if (!meta3) return; const dependencies = meta3.dependencies; if (!dependencies) return; - assert3(Array.isArray(dependencies), "The dependencies should be an array of strings"); + assert4(Array.isArray(dependencies), "The dependencies should be an array of strings"); dependencies.forEach((dependency) => { if (!this[kRegisteredPlugins].includes(dependency)) { throw new FST_ERR_PLUGIN_DEPENDENCY_NOT_REGISTERED(dependency, meta3.name); @@ -44182,7 +44182,7 @@ var require_plugin_utils = __commonJS({ Reply: existReply }; function _checkDecorators(that, instance, decorators, name) { - assert3(Array.isArray(decorators), "The decorators should be an array of strings"); + assert4(Array.isArray(decorators), "The decorators should be an array of strings"); decorators.forEach((decorator) => { const withPluginName = typeof name === "string" ? ` required by '${name}'` : ""; if (!checks[instance].call(that, decorator)) { @@ -44736,11 +44736,11 @@ var require_parse3 = __commonJS({ "use strict"; var fastDecode = require_fast_decode_uri_component(); var plusRegex = /\+/g; - var Empty = function() { + var Empty2 = function() { }; - Empty.prototype = /* @__PURE__ */ Object.create(null); + Empty2.prototype = /* @__PURE__ */ Object.create(null); function parse4(input2) { - const result2 = new Empty(); + const result2 = new Empty2(); if (typeof input2 !== "string") { return result2; } @@ -45098,17 +45098,17 @@ var require_types3 = __commonJS({ "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.types = void 0; - var types2; - (function(types3) { - types3[types3["ROOT"] = 0] = "ROOT"; - types3[types3["GROUP"] = 1] = "GROUP"; - types3[types3["POSITION"] = 2] = "POSITION"; - types3[types3["SET"] = 3] = "SET"; - types3[types3["RANGE"] = 4] = "RANGE"; - types3[types3["REPETITION"] = 5] = "REPETITION"; - types3[types3["REFERENCE"] = 6] = "REFERENCE"; - types3[types3["CHAR"] = 7] = "CHAR"; - })(types2 = exports2.types || (exports2.types = {})); + var types3; + (function(types4) { + types4[types4["ROOT"] = 0] = "ROOT"; + types4[types4["GROUP"] = 1] = "GROUP"; + types4[types4["POSITION"] = 2] = "POSITION"; + types4[types4["SET"] = 3] = "SET"; + types4[types4["RANGE"] = 4] = "RANGE"; + types4[types4["REPETITION"] = 5] = "REPETITION"; + types4[types4["REFERENCE"] = 6] = "REFERENCE"; + types4[types4["CHAR"] = 7] = "CHAR"; + })(types3 = exports2.types || (exports2.types = {})); } }); @@ -45809,12 +45809,12 @@ var require_safe_regex2 = __commonJS({ "node_modules/.pnpm/safe-regex2@5.1.1/node_modules/safe-regex2/index.js"(exports2, module2) { "use strict"; var parse4 = require_dist4(); - var { types: types2 } = require_dist4(); + var { types: types3 } = require_dist4(); function walk2(node2, opts, starHeight) { let i; let ok; let len; - if (node2.type === types2.REPETITION) { + if (node2.type === types3.REPETITION) { starHeight++; opts.reps++; if (starHeight > 1) return false; @@ -46226,13 +46226,13 @@ var require_node = __commonJS({ this.staticChildrenNodes[index2] = node2; } } - findStaticMatchingChild(path, pathIndex) { - const charCode = path.charCodeAt(pathIndex); + findStaticMatchingChild(path2, pathIndex) { + const charCode = path2.charCodeAt(pathIndex); const charCodes = this.staticChildrenCharCodes; for (let i = 0; i < charCodes.length; i++) { if (charCodes[i] === charCode) { const staticChild = this.staticChildrenNodes[i]; - if (staticChild.matchPrefix(path, pathIndex)) { + if (staticChild.matchPrefix(path2, pathIndex)) { return staticChild; } return null; @@ -46240,34 +46240,34 @@ var require_node = __commonJS({ } return null; } - getStaticChild(path, pathIndex = 0) { - if (path.length === pathIndex) { + getStaticChild(path2, pathIndex = 0) { + if (path2.length === pathIndex) { return this; } - const staticChild = this.findStaticMatchingChild(path, pathIndex); + const staticChild = this.findStaticMatchingChild(path2, pathIndex); if (staticChild) { - return staticChild.getStaticChild(path, pathIndex + staticChild.prefix.length); + return staticChild.getStaticChild(path2, pathIndex + staticChild.prefix.length); } return null; } - createStaticChild(path) { - if (path.length === 0) { + createStaticChild(path2) { + if (path2.length === 0) { return this; } - const childIndex = this.staticChildrenCharCodes.indexOf(path.charCodeAt(0)); + const childIndex = this.staticChildrenCharCodes.indexOf(path2.charCodeAt(0)); let staticChild = childIndex === -1 ? void 0 : this.staticChildrenNodes[childIndex]; if (staticChild) { let i = 1; for (; i < staticChild.prefix.length; i++) { - if (path.charCodeAt(i) !== staticChild.prefix.charCodeAt(i)) { + if (path2.charCodeAt(i) !== staticChild.prefix.charCodeAt(i)) { staticChild = staticChild.split(this, i); break; } } - return staticChild.createStaticChild(path.slice(i)); + return staticChild.createStaticChild(path2.slice(i)); } - const node2 = new StaticNode(path); - this.setStaticChild(path.charAt(0), node2); + const node2 = new StaticNode(path2); + this.setStaticChild(path2.charAt(0), node2); return node2; } }; @@ -46327,8 +46327,8 @@ var require_node = __commonJS({ parentNode.setStaticChild(parentPrefix.charAt(0), staticNode); return staticNode; } - getNextNode(path, pathIndex, nodeStack, paramsCount) { - let node2 = this.findStaticMatchingChild(path, pathIndex); + getNextNode(path2, pathIndex, nodeStack, paramsCount) { + let node2 = this.findStaticMatchingChild(path2, pathIndex); let parametricBrotherNodeIndex = 0; if (node2 === null) { if (this.parametricChildren.length === 0) { @@ -46375,8 +46375,8 @@ var require_node = __commonJS({ this.kind = NODE_TYPES.PARAMETRIC; this.nodePaths = /* @__PURE__ */ new Set([nodePath]); } - getNextNode(path, pathIndex) { - return this.findStaticMatchingChild(path, pathIndex); + getNextNode(path2, pathIndex) { + return this.findStaticMatchingChild(path2, pathIndex); } }; var WildcardNode = class extends Node2 { @@ -46396,7 +46396,7 @@ var require_node = __commonJS({ var require_accept_version = __commonJS({ "node_modules/.pnpm/find-my-way@9.9.0/node_modules/find-my-way/lib/strategies/accept-version.js"(exports2, module2) { "use strict"; - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); function SemVerStore() { if (!(this instanceof SemVerStore)) { return new SemVerStore(); @@ -46444,7 +46444,7 @@ var require_accept_version = __commonJS({ mustMatchWhenDerived: true, storage: SemVerStore, validate(value) { - assert3(typeof value === "string", "Version should be a string"); + assert4(typeof value === "string", "Version should be a string"); } }; } @@ -46454,7 +46454,7 @@ var require_accept_version = __commonJS({ var require_accept_host = __commonJS({ "node_modules/.pnpm/find-my-way@9.9.0/node_modules/find-my-way/lib/strategies/accept-host.js"(exports2, module2) { "use strict"; - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); function HostStorage() { const hosts = /* @__PURE__ */ new Map(); const regexHosts = []; @@ -46491,7 +46491,7 @@ var require_accept_host = __commonJS({ mustMatchWhenDerived: false, storage: HostStorage, validate(value) { - assert3(typeof value === "string" || Object.prototype.toString.call(value) === "[object RegExp]", "Host should be a string or a RegExp"); + assert4(typeof value === "string" || Object.prototype.toString.call(value) === "[object RegExp]", "Host should be a string or a RegExp"); } }; } @@ -46503,7 +46503,7 @@ var require_constrainer = __commonJS({ "use strict"; var acceptVersionStrategy = require_accept_version(); var acceptHostStrategy = require_accept_host(); - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); var Constrainer = class { constructor(customStrategies) { this.strategies = { @@ -46529,9 +46529,9 @@ var require_constrainer = __commonJS({ return false; } addConstraintStrategy(strategy) { - assert3(typeof strategy.name === "string" && strategy.name !== "", "strategy.name is required."); - assert3(strategy.storage && typeof strategy.storage === "function", "strategy.storage function is required."); - assert3(strategy.deriveConstraint && typeof strategy.deriveConstraint === "function", "strategy.deriveConstraint function is required."); + assert4(typeof strategy.name === "string" && strategy.name !== "", "strategy.name is required."); + assert4(strategy.storage && typeof strategy.storage === "function", "strategy.storage function is required."); + assert4(strategy.deriveConstraint && typeof strategy.deriveConstraint === "function", "strategy.deriveConstraint function is required."); if (this.strategies[strategy.name] && this.strategies[strategy.name].isCustom) { throw new Error(`There already exists a custom constraint with the name ${strategy.name}.`); } @@ -46732,81 +46732,81 @@ var require_url_sanitizer = __commonJS({ return String.fromCharCode(charCode); } var MIN_NATIVE_SCAN_LENGTH = 12; - function safeDecodeURI(path, useSemicolonDelimiter) { - if (path.length >= MIN_NATIVE_SCAN_LENGTH) { - return safeDecodeURINativeScan(path, useSemicolonDelimiter); + function safeDecodeURI(path2, useSemicolonDelimiter) { + if (path2.length >= MIN_NATIVE_SCAN_LENGTH) { + return safeDecodeURINativeScan(path2, useSemicolonDelimiter); } - return safeDecodeURICharScan(path, useSemicolonDelimiter, 1); + return safeDecodeURICharScan(path2, useSemicolonDelimiter, 1); } - function safeDecodeURINativeScan(path, useSemicolonDelimiter) { - const percentIndex = path.indexOf("%", 1); - let delimIndex = path.indexOf("?", 1); - const hashIndex = path.indexOf("#", 1); + function safeDecodeURINativeScan(path2, useSemicolonDelimiter) { + const percentIndex = path2.indexOf("%", 1); + let delimIndex = path2.indexOf("?", 1); + const hashIndex = path2.indexOf("#", 1); if (hashIndex !== -1 && (delimIndex === -1 || hashIndex < delimIndex)) { delimIndex = hashIndex; } if (useSemicolonDelimiter) { - const semicolonIndex = path.indexOf(";", 1); + const semicolonIndex = path2.indexOf(";", 1); if (semicolonIndex !== -1 && (delimIndex === -1 || semicolonIndex < delimIndex)) { delimIndex = semicolonIndex; } } if (percentIndex === -1 || delimIndex !== -1 && percentIndex > delimIndex) { if (delimIndex === -1) { - return { path, querystring: "", shouldDecodeParam: false }; + return { path: path2, querystring: "", shouldDecodeParam: false }; } return { - path: path.slice(0, delimIndex), - querystring: path.slice(delimIndex + 1), + path: path2.slice(0, delimIndex), + querystring: path2.slice(delimIndex + 1), shouldDecodeParam: false }; } - return safeDecodeURIPercentScan(path, useSemicolonDelimiter, percentIndex); + return safeDecodeURIPercentScan(path2, useSemicolonDelimiter, percentIndex); } - function safeDecodeURICharScan(path, useSemicolonDelimiter, startIndex) { - for (let i = startIndex; i < path.length; i++) { - const charCode = path.charCodeAt(i); + function safeDecodeURICharScan(path2, useSemicolonDelimiter, startIndex) { + for (let i = startIndex; i < path2.length; i++) { + const charCode = path2.charCodeAt(i); if (charCode === 37) { - return safeDecodeURIPercentScan(path, useSemicolonDelimiter, i); + return safeDecodeURIPercentScan(path2, useSemicolonDelimiter, i); } else if (charCode === 63 || charCode === 35 || charCode === 59 && useSemicolonDelimiter) { return { - path: path.slice(0, i), - querystring: path.slice(i + 1), + path: path2.slice(0, i), + querystring: path2.slice(i + 1), shouldDecodeParam: false }; } } - return { path, querystring: "", shouldDecodeParam: false }; + return { path: path2, querystring: "", shouldDecodeParam: false }; } - function reencodePercentChar(path, index2) { - return path.slice(0, index2 + 1) + "25" + path.slice(index2 + 1); + function reencodePercentChar(path2, index2) { + return path2.slice(0, index2 + 1) + "25" + path2.slice(index2 + 1); } - function safeDecodeURIPercentScan(path, useSemicolonDelimiter, startIndex) { + function safeDecodeURIPercentScan(path2, useSemicolonDelimiter, startIndex) { let shouldDecode = false; let shouldDecodeParam = false; let querystring = ""; - for (let i = startIndex; i < path.length; i++) { - const charCode = path.charCodeAt(i); + for (let i = startIndex; i < path2.length; i++) { + const charCode = path2.charCodeAt(i); if (charCode === 37) { - const componentCharCode = decodeComponentCharCode(path.charCodeAt(i + 1), path.charCodeAt(i + 2)); + const componentCharCode = decodeComponentCharCode(path2.charCodeAt(i + 1), path2.charCodeAt(i + 2)); if (componentCharCode === 0) { shouldDecode = true; } else { shouldDecodeParam = true; if (componentCharCode === 37) { shouldDecode = true; - path = reencodePercentChar(path, i); + path2 = reencodePercentChar(path2, i); i += 2; } i += 2; } } else if (charCode === 63 || charCode === 35 || charCode === 59 && useSemicolonDelimiter) { - querystring = path.slice(i + 1); - path = path.slice(0, i); + querystring = path2.slice(i + 1); + path2 = path2.slice(0, i); break; } } - const decodedPath = shouldDecode ? decodeURI(path) : path; + const decodedPath = shouldDecode ? decodeURI(path2) : path2; return { path: decodedPath, querystring, shouldDecodeParam }; } function safeDecodeURIComponent(uriComponent) { @@ -46833,7 +46833,7 @@ var require_url_sanitizer = __commonJS({ var require_find_my_way = __commonJS({ "node_modules/.pnpm/find-my-way@9.9.0/node_modules/find-my-way/index.js"(exports2, module2) { "use strict"; - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); var querystring = require_lib(); var isRegexSafe = require_safe_regex2(); var deepEqual = require_fast_deep_equal(); @@ -46862,25 +46862,25 @@ var require_find_my_way = __commonJS({ opts = opts || {}; this._opts = opts; if (opts.defaultRoute) { - assert3(typeof opts.defaultRoute === "function", "The default route must be a function"); + assert4(typeof opts.defaultRoute === "function", "The default route must be a function"); this.defaultRoute = opts.defaultRoute; } else { this.defaultRoute = null; } if (opts.onBadUrl) { - assert3(typeof opts.onBadUrl === "function", "The bad url handler must be a function"); + assert4(typeof opts.onBadUrl === "function", "The bad url handler must be a function"); this.onBadUrl = opts.onBadUrl; } else { this.onBadUrl = null; } if (opts.buildPrettyMeta) { - assert3(typeof opts.buildPrettyMeta === "function", "buildPrettyMeta must be a function"); + assert4(typeof opts.buildPrettyMeta === "function", "buildPrettyMeta must be a function"); this.buildPrettyMeta = opts.buildPrettyMeta; } else { this.buildPrettyMeta = defaultBuildPrettyMeta; } if (opts.querystringParser) { - assert3(typeof opts.querystringParser === "function", "querystringParser must be a function"); + assert4(typeof opts.querystringParser === "function", "querystringParser must be a function"); this.querystringParser = opts.querystringParser; } else { this.querystringParser = (query) => query.length === 0 ? {} : querystring.parse(query); @@ -46897,7 +46897,7 @@ var require_find_my_way = __commonJS({ this.trees = /* @__PURE__ */ Object.create(null); this._treeGET = null; } - Router.prototype.on = function on(method, path, opts, handler, store) { + Router.prototype.on = function on(method, path2, opts, handler, store) { if (typeof opts === "function") { if (handler !== void 0) { store = handler; @@ -46905,37 +46905,37 @@ var require_find_my_way = __commonJS({ handler = opts; opts = {}; } - assert3(typeof path === "string", "Path should be a string"); - assert3(path.length > 0, "The path could not be empty"); - assert3(path[0] === "/" || path[0] === "*", "The first character of a path should be `/` or `*`"); - assert3(typeof handler === "function", "Handler should be a function"); - const optionalParamMatch = path.match(OPTIONAL_PARAM_REGEXP); + assert4(typeof path2 === "string", "Path should be a string"); + assert4(path2.length > 0, "The path could not be empty"); + assert4(path2[0] === "/" || path2[0] === "*", "The first character of a path should be `/` or `*`"); + assert4(typeof handler === "function", "Handler should be a function"); + const optionalParamMatch = path2.match(OPTIONAL_PARAM_REGEXP); if (optionalParamMatch) { - assert3(path.length === optionalParamMatch.index + optionalParamMatch[0].length, "Optional Parameter needs to be the last parameter of the path"); - const pathFull = path.replace(OPTIONAL_PARAM_REGEXP, "$1$2"); - const pathOptional = path.replace(OPTIONAL_PARAM_REGEXP, "$2") || "/"; + assert4(path2.length === optionalParamMatch.index + optionalParamMatch[0].length, "Optional Parameter needs to be the last parameter of the path"); + const pathFull = path2.replace(OPTIONAL_PARAM_REGEXP, "$1$2"); + const pathOptional = path2.replace(OPTIONAL_PARAM_REGEXP, "$2") || "/"; this.on(method, pathFull, opts, handler, store); this.on(method, pathOptional, opts, handler, store); return; } - const route = path; + const route = path2; if (this.ignoreDuplicateSlashes) { - path = removeDuplicateSlashes(path); + path2 = removeDuplicateSlashes(path2); } if (this.ignoreTrailingSlash) { - path = trimLastSlash(path); + path2 = trimLastSlash(path2); } const methods = Array.isArray(method) ? method : [method]; for (const method2 of methods) { - assert3(typeof method2 === "string", "Method should be a string"); - assert3(httpMethods.includes(method2), `Method '${method2}' is not an http method.`); - this._on(method2, path, opts, handler, store, route); + assert4(typeof method2 === "string", "Method should be a string"); + assert4(httpMethods.includes(method2), `Method '${method2}' is not an http method.`); + this._on(method2, path2, opts, handler, store, route); } }; - Router.prototype._on = function _on(method, path, opts, handler, store) { + Router.prototype._on = function _on(method, path2, opts, handler, store) { let constraints = {}; if (opts.constraints !== void 0) { - assert3(typeof opts.constraints === "object" && opts.constraints !== null, "Constraints should be an object"); + assert4(typeof opts.constraints === "object" && opts.constraints !== null, "Constraints should be an object"); if (Object.keys(opts.constraints).length !== 0) { constraints = opts.constraints; } @@ -46945,7 +46945,7 @@ var require_find_my_way = __commonJS({ if (this.trees[method] === void 0) { this.trees[method] = new StaticNode("/"); } - let pattern = path; + let pattern = path2; if (pattern === "*" && this.trees[method].prefix.length !== 0) { const currentRoot = this.trees[method]; this.trees[method] = new StaticNode(""); @@ -46993,7 +46993,7 @@ var require_find_my_way = __commonJS({ const endOfRegexIndex = getClosingParenthensePosition(pattern, j); const regexString = pattern.slice(j, endOfRegexIndex + 1); if (!this.allowUnsafeRegex) { - assert3(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`); + assert4(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`); } regexps.push(trimRegExpStartAndEnd(regexString)); j = endOfRegexIndex + 1; @@ -47053,19 +47053,19 @@ var require_find_my_way = __commonJS({ throw new Error(`Method '${method}' already declared for route '${pattern}' with constraints '${JSON.stringify(constraints)}'`); } } - const route = { method, path, pattern, params, opts, handler, store }; + const route = { method, path: path2, pattern, params, opts, handler, store }; this.routes.push(route); currentNode.addRoute(route, this.constrainer); }; - Router.prototype.hasRoute = function hasRoute(method, path, constraints) { - const route = this.findRoute(method, path, constraints); + Router.prototype.hasRoute = function hasRoute(method, path2, constraints) { + const route = this.findRoute(method, path2, constraints); return route !== null; }; - Router.prototype.findRoute = function findNode(method, path, constraints = {}) { + Router.prototype.findRoute = function findNode(method, path2, constraints = {}) { if (this.trees[method] === void 0) { return null; } - let pattern = path; + let pattern = path2; let currentNode = this.trees[method]; let parentNodePathIndex = currentNode.prefix.length; const params = []; @@ -47108,7 +47108,7 @@ var require_find_my_way = __commonJS({ const endOfRegexIndex = getClosingParenthensePosition(pattern, j); const regexString = pattern.slice(j, endOfRegexIndex + 1); if (!this.allowUnsafeRegex) { - assert3(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`); + assert4(isRegexSafe(new RegExp(regexString)), `The regex '${regexString}' is not safe!`); } regexps.push(trimRegExpStartAndEnd(regexString)); j = endOfRegexIndex + 1; @@ -47186,39 +47186,39 @@ var require_find_my_way = __commonJS({ this._treeGET = null; this.routes = []; }; - Router.prototype.off = function off(method, path, constraints) { - assert3(typeof path === "string", "Path should be a string"); - assert3(path.length > 0, "The path could not be empty"); - assert3(path[0] === "/" || path[0] === "*", "The first character of a path should be `/` or `*`"); - assert3( + Router.prototype.off = function off(method, path2, constraints) { + assert4(typeof path2 === "string", "Path should be a string"); + assert4(path2.length > 0, "The path could not be empty"); + assert4(path2[0] === "/" || path2[0] === "*", "The first character of a path should be `/` or `*`"); + assert4( typeof constraints === "undefined" || typeof constraints === "object" && !Array.isArray(constraints) && constraints !== null, "Constraints should be an object or undefined." ); - const optionalParamMatch = path.match(OPTIONAL_PARAM_REGEXP); + const optionalParamMatch = path2.match(OPTIONAL_PARAM_REGEXP); if (optionalParamMatch) { - assert3(path.length === optionalParamMatch.index + optionalParamMatch[0].length, "Optional Parameter needs to be the last parameter of the path"); - const pathFull = path.replace(OPTIONAL_PARAM_REGEXP, "$1$2"); - const pathOptional = path.replace(OPTIONAL_PARAM_REGEXP, "$2") || "/"; + assert4(path2.length === optionalParamMatch.index + optionalParamMatch[0].length, "Optional Parameter needs to be the last parameter of the path"); + const pathFull = path2.replace(OPTIONAL_PARAM_REGEXP, "$1$2"); + const pathOptional = path2.replace(OPTIONAL_PARAM_REGEXP, "$2") || "/"; this.off(method, pathFull, constraints); this.off(method, pathOptional, constraints); return; } if (this.ignoreDuplicateSlashes) { - path = removeDuplicateSlashes(path); + path2 = removeDuplicateSlashes(path2); } if (this.ignoreTrailingSlash) { - path = trimLastSlash(path); + path2 = trimLastSlash(path2); } const methods = Array.isArray(method) ? method : [method]; for (const method2 of methods) { - this._off(method2, path, constraints); + this._off(method2, path2, constraints); } }; - Router.prototype._off = function _off(method, path, constraints) { - assert3(typeof method === "string", "Method should be a string"); - assert3(httpMethods.includes(method), `Method '${method}' is not an http method.`); + Router.prototype._off = function _off(method, path2, constraints) { + assert4(typeof method === "string", "Method should be a string"); + assert4(httpMethods.includes(method), `Method '${method}' is not an http method.`); function matcherWithoutConstraints(route) { - return method !== route.method || path !== route.path; + return method !== route.method || path2 !== route.path; } function matcherWithConstraints(route) { return matcherWithoutConstraints(route) || !deepEqual(constraints, route.opts.constraints || {}); @@ -47255,41 +47255,41 @@ var require_find_my_way = __commonJS({ if (handle === null) return this._defaultRoute(req, res, ctx); return ctx === void 0 ? handle.handler(req, res, handle.params, handle.store, handle.searchParams) : handle.handler.call(ctx, req, res, handle.params, handle.store, handle.searchParams); }; - Router.prototype.find = function find2(method, path, derivedConstraints) { + Router.prototype.find = function find3(method, path2, derivedConstraints) { let currentNode = method === "GET" ? this._treeGET : this.trees[method]; if (currentNode == null) return null; - if (path.charCodeAt(0) !== 47) { - const absolutePath = getPathFromAbsoluteUrl(path); + if (path2.charCodeAt(0) !== 47) { + const absolutePath = getPathFromAbsoluteUrl(path2); if (absolutePath === null) { - return this._onBadUrl(path); + return this._onBadUrl(path2); } - path = absolutePath; + path2 = absolutePath; } if (this.ignoreDuplicateSlashes) { - path = removeDuplicateSlashes(path); + path2 = removeDuplicateSlashes(path2); } let sanitizedUrl; let querystring2; let shouldDecodeParam; try { - sanitizedUrl = path.length >= MIN_NATIVE_SCAN_LENGTH ? safeDecodeURINativeScan(path, this.useSemicolonDelimiter) : safeDecodeURICharScan(path, this.useSemicolonDelimiter, 1); - path = sanitizedUrl.path; + sanitizedUrl = path2.length >= MIN_NATIVE_SCAN_LENGTH ? safeDecodeURINativeScan(path2, this.useSemicolonDelimiter) : safeDecodeURICharScan(path2, this.useSemicolonDelimiter, 1); + path2 = sanitizedUrl.path; querystring2 = sanitizedUrl.querystring; shouldDecodeParam = sanitizedUrl.shouldDecodeParam; } catch (error62) { - return this._onBadUrl(path); + return this._onBadUrl(path2); } if (this.ignoreTrailingSlash) { - path = trimLastSlash(path); + path2 = trimLastSlash(path2); } - const originPath = path; + const originPath = path2; if (this.caseSensitive === false) { - path = path.toLowerCase(); + path2 = path2.toLowerCase(); } const maxParamLength = this.maxParamLength; let pathIndex = currentNode.prefix.length; const params = []; - const pathLen = path.length; + const pathLen = path2.length; const brothersNodesStack = []; let maxParamLengthExceeded = false; while (true) { @@ -47304,7 +47304,7 @@ var require_find_my_way = __commonJS({ }; } } - let node2 = currentNode.getNextNode(path, pathIndex, brothersNodesStack, params.length); + let node2 = currentNode.getNextNode(path2, pathIndex, brothersNodesStack, params.length); if (node2 === null) { if (brothersNodesStack.length === 0) { if (maxParamLengthExceeded && this.onMaxParamLength) { @@ -47405,8 +47405,8 @@ var require_find_my_way = __commonJS({ Router.prototype._rebuild = function(routes) { this.reset(); for (const route of routes) { - const { method, path, opts, handler, store } = route; - this._on(method, path, opts, handler, store); + const { method, path: path2, opts, handler, store } = route; + this._on(method, path2, opts, handler, store); } }; Router.prototype._defaultRoute = function(req, res, ctx) { @@ -47417,24 +47417,24 @@ var require_find_my_way = __commonJS({ res.end(); } }; - Router.prototype._onBadUrl = function(path) { + Router.prototype._onBadUrl = function(path2) { if (this.onBadUrl === null) { return null; } const onBadUrl = this.onBadUrl; return { - handler: (req, res, ctx) => onBadUrl(path, req, res), + handler: (req, res, ctx) => onBadUrl(path2, req, res), params: {}, store: null }; }; - Router.prototype._onMaxParamLength = function(path) { + Router.prototype._onMaxParamLength = function(path2) { if (this.onMaxParamLength === null) { return null; } const onMaxParamLength = this.onMaxParamLength; return { - handler: (req, res, ctx) => onMaxParamLength(path, req, res), + handler: (req, res, ctx) => onMaxParamLength(path2, req, res), params: {}, store: null }; @@ -47466,12 +47466,12 @@ var require_find_my_way = __commonJS({ if (!httpMethods.hasOwnProperty(i)) continue; const m = httpMethods[i]; const methodName = m.toLowerCase(); - Router.prototype[methodName] = function(path, handler, store) { - return this.on(m, path, handler, store); + Router.prototype[methodName] = function(path2, handler, store) { + return this.on(m, path2, handler, store); }; } - Router.prototype.all = function(path, handler, store) { - this.on(httpMethods, path, handler, store); + Router.prototype.all = function(path2, handler, store) { + this.on(httpMethods, path2, handler, store); }; Router.sanitizeUrlPath = function sanitizeUrlPath(url2, useSemicolonDelimiter) { const decoded = safeDecodeURI(url2, useSemicolonDelimiter); @@ -47524,14 +47524,14 @@ var require_find_my_way = __commonJS({ } return url2.slice(pathStart); } - function removeDuplicateSlashes(path) { - return path.indexOf("//") !== -1 ? path.replace(REMOVE_DUPLICATE_SLASHES_REGEXP, "/") : path; + function removeDuplicateSlashes(path2) { + return path2.indexOf("//") !== -1 ? path2.replace(REMOVE_DUPLICATE_SLASHES_REGEXP, "/") : path2; } - function trimLastSlash(path) { - if (path.length > 1 && path.charCodeAt(path.length - 1) === 47) { - return path.slice(0, -1); + function trimLastSlash(path2) { + if (path2.length > 1 && path2.charCodeAt(path2.length - 1) === 47) { + return path2.slice(0, -1); } - return path; + return path2; } function trimRegExpStartAndEnd(regexString) { if (regexString.charCodeAt(1) === 94) { @@ -47542,22 +47542,22 @@ var require_find_my_way = __commonJS({ } return regexString; } - function getClosingParenthensePosition(path, idx) { + function getClosingParenthensePosition(path2, idx) { let parentheses = 1; - while (idx < path.length) { + while (idx < path2.length) { idx++; - if (path.charCodeAt(idx) === 92) { + if (path2.charCodeAt(idx) === 92) { idx++; continue; } - if (path.charCodeAt(idx) === 41) { + if (path2.charCodeAt(idx) === 41) { parentheses--; - } else if (path.charCodeAt(idx) === 40) { + } else if (path2.charCodeAt(idx) === 40) { parentheses++; } if (!parentheses) return idx; } - throw new TypeError('Invalid regexp expression in "' + path + '"'); + throw new TypeError('Invalid regexp expression in "' + path2 + '"'); } function defaultBuildPrettyMeta(route) { if (!route) return {}; @@ -47790,12 +47790,12 @@ var require_route = __commonJS({ function route({ options: options2, isFastify }) { throwIfAlreadyStarted("Cannot add route!"); const opts = { ...options2 }; - const path = opts.url || opts.path || ""; + const path2 = opts.url || opts.path || ""; if (!opts.handler) { - throw new FST_ERR_ROUTE_MISSING_HANDLER(opts.method, path); + throw new FST_ERR_ROUTE_MISSING_HANDLER(opts.method, path2); } if (opts.errorHandler !== void 0 && typeof opts.errorHandler !== "function") { - throw new FST_ERR_ROUTE_HANDLER_NOT_FN(opts.method, path); + throw new FST_ERR_ROUTE_HANDLER_NOT_FN(opts.method, path2); } validateBodyLimitOption(opts.bodyLimit); validateHandlerTimeoutOption(opts.handlerTimeout); @@ -47805,22 +47805,22 @@ var require_route = __commonJS({ if (Array.isArray(opts.method)) { for (let i = 0; i < opts.method.length; ++i) { opts.method[i] = normalizeAndValidateMethod.call(this, opts.method[i]); - validateSchemaBodyOption.call(this, opts.method[i], path, opts.schema); + validateSchemaBodyOption.call(this, opts.method[i], path2, opts.schema); isGetRoute = opts.method.includes("GET"); isHeadRoute = opts.method.includes("HEAD"); } } else { opts.method = normalizeAndValidateMethod.call(this, opts.method); - validateSchemaBodyOption.call(this, opts.method, path, opts.schema); + validateSchemaBodyOption.call(this, opts.method, path2, opts.schema); isGetRoute = opts.method === "GET"; isHeadRoute = opts.method === "HEAD"; } const headOpts = shouldExposeHead && isGetRoute ? { ...options2 } : null; const prefix = this[kRoutePrefix]; - if (path === "/" && prefix.length > 0 && opts.method !== "HEAD") { + if (path2 === "/" && prefix.length > 0 && opts.method !== "HEAD") { switch (opts.prefixTrailingSlash) { case "slash": - addNewRoute.call(this, { path, isFastify }); + addNewRoute.call(this, { path: path2, isFastify }); break; case "no-slash": addNewRoute.call(this, { path: "", isFastify }); @@ -47829,20 +47829,20 @@ var require_route = __commonJS({ default: addNewRoute.call(this, { path: "", isFastify }); if (ignoreTrailingSlash !== true && (ignoreDuplicateSlashes !== true || !prefix.endsWith("/"))) { - addNewRoute.call(this, { path, prefixing: true, isFastify }); + addNewRoute.call(this, { path: path2, prefixing: true, isFastify }); } } - } else if (path[0] === "/" && prefix.endsWith("/")) { - addNewRoute.call(this, { path: path.slice(1), isFastify }); + } else if (path2[0] === "/" && prefix.endsWith("/")) { + addNewRoute.call(this, { path: path2.slice(1), isFastify }); } else { - addNewRoute.call(this, { path, isFastify }); + addNewRoute.call(this, { path: path2, isFastify }); } return this; - function addNewRoute({ path: path2, prefixing = false, isFastify: isFastify2 = false }) { - const url2 = prefix + path2; + function addNewRoute({ path: path3, prefixing = false, isFastify: isFastify2 = false }) { + const url2 = prefix + path3; opts.url = url2; opts.path = url2; - opts.routePath = path2; + opts.routePath = path3; opts.prefix = prefix; opts.logLevel = opts.logLevel || this[kLogLevel]; validateLogLevelOption(opts.logLevel, opts.method, opts.url, logger2); @@ -47975,7 +47975,7 @@ var require_route = __commonJS({ }); if (shouldExposeHead && isGetRoute && !isHeadRoute && !hasHEADHandler) { const onSendHandlers = parseHeadOnSendHandlers(headOpts.onSend); - prepareRoute.call(this, { method: "HEAD", url: path2, options: { ...headOpts, onSend: onSendHandlers }, isFastify: true }); + prepareRoute.call(this, { method: "HEAD", url: path3, options: { ...headOpts, onSend: onSendHandlers }, isFastify: true }); } } } @@ -48099,9 +48099,9 @@ var require_route = __commonJS({ } return method; } - function validateSchemaBodyOption(method, path, schema) { + function validateSchemaBodyOption(method, path2, schema) { if (this[kSupportedHTTPMethods].bodyless.has(method) && schema?.body) { - throw new FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED(method, path); + throw new FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED(method, path2); } } function validateBodyLimitOption(bodyLimit) { @@ -48116,11 +48116,11 @@ var require_route = __commonJS({ throw new FST_ERR_ROUTE_HANDLER_TIMEOUT_OPTION_NOT_INT(handlerTimeout); } } - function validateLogLevelOption(logLevel, method, path, logger2) { + function validateLogLevelOption(logLevel, method, path2, logger2) { if (logLevel == null || logLevel === "") return; if (logger2?.levels?.values == null) return; if (typeof logLevel !== "string" || logger2.levels.values[logLevel] === void 0) { - throw new FST_ERR_ROUTE_LOG_LEVEL_INVALID(method, path, logLevel); + throw new FST_ERR_ROUTE_LOG_LEVEL_INVALID(method, path2, logLevel); } } function runPreParsing(err, request, reply) { @@ -48165,7 +48165,7 @@ var require_four_oh_four = __commonJS({ "use strict"; var FindMyWay = require_find_my_way(); var Reply = require_reply(); - var Request = require_request(); + var Request2 = require_request(); var Context = require_context(); var { kRoutePrefix, @@ -48281,7 +48281,7 @@ var require_four_oh_four = __commonJS({ const fourOhFourContext = this[kFourOhFourLevelInstance][kFourOhFourContext]; const id = getGenReqId(fourOhFourContext.server, req); const childLogger = createChildLogger(fourOhFourContext, logger2, req, id); - const request = new Request(id, null, req, null, childLogger, fourOhFourContext); + const request = new Request2(id, null, req, null, childLogger, fourOhFourContext); const reply = new Reply(res, request, childLogger); fourOhFourContext.server[kLogController].incomingRequest(request, reply); request.log.warn("the default handler for 404 did not catch this, this is likely a fastify bug, please report it"); @@ -48313,7 +48313,7 @@ var require_plugin_override = __commonJS({ kErrorHandlerAlreadySet } = require_symbols3(); var Reply = require_reply(); - var Request = require_request(); + var Request2 = require_request(); var SchemaController = require_schema_controller(); var ContentTypeParser = require_content_type_parser(); var { buildHooks } = require_hooks(); @@ -48330,7 +48330,7 @@ var require_plugin_override = __commonJS({ instance.ready = old[kAvvioBoot].bind(instance); instance[kChildren] = []; instance[kReply] = Reply.buildReply(instance[kReply]); - instance[kRequest] = Request.buildRequest(instance[kRequest]); + instance[kRequest] = Request2.buildRequest(instance[kRequest]); instance[kContentTypeParser] = ContentTypeParser.helpers.buildContentTypeParser(instance[kContentTypeParser]); instance[kHooks] = buildHooks(instance[kHooks]); instance[kRoutePrefix] = buildRoutePrefix(instance[kRoutePrefix], opts.prefix); @@ -48771,7 +48771,7 @@ var require_request2 = __commonJS({ var { Readable, addAbortSignal } = __require("node:stream"); var util = __require("node:util"); var cookie = require_dist5(); - var assert3 = __require("node:assert"); + var assert4 = __require("node:assert"); var { createDeprecation } = require_process_warning2(); var parseURL = require_parse_url(); var { isFormDataLike, formDataToStream } = require_form_data(); @@ -48793,19 +48793,19 @@ var require_request2 = __commonJS({ function CustomRequest(options) { return new _CustomLMRRequest(this); function _CustomLMRRequest(obj2) { - Request.call(obj2, { + Request2.call(obj2, { ...options, Request: void 0 }); Object.assign(this, obj2); - for (const fn of Object.keys(Request.prototype)) { - this.constructor.prototype[fn] = Request.prototype[fn]; + for (const fn of Object.keys(Request2.prototype)) { + this.constructor.prototype[fn] = Request2.prototype[fn]; } util.inherits(this.constructor, options.Request); return this; } } - function Request(options) { + function Request2(options) { Readable.call(this, { autoDestroy: false }); @@ -48826,7 +48826,7 @@ var require_request2 = __commonJS({ continue; } const value = headers[field]; - assert3(value !== void 0, 'invalid value "undefined" for header ' + field); + assert4(value !== void 0, 'invalid value "undefined" for header ' + field); this.headers[fieldLowerCase] = "" + value; } if ("user-agent" in this.headers === false) { @@ -48938,9 +48938,9 @@ var require_request2 = __commonJS({ } }); } - util.inherits(Request, Readable); - util.inherits(CustomRequest, Request); - Request.prototype.destroy = function(error62) { + util.inherits(Request2, Readable); + util.inherits(CustomRequest, Request2); + Request2.prototype.destroy = function(error62) { if (this.destroyed || this._lightMyRequest.isDone) return; this.destroyed = true; if (error62) { @@ -48949,8 +48949,8 @@ var require_request2 = __commonJS({ } process.nextTick(() => this.emit("close")); }; - module2.exports = Request; - module2.exports.Request = Request; + module2.exports = Request2; + module2.exports.Request = Request2; module2.exports.CustomRequest = CustomRequest; } }); @@ -49086,7 +49086,7 @@ var require_set_cookie = __commonJS({ var cookiesStrings = []; var pos = 0; var start; - var ch; + var ch2; var lastComma; var nextStart; var cookiesSeparatorFound; @@ -49097,15 +49097,15 @@ var require_set_cookie = __commonJS({ return pos < cookiesString.length; } function notSpecialChar() { - ch = cookiesString.charAt(pos); - return ch !== "=" && ch !== ";" && ch !== ","; + ch2 = cookiesString.charAt(pos); + return ch2 !== "=" && ch2 !== ";" && ch2 !== ","; } while (pos < cookiesString.length) { start = pos; cookiesSeparatorFound = false; while (skipWhitespace()) { - ch = cookiesString.charAt(pos); - if (ch === ",") { + ch2 = cookiesString.charAt(pos); + if (ch2 === ",") { lastComma = pos; pos += 1; skipWhitespace(); @@ -50165,8 +50165,8 @@ var require_config_validator2 = __commonJS({ var require_light_my_request = __commonJS({ "node_modules/.pnpm/light-my-request@6.6.0/node_modules/light-my-request/index.js"(exports2, module2) { "use strict"; - var assert3 = __require("node:assert"); - var Request = require_request2(); + var assert4 = __require("node:assert"); + var Request2 = require_request2(); var Response2 = require_response(); var errorMessage = "The dispatch function has already been invoked"; var optsValidator = require_config_validator2(); @@ -50207,14 +50207,14 @@ var require_light_my_request = __commonJS({ function doInject(dispatchFunc, options, callback) { options = typeof options === "string" ? { url: options } : options; if (options.validate !== false) { - assert3(typeof dispatchFunc === "function", "dispatchFunc should be a function"); + assert4(typeof dispatchFunc === "function", "dispatchFunc should be a function"); const isOptionValid = optsValidator(options); if (!isOptionValid) { throw new Error(optsValidator.errors.map((e) => e.message)); } } const server = options.server || {}; - const RequestConstructor = options.Request ? Request.CustomRequest : Request; + const RequestConstructor = options.Request ? Request2.CustomRequest : Request2; if (dispatchFunc.request && dispatchFunc.request.app === dispatchFunc) { Object.setPrototypeOf(Object.getPrototypeOf(dispatchFunc.request), RequestConstructor.prototype); Object.setPrototypeOf(Object.getPrototypeOf(dispatchFunc.response), Response2.prototype); @@ -50310,7 +50310,7 @@ var require_light_my_request = __commonJS({ }; }); function isInjection(obj2) { - return obj2 instanceof Request || obj2 instanceof Response2 || obj2?.constructor?.name === "_CustomLMRRequest"; + return obj2 instanceof Request2 || obj2 instanceof Response2 || obj2?.constructor?.name === "_CustomLMRRequest"; } module2.exports = inject; module2.exports.default = inject; @@ -50359,7 +50359,7 @@ var require_fastify = __commonJS({ } = require_symbols3(); var { createServer } = require_server(); var Reply = require_reply(); - var Request = require_request(); + var Request2 = require_request(); var Context = require_context(); var decorator = require_decorate(); var ContentTypeParser = require_content_type_parser(); @@ -50471,7 +50471,7 @@ var require_fastify = __commonJS({ options.onConstructorPoisoning || defaultInitOptions.onConstructorPoisoning ), [kReply]: Reply.buildReply(Reply), - [kRequest]: Request.buildRequest(Request, options.trustProxy), + [kRequest]: Request2.buildRequest(Request2, options.trustProxy), [kFourOhFour]: fourOhFour, [pluginUtils.kRegisteredPlugins]: [], [kPluginNameChain]: ["fastify"], @@ -50501,7 +50501,7 @@ var require_fastify = __commonJS({ put: function _put(url2, options2, handler) { return router.prepareRoute.call(this, { method: "PUT", url: url2, options: options2, handler }); }, - options: function _options(url2, options2, handler) { + options: function _options2(url2, options2, handler) { return router.prepareRoute.call(this, { method: "OPTIONS", url: url2, options: options2, handler }); }, query: function _query(url2, options2, handler) { @@ -50865,19 +50865,19 @@ var require_fastify = __commonJS({ } fourOhFour.router.lookup(req, res); } - function onBadUrl(path, req, res) { + function onBadUrl(path2, req, res) { if (options.frameworkErrors) { const id = getGenReqId(routeEventContext.server, req); const childLogger = createChildLogger(routeEventContext, options.logger, req, id); - const request = new Request(id, null, req, null, childLogger, routeEventContext); + const request = new Request2(id, null, req, null, childLogger, routeEventContext); const reply = new Reply(res, request, childLogger); routeEventContext.server[kLogController].incomingRequest(request, reply); - return options.frameworkErrors(new FST_ERR_BAD_URL(path), request, reply); + return options.frameworkErrors(new FST_ERR_BAD_URL(path2), request, reply); } const body = JSON.stringify({ error: "Bad Request", code: "FST_ERR_BAD_URL", - message: `'${path}' is not a valid url component`, + message: `'${path2}' is not a valid url component`, statusCode: 400 }); res.writeHead(400, { @@ -50886,19 +50886,19 @@ var require_fastify = __commonJS({ }); res.end(body); } - function onMaxParamLength(path, req, res) { + function onMaxParamLength(path2, req, res) { if (options.frameworkErrors) { const id = getGenReqId(routeEventContext.server, req); const childLogger = createChildLogger(routeEventContext, options.logger, req, id); - const request = new Request(id, null, req, null, childLogger, routeEventContext); + const request = new Request2(id, null, req, null, childLogger, routeEventContext); const reply = new Reply(res, request, childLogger); routeEventContext.server[kLogController].incomingRequest(request, reply); - return options.frameworkErrors(new FST_ERR_MAX_PARAM_LENGTH(path), request, reply); + return options.frameworkErrors(new FST_ERR_MAX_PARAM_LENGTH(path2), request, reply); } const body = JSON.stringify({ error: "Bad Request", code: "FST_ERR_MAX_PARAM_LENGTH", - message: `'${path}' is exceeding the max param length`, + message: `'${path2}' is exceeding the max param length`, statusCode: 414 }); res.writeHead(414, { @@ -50914,7 +50914,7 @@ var require_fastify = __commonJS({ if (options.frameworkErrors) { const id = getGenReqId(routeEventContext.server, req); const childLogger = createChildLogger(routeEventContext, options.logger, req, id); - const request = new Request(id, null, req, null, childLogger, routeEventContext); + const request = new Request2(id, null, req, null, childLogger, routeEventContext); const reply = new Reply(res, request, childLogger); routeEventContext.server[kLogController].incomingRequest(request, reply); return options.frameworkErrors(new FST_ERR_ASYNC_CONSTRAINT(), request, reply); @@ -51699,8 +51699,8 @@ var require_registry = __commonJS({ } async getMetricsAsString(metrics2) { const metric = typeof metrics2.getForPromString === "function" ? await metrics2.getForPromString() : await metrics2.get(); - const name = escapeString(metric.name); - const help = `# HELP ${name} ${escapeString(metric.help)}`; + const name = escapeString2(metric.name); + const help = `# HELP ${name} ${escapeString2(metric.help)}`; const type = `# TYPE ${name} ${metric.type}`; const values3 = [help, type]; let defaultLabelNames = Object.keys(this._defaultLabels); @@ -51901,9 +51901,9 @@ var require_registry = __commonJS({ if (typeof str !== "string") { return str; } - return escapeString(str).replace(/"/g, '\\"'); + return escapeString2(str).replace(/"/g, '\\"'); } - function escapeString(str) { + function escapeString2(str) { return str.replace(/\\/g, "\\\\").replace(/\n/g, "\\n"); } function standardizeCounterName(name) { @@ -54105,43 +54105,43 @@ var init_NoopMeter = __esm({ /** * @see {@link Meter.createGauge} */ - createGauge(_name, _options) { + createGauge(_name, _options2) { return NOOP_GAUGE_METRIC; } /** * @see {@link Meter.createHistogram} */ - createHistogram(_name, _options) { + createHistogram(_name, _options2) { return NOOP_HISTOGRAM_METRIC; } /** * @see {@link Meter.createCounter} */ - createCounter(_name, _options) { + createCounter(_name, _options2) { return NOOP_COUNTER_METRIC; } /** * @see {@link Meter.createUpDownCounter} */ - createUpDownCounter(_name, _options) { + createUpDownCounter(_name, _options2) { return NOOP_UP_DOWN_COUNTER_METRIC; } /** * @see {@link Meter.createObservableGauge} */ - createObservableGauge(_name, _options) { + createObservableGauge(_name, _options2) { return NOOP_OBSERVABLE_GAUGE_METRIC; } /** * @see {@link Meter.createObservableCounter} */ - createObservableCounter(_name, _options) { + createObservableCounter(_name, _options2) { return NOOP_OBSERVABLE_COUNTER_METRIC; } /** * @see {@link Meter.createObservableUpDownCounter} */ - createObservableUpDownCounter(_name, _options) { + createObservableUpDownCounter(_name, _options2) { return NOOP_OBSERVABLE_UP_DOWN_COUNTER_METRIC; } /** @@ -54158,19 +54158,19 @@ var init_NoopMeter = __esm({ NoopMetric = class { }; NoopCounterMetric = class extends NoopMetric { - add(_value, _attributes) { + add(_value, _attributes2) { } }; NoopUpDownCounterMetric = class extends NoopMetric { - add(_value, _attributes) { + add(_value, _attributes2) { } }; NoopGaugeMetric = class extends NoopMetric { - record(_value, _attributes) { + record(_value, _attributes2) { } }; NoopHistogramMetric = class extends NoopMetric { - record(_value, _attributes) { + record(_value, _attributes2) { } }; NoopObservableMetric = class { @@ -54371,11 +54371,11 @@ var init_NonRecordingSpan = __esm({ return this; } // By default does nothing - setAttributes(_attributes) { + setAttributes(_attributes2) { return this; } // By default does nothing - addEvent(_name, _attributes) { + addEvent(_name, _attributes2) { return this; } addLink(_link) { @@ -54638,7 +54638,7 @@ var init_ProxyTracer = __esm({ startSpan(name, options, context2) { return this._getTracer().startSpan(name, options, context2); } - startActiveSpan(_name, _options, _context, _fn) { + startActiveSpan(_name, _options2, _context, _fn) { const tracer2 = this._getTracer(); return Reflect.apply(tracer2.startActiveSpan, tracer2, arguments); } @@ -54667,7 +54667,7 @@ var init_NoopTracerProvider = __esm({ "node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/trace/NoopTracerProvider.js"() { init_NoopTracer(); NoopTracerProvider = class { - getTracer(_name, _version, _options) { + getTracer(_name, _version, _options2) { return new NoopTracer(); } }; @@ -54868,7 +54868,7 @@ var init_NoopMeterProvider = __esm({ "node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/metrics/NoopMeterProvider.js"() { init_NoopMeter(); NoopMeterProvider = class { - getMeter(_name, _version, _options) { + getMeter(_name, _version, _options2) { return NOOP_METER; } }; @@ -57724,8 +57724,8 @@ var init_tap = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/toPath.js -function toPath(path) { - return isArray_default(path) ? path : [path]; +function toPath(path2) { + return isArray_default(path2) ? path2 : [path2]; } var init_toPath = __esm({ "node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/toPath.js"() { @@ -57736,8 +57736,8 @@ var init_toPath = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/_toPath.js -function toPath2(path) { - return _.toPath(path); +function toPath2(path2) { + return _.toPath(path2); } var init_toPath2 = __esm({ "node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/_toPath.js"() { @@ -57747,11 +57747,11 @@ var init_toPath2 = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/_deepGet.js -function deepGet(obj2, path) { - var length = path.length; +function deepGet(obj2, path2) { + var length = path2.length; for (var i = 0; i < length; i++) { if (obj2 == null) return void 0; - obj2 = obj2[path[i]]; + obj2 = obj2[path2[i]]; } return length ? obj2 : void 0; } @@ -57761,8 +57761,8 @@ var init_deepGet = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/get.js -function get(object3, path, defaultValue) { - var value = deepGet(object3, toPath2(path)); +function get(object3, path2, defaultValue) { + var value = deepGet(object3, toPath2(path2)); return isUndefined(value) ? defaultValue : value; } var init_get = __esm({ @@ -57774,11 +57774,11 @@ var init_get = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/has.js -function has2(obj2, path) { - path = toPath2(path); - var length = path.length; +function has2(obj2, path2) { + path2 = toPath2(path2); + var length = path2.length; for (var i = 0; i < length; i++) { - var key = path[i]; + var key = path2[i]; if (!has(obj2, key)) return false; obj2 = obj2[key]; } @@ -57815,10 +57815,10 @@ var init_matcher = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/property.js -function property(path) { - path = toPath2(path); +function property(path2) { + path2 = toPath2(path2); return function(obj2) { - return deepGet(obj2, path); + return deepGet(obj2, path2); }; } var init_property = __esm({ @@ -57927,8 +57927,8 @@ var init_noop = __esm({ // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/propertyOf.js function propertyOf(obj2) { if (obj2 == null) return noop3; - return function(path) { - return get(obj2, path); + return function(path2) { + return get(obj2, path2); }; } var init_propertyOf = __esm({ @@ -58122,14 +58122,14 @@ var init_template = __esm({ }); // node_modules/.pnpm/underscore@1.13.8/node_modules/underscore/modules/result.js -function result(obj2, path, fallback) { - path = toPath2(path); - var length = path.length; +function result(obj2, path2, fallback) { + path2 = toPath2(path2); + var length = path2.length; if (!length) { return isFunction_default(fallback) ? fallback.call(obj2) : fallback; } for (var i = 0; i < length; i++) { - var prop = obj2 == null ? void 0 : obj2[path[i]]; + var prop = obj2 == null ? void 0 : obj2[path2[i]]; if (prop === void 0) { prop = fallback; i = length; @@ -58812,14 +58812,14 @@ var init_invoke = __esm({ init_map(); init_deepGet(); init_toPath2(); - invoke_default = restArguments(function(obj2, path, args) { + invoke_default = restArguments(function(obj2, path2, args) { var contextPath, func; - if (isFunction_default(path)) { - func = path; + if (isFunction_default(path2)) { + func = path2; } else { - path = toPath2(path); - contextPath = path.slice(0, -1); - path = path[path.length - 1]; + path2 = toPath2(path2); + contextPath = path2.slice(0, -1); + path2 = path2[path2.length - 1]; } return map2(obj2, function(context2) { var method = func; @@ -58828,7 +58828,7 @@ var init_invoke = __esm({ context2 = deepGet(context2, contextPath); } if (context2 == null) return void 0; - method = context2[path]; + method = context2[path2]; } return method == null ? method : method.apply(context2, args); }); @@ -61146,7 +61146,7 @@ var require_debuggability = __commonJS({ return (this._bitField & 1048576) > 0; }; Promise2.prototype._warn = function(message2, shouldUseOwnTrace, promise2) { - return warn2(message2, shouldUseOwnTrace, promise2 || this); + return warn3(message2, shouldUseOwnTrace, promise2 || this); }; Promise2.onPossiblyUnhandledRejection = function(fn) { var domain2 = getDomain(); @@ -61491,9 +61491,9 @@ var require_debuggability = __commonJS({ function deprecated2(name, replacement) { var message2 = name + " is deprecated and will be removed in a future version."; if (replacement) message2 += " Use " + replacement + " instead."; - return warn2(message2); + return warn3(message2); } - function warn2(message2, shouldUseOwnTrace, promise2) { + function warn3(message2, shouldUseOwnTrace, promise2) { if (!config2.warnings) return; var warning = new Warning(message2); var ctx; @@ -61699,9 +61699,9 @@ var require_debuggability = __commonJS({ } shouldIgnore = function(line2) { if (bluebirdFramePattern.test(line2)) return true; - var info2 = parseLineInfo(line2); - if (info2) { - if (info2.fileName === firstFileName && (firstIndex <= info2.line && info2.line <= lastIndex)) { + var info3 = parseLineInfo(line2); + if (info3) { + if (info3.fileName === firstFileName && (firstIndex <= info3.line && info3.line <= lastIndex)) { return true; } } @@ -61883,7 +61883,7 @@ var require_debuggability = __commonJS({ }, checkForgottenReturns, setBounds, - warn: warn2, + warn: warn3, deprecated: deprecated2, CapturedTrace, fireDomEvent, @@ -65030,7 +65030,7 @@ var require_promises = __commonJS({ var require_documents = __commonJS({ "node_modules/.pnpm/mammoth@1.12.3/node_modules/mammoth/lib/documents.js"(exports2) { var _3 = (init_index_all(), __toCommonJS(index_all_exports)); - var types2 = exports2.types = { + var types3 = exports2.types = { document: "document", paragraph: "paragraph", run: "run", @@ -65052,7 +65052,7 @@ var require_documents = __commonJS({ function Document(children, options) { options = options || {}; return { - type: types2.document, + type: types3.document, children, notes: options.notes || new Notes({}), comments: options.comments || [] @@ -65062,7 +65062,7 @@ var require_documents = __commonJS({ properties = properties || {}; var indent = properties.indent || {}; return { - type: types2.paragraph, + type: types3.paragraph, children, styleId: properties.styleId || null, styleName: properties.styleName || null, @@ -65079,7 +65079,7 @@ var require_documents = __commonJS({ function Run(children, properties) { properties = properties || {}; return { - type: types2.run, + type: types3.run, children, styleId: properties.styleId || null, styleName: properties.styleName || null, @@ -65100,26 +65100,26 @@ var require_documents = __commonJS({ superscript: "superscript", subscript: "subscript" }; - function Text(value) { + function Text2(value) { return { - type: types2.text, + type: types3.text, value }; } function Tab() { return { - type: types2.tab + type: types3.tab }; } function Checkbox(options) { return { - type: types2.checkbox, + type: types3.checkbox, checked: options.checked }; } function Hyperlink(children, options) { return { - type: types2.hyperlink, + type: types3.hyperlink, children, href: options.href, anchor: options.anchor, @@ -65128,7 +65128,7 @@ var require_documents = __commonJS({ } function NoteReference(options) { return { - type: types2.noteReference, + type: types3.noteReference, noteType: options.noteType, noteId: options.noteId }; @@ -65146,7 +65146,7 @@ var require_documents = __commonJS({ }; function Note(options) { return { - type: types2.note, + type: types3.note, noteType: options.noteType, noteId: options.noteId, body: options.body @@ -65154,13 +65154,13 @@ var require_documents = __commonJS({ } function commentReference(options) { return { - type: types2.commentReference, + type: types3.commentReference, commentId: options.commentId }; } function comment(options) { return { - type: types2.comment, + type: types3.comment, commentId: options.commentId, body: options.body, authorName: options.authorName, @@ -65170,9 +65170,9 @@ var require_documents = __commonJS({ function noteKey(noteType, id) { return noteType + "-" + id; } - function Image2(options) { + function Image3(options) { return { - type: types2.image, + type: types3.image, // `read` is retained for backwards compatibility, but other read // methods should be preferred. read: function(encoding) { @@ -65202,7 +65202,7 @@ var require_documents = __commonJS({ function Table3(children, properties) { properties = properties || {}; return { - type: types2.table, + type: types3.table, children, styleId: properties.styleId || null, styleName: properties.styleName || null @@ -65211,7 +65211,7 @@ var require_documents = __commonJS({ function TableRow(children, options) { options = options || {}; return { - type: types2.tableRow, + type: types3.tableRow, children, isHeader: options.isHeader || false }; @@ -65219,28 +65219,28 @@ var require_documents = __commonJS({ function TableCell(children, options) { options = options || {}; return { - type: types2.tableCell, + type: types3.tableCell, children, colSpan: options.colSpan == null ? 1 : options.colSpan, rowSpan: options.rowSpan == null ? 1 : options.rowSpan }; } - function Break(breakType) { + function Break2(breakType) { return { - type: types2["break"], + type: types3["break"], breakType }; } function BookmarkStart(options) { return { - type: types2.bookmarkStart, + type: types3.bookmarkStart, name: options.name }; } exports2.document = exports2.Document = Document; exports2.paragraph = exports2.Paragraph = Paragraph; exports2.run = exports2.Run = Run; - exports2.text = exports2.Text = Text; + exports2.text = exports2.Text = Text2; exports2.tab = exports2.Tab = Tab; exports2.checkbox = exports2.Checkbox = Checkbox; exports2.Hyperlink = Hyperlink; @@ -65249,13 +65249,13 @@ var require_documents = __commonJS({ exports2.Note = Note; exports2.commentReference = commentReference; exports2.comment = comment; - exports2.Image = Image2; + exports2.Image = Image3; exports2.Table = Table3; exports2.TableRow = TableRow; exports2.TableCell = TableCell; - exports2.lineBreak = Break("line"); - exports2.pageBreak = Break("page"); - exports2.columnBreak = Break("column"); + exports2.lineBreak = Break2("line"); + exports2.pageBreak = Break2("page"); + exports2.columnBreak = Break2("column"); exports2.BookmarkStart = BookmarkStart; exports2.verticalAlignment = verticalAlignment; } @@ -65837,7 +65837,7 @@ var require_stream_writable = __commonJS({ var internalUtil = { deprecate: require_node2() }; - var Stream3 = require_stream(); + var Stream4 = require_stream(); var Buffer2 = require_safe_buffer().Buffer; var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() { }; @@ -65848,7 +65848,7 @@ var require_stream_writable = __commonJS({ return Buffer2.isBuffer(obj2) || obj2 instanceof OurUint8Array; } var destroyImpl = require_destroy(); - util.inherits(Writable, Stream3); + util.inherits(Writable, Stream4); function nop() { } function WritableState(options, stream) { @@ -65938,7 +65938,7 @@ var require_stream_writable = __commonJS({ if (typeof options.destroy === "function") this._destroy = options.destroy; if (typeof options.final === "function") this._final = options.final; } - Stream3.call(this); + Stream4.call(this); } Writable.prototype.pipe = function() { this.emit("error", new Error("Cannot pipe, not readable")); @@ -66583,7 +66583,7 @@ var require_stream_readable = __commonJS({ var EElistenerCount = function(emitter, type) { return emitter.listeners(type).length; }; - var Stream3 = require_stream(); + var Stream4 = require_stream(); var Buffer2 = require_safe_buffer().Buffer; var OurUint8Array = (typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : {}).Uint8Array || function() { }; @@ -66606,7 +66606,7 @@ var require_stream_readable = __commonJS({ var BufferList = require_BufferList(); var destroyImpl = require_destroy(); var StringDecoder; - util.inherits(Readable, Stream3); + util.inherits(Readable, Stream4); var kProxyEvents = ["error", "close", "destroy", "pause", "resume"]; function prependListener(emitter, event, fn) { if (typeof emitter.prependListener === "function") return emitter.prependListener(event, fn); @@ -66661,7 +66661,7 @@ var require_stream_readable = __commonJS({ if (typeof options.read === "function") this._read = options.read; if (typeof options.destroy === "function") this._destroy = options.destroy; } - Stream3.call(this); + Stream4.call(this); } Object.defineProperty(Readable.prototype, "destroyed", { get: function() { @@ -67035,7 +67035,7 @@ var require_stream_readable = __commonJS({ return this; }; Readable.prototype.on = function(ev, fn) { - var res = Stream3.prototype.on.call(this, ev, fn); + var res = Stream4.prototype.on.call(this, ev, fn); if (ev === "data") { if (this._readableState.flowing !== false) this.resume(); } else if (ev === "readable") { @@ -67260,11 +67260,11 @@ var require_stream_readable = __commonJS({ var require_stream_transform = __commonJS({ "node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/lib/_stream_transform.js"(exports2, module2) { "use strict"; - module2.exports = Transform; + module2.exports = Transform2; var Duplex = require_stream_duplex(); var util = Object.create(require_util5()); util.inherits = require_inherits(); - util.inherits(Transform, Duplex); + util.inherits(Transform2, Duplex); function afterTransform(er, data) { var ts = this._transformState; ts.transforming = false; @@ -67283,8 +67283,8 @@ var require_stream_transform = __commonJS({ this._read(rs.highWaterMark); } } - function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); + function Transform2(options) { + if (!(this instanceof Transform2)) return new Transform2(options); Duplex.call(this, options); this._transformState = { afterTransform: afterTransform.bind(this), @@ -67312,14 +67312,14 @@ var require_stream_transform = __commonJS({ done(this, null, null); } } - Transform.prototype.push = function(chunk2, encoding) { + Transform2.prototype.push = function(chunk2, encoding) { this._transformState.needTransform = false; return Duplex.prototype.push.call(this, chunk2, encoding); }; - Transform.prototype._transform = function(chunk2, encoding, cb2) { + Transform2.prototype._transform = function(chunk2, encoding, cb2) { throw new Error("_transform() is not implemented"); }; - Transform.prototype._write = function(chunk2, encoding, cb2) { + Transform2.prototype._write = function(chunk2, encoding, cb2) { var ts = this._transformState; ts.writecb = cb2; ts.writechunk = chunk2; @@ -67329,7 +67329,7 @@ var require_stream_transform = __commonJS({ if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); } }; - Transform.prototype._read = function(n) { + Transform2.prototype._read = function(n) { var ts = this._transformState; if (ts.writechunk !== null && ts.writecb && !ts.transforming) { ts.transforming = true; @@ -67338,7 +67338,7 @@ var require_stream_transform = __commonJS({ ts.needTransform = true; } }; - Transform.prototype._destroy = function(err, cb2) { + Transform2.prototype._destroy = function(err, cb2) { var _this2 = this; Duplex.prototype._destroy.call(this, err, function(err2) { cb2(err2); @@ -67361,13 +67361,13 @@ var require_stream_passthrough = __commonJS({ "node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/lib/_stream_passthrough.js"(exports2, module2) { "use strict"; module2.exports = PassThrough; - var Transform = require_stream_transform(); + var Transform2 = require_stream_transform(); var util = Object.create(require_util5()); util.inherits = require_inherits(); - util.inherits(PassThrough, Transform); + util.inherits(PassThrough, Transform2); function PassThrough(options) { if (!(this instanceof PassThrough)) return new PassThrough(options); - Transform.call(this, options); + Transform2.call(this, options); } PassThrough.prototype._transform = function(chunk2, encoding, cb2) { cb2(null, chunk2); @@ -67378,19 +67378,19 @@ var require_stream_passthrough = __commonJS({ // node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/readable.js var require_readable = __commonJS({ "node_modules/.pnpm/readable-stream@2.3.8/node_modules/readable-stream/readable.js"(exports2, module2) { - var Stream3 = __require("stream"); - if (process.env.READABLE_STREAM === "disable" && Stream3) { - module2.exports = Stream3; - exports2 = module2.exports = Stream3.Readable; - exports2.Readable = Stream3.Readable; - exports2.Writable = Stream3.Writable; - exports2.Duplex = Stream3.Duplex; - exports2.Transform = Stream3.Transform; - exports2.PassThrough = Stream3.PassThrough; - exports2.Stream = Stream3; + var Stream4 = __require("stream"); + if (process.env.READABLE_STREAM === "disable" && Stream4) { + module2.exports = Stream4; + exports2 = module2.exports = Stream4.Readable; + exports2.Readable = Stream4.Readable; + exports2.Writable = Stream4.Writable; + exports2.Duplex = Stream4.Duplex; + exports2.Transform = Stream4.Transform; + exports2.PassThrough = Stream4.PassThrough; + exports2.Stream = Stream4; } else { exports2 = module2.exports = require_stream_readable(); - exports2.Stream = Stream3 || exports2; + exports2.Stream = Stream4 || exports2; exports2.Readable = exports2; exports2.Writable = require_stream_writable(); exports2.Duplex = require_stream_duplex(); @@ -67420,8 +67420,8 @@ var require_support = __commonJS({ }).size === 0; } catch (e) { try { - Builder2 = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; - builder = new Builder2(); + Builder3 = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + builder = new Builder3(); builder.append(buffer2); exports2.blob = builder.getBlob("application/zip").size === 0; } catch (e2) { @@ -67430,7 +67430,7 @@ var require_support = __commonJS({ } } var buffer2; - var Builder2; + var Builder3; var builder; try { exports2.nodestream = !!require_readable().Readable; @@ -68107,8 +68107,8 @@ var require_utils3 = __commonJS({ }); } catch (e) { try { - var Builder2 = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; - var builder = new Builder2(); + var Builder3 = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; + var builder = new Builder3(); builder.append(part); return builder.getBlob(type); } catch (e2) { @@ -68294,8 +68294,8 @@ var require_utils3 = __commonJS({ var result2 = transform2[inputType][outputType](input2); return result2; }; - exports2.resolve = function(path) { - var parts = path.split("/"); + exports2.resolve = function(path2) { + var parts = path2.split("/"); var result2 = []; for (var index2 = 0; index2 < parts.length; index2++) { var part = parts[index2]; @@ -70722,7 +70722,7 @@ var require_deflate = __commonJS({ } return BS_BLOCK_DONE; } - function Config(good_length, max_lazy, nice_length, max_chain, func) { + function Config2(good_length, max_lazy, nice_length, max_chain, func) { this.good_length = good_length; this.max_lazy = max_lazy; this.nice_length = nice_length; @@ -70732,25 +70732,25 @@ var require_deflate = __commonJS({ var configuration_table; configuration_table = [ /* good lazy nice chain */ - new Config(0, 0, 0, 0, deflate_stored), + new Config2(0, 0, 0, 0, deflate_stored), /* 0 store only */ - new Config(4, 4, 8, 4, deflate_fast), + new Config2(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ - new Config(4, 5, 16, 8, deflate_fast), + new Config2(4, 5, 16, 8, deflate_fast), /* 2 */ - new Config(4, 6, 32, 32, deflate_fast), + new Config2(4, 6, 32, 32, deflate_fast), /* 3 */ - new Config(4, 4, 16, 16, deflate_slow), + new Config2(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ - new Config(8, 16, 32, 32, deflate_slow), + new Config2(8, 16, 32, 32, deflate_slow), /* 5 */ - new Config(8, 16, 128, 128, deflate_slow), + new Config2(8, 16, 128, 128, deflate_slow), /* 6 */ - new Config(8, 32, 128, 256, deflate_slow), + new Config2(8, 32, 128, 256, deflate_slow), /* 7 */ - new Config(32, 128, 258, 1024, deflate_slow), + new Config2(32, 128, 258, 1024, deflate_slow), /* 8 */ - new Config(32, 258, 258, 4096, deflate_slow) + new Config2(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ ]; function lm_init(s) { @@ -71496,7 +71496,7 @@ var require_deflate2 = __commonJS({ } Deflate.prototype.push = function(data, mode) { var strm = this.strm; - var chunkSize = this.options.chunkSize; + var chunkSize2 = this.options.chunkSize; var status, _mode; if (this.ended) { return false; @@ -71513,9 +71513,9 @@ var require_deflate2 = __commonJS({ strm.avail_in = strm.input.length; do { if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); + strm.output = new utils.Buf8(chunkSize2); strm.next_out = 0; - strm.avail_out = chunkSize; + strm.avail_out = chunkSize2; } status = zlib_deflate.deflate(strm, _mode); if (status !== Z_STREAM_END && status !== Z_OK) { @@ -73500,7 +73500,7 @@ var require_inflate2 = __commonJS({ } Inflate.prototype.push = function(data, mode) { var strm = this.strm; - var chunkSize = this.options.chunkSize; + var chunkSize2 = this.options.chunkSize; var dictionary = this.options.dictionary; var status, _mode; var next_out_utf8, tail, utf8str; @@ -73520,9 +73520,9 @@ var require_inflate2 = __commonJS({ strm.avail_in = strm.input.length; do { if (strm.avail_out === 0) { - strm.output = new utils.Buf8(chunkSize); + strm.output = new utils.Buf8(chunkSize2); strm.next_out = 0; - strm.avail_out = chunkSize; + strm.avail_out = chunkSize2; } status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); if (status === c.Z_NEED_DICT && dictionary) { @@ -73544,7 +73544,7 @@ var require_inflate2 = __commonJS({ tail = strm.next_out - next_out_utf8; utf8str = strings.buf2string(strm.output, next_out_utf8); strm.next_out = tail; - strm.avail_out = chunkSize - tail; + strm.avail_out = chunkSize2 - tail; if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } @@ -74156,18 +74156,18 @@ var require_object = __commonJS({ var object3 = new ZipObject(name, zipObjectContent, o); this.files[name] = object3; }; - var parentFolder = function(path) { - if (path.slice(-1) === "/") { - path = path.substring(0, path.length - 1); + var parentFolder = function(path2) { + if (path2.slice(-1) === "/") { + path2 = path2.substring(0, path2.length - 1); } - var lastSlash = path.lastIndexOf("/"); - return lastSlash > 0 ? path.substring(0, lastSlash) : ""; + var lastSlash = path2.lastIndexOf("/"); + return lastSlash > 0 ? path2.substring(0, lastSlash) : ""; }; - var forceTrailingSlash = function(path) { - if (path.slice(-1) !== "/") { - path += "/"; + var forceTrailingSlash = function(path2) { + if (path2.slice(-1) !== "/") { + path2 += "/"; } - return path; + return path2; }; var folderAdd = function(name, createFolders) { createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders; @@ -75205,27 +75205,27 @@ var require_zipfile = __commonJS({ }; }); } - function splitPath(path) { - var lastIndex = path.lastIndexOf("/"); + function splitPath(path2) { + var lastIndex = path2.lastIndexOf("/"); if (lastIndex === -1) { - return { dirname: "", basename: path }; + return { dirname: "", basename: path2 }; } else { return { - dirname: path.substring(0, lastIndex), - basename: path.substring(lastIndex + 1) + dirname: path2.substring(0, lastIndex), + basename: path2.substring(lastIndex + 1) }; } } function joinPath() { - var nonEmptyPaths = Array.prototype.filter.call(arguments, function(path) { - return path; + var nonEmptyPaths = Array.prototype.filter.call(arguments, function(path2) { + return path2; }); var relevantPaths = []; - nonEmptyPaths.forEach(function(path) { - if (/^\//.test(path)) { - relevantPaths = [path]; + nonEmptyPaths.forEach(function(path2) { + if (/^\//.test(path2)) { + relevantPaths = [path2]; } else { - relevantPaths.push(path); + relevantPaths.push(path2); } }); return relevantPaths.join("/"); @@ -75302,7 +75302,7 @@ var require_nodes = __commonJS({ var require_conventions = __commonJS({ "node_modules/.pnpm/@xmldom+xmldom@0.8.15/node_modules/@xmldom/xmldom/lib/conventions.js"(exports2) { "use strict"; - function find2(list, predicate, ac) { + function find3(list, predicate, ac) { if (ac === void 0) { ac = Array.prototype; } @@ -75433,7 +75433,7 @@ var require_conventions = __commonJS({ var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]"); var tagNamePattern = new RegExp("^" + nameStartChar.source + nameChar.source + "*(?::" + nameStartChar.source + nameChar.source + "*)?$"); exports2.assign = assign; - exports2.find = find2; + exports2.find = find3; exports2.freeze = freeze; exports2.MIME_TYPE = MIME_TYPE; exports2.NAMESPACE = NAMESPACE; @@ -75447,7 +75447,7 @@ var require_conventions = __commonJS({ var require_dom = __commonJS({ "node_modules/.pnpm/@xmldom+xmldom@0.8.15/node_modules/@xmldom/xmldom/lib/dom.js"(exports2) { var conventions = require_conventions(); - var find2 = conventions.find; + var find3 = conventions.find; var NAMESPACE = conventions.NAMESPACE; var tagNamePattern = conventions.tagNamePattern; function notEmptyString(input2) { @@ -76085,10 +76085,10 @@ var require_dom = __commonJS({ } function isElementInsertionPossible(doc, child) { var parentChildNodes = doc.childNodes || []; - if (find2(parentChildNodes, isElementNode) || isDocTypeNode(child)) { + if (find3(parentChildNodes, isElementNode) || isDocTypeNode(child)) { return false; } - var docTypeNode = find2(parentChildNodes, isDocTypeNode); + var docTypeNode = find3(parentChildNodes, isDocTypeNode); return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); } function isElementReplacementPossible(doc, child) { @@ -76096,10 +76096,10 @@ var require_dom = __commonJS({ function hasElementChildThatIsNotChild(node2) { return isElementNode(node2) && node2 !== child; } - if (find2(parentChildNodes, hasElementChildThatIsNotChild)) { + if (find3(parentChildNodes, hasElementChildThatIsNotChild)) { return false; } - var docTypeNode = find2(parentChildNodes, isDocTypeNode); + var docTypeNode = find3(parentChildNodes, isDocTypeNode); return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child)); } function assertPreInsertionValidity1to5(parent, node2, child) { @@ -76128,7 +76128,7 @@ var require_dom = __commonJS({ var nodeChildNodes = node2.childNodes || []; if (node2.nodeType === Node2.DOCUMENT_FRAGMENT_NODE) { var nodeChildElements = nodeChildNodes.filter(isElementNode); - if (nodeChildElements.length > 1 || find2(nodeChildNodes, isTextNode)) { + if (nodeChildElements.length > 1 || find3(nodeChildNodes, isTextNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "More than one element or text in fragment"); } if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) { @@ -76141,10 +76141,10 @@ var require_dom = __commonJS({ } } if (isDocTypeNode(node2)) { - if (find2(parentChildNodes, isDocTypeNode)) { + if (find3(parentChildNodes, isDocTypeNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one doctype is allowed"); } - var parentElementChild = find2(parentChildNodes, isElementNode); + var parentElementChild = find3(parentChildNodes, isElementNode); if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "Doctype can only be inserted before an element"); } @@ -76158,7 +76158,7 @@ var require_dom = __commonJS({ var nodeChildNodes = node2.childNodes || []; if (node2.nodeType === Node2.DOCUMENT_FRAGMENT_NODE) { var nodeChildElements = nodeChildNodes.filter(isElementNode); - if (nodeChildElements.length > 1 || find2(nodeChildNodes, isTextNode)) { + if (nodeChildElements.length > 1 || find3(nodeChildNodes, isTextNode)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "More than one element or text in fragment"); } if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) { @@ -76175,10 +76175,10 @@ var require_dom = __commonJS({ return isDocTypeNode(node3) && node3 !== child; }; var hasDoctypeChildThatIsNotChild = hasDoctypeChildThatIsNotChild2; - if (find2(parentChildNodes, hasDoctypeChildThatIsNotChild2)) { + if (find3(parentChildNodes, hasDoctypeChildThatIsNotChild2)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "Only one doctype is allowed"); } - var parentElementChild = find2(parentChildNodes, isElementNode); + var parentElementChild = find3(parentChildNodes, isElementNode); if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) { throw new DOMException(HIERARCHY_REQUEST_ERR, "Doctype can only be inserted before an element"); } @@ -76386,7 +76386,7 @@ var require_dom = __commonJS({ return node2; }, createTextNode: function(data) { - var node2 = new Text(); + var node2 = new Text2(); node2.ownerDocument = this; node2.appendData(data); return node2; @@ -76638,9 +76638,9 @@ var require_dom = __commonJS({ } }; _extends(CharacterData, Node2); - function Text() { + function Text2() { } - Text.prototype = { + Text2.prototype = { nodeName: "#text", nodeType: TEXT_NODE, splitText: function(offset) { @@ -76656,7 +76656,7 @@ var require_dom = __commonJS({ return newNode; } }; - _extends(Text, CharacterData); + _extends(Text2, CharacterData); function Comment2() { } Comment2.prototype = { @@ -79927,19 +79927,19 @@ var require_dom_parser = __commonJS({ this.locator && position(this.locator, ins); appendElement(this, ins); }, - ignorableWhitespace: function(ch, start, length) { + ignorableWhitespace: function(ch2, start, length) { }, - characters: function(chars, start, length) { - chars = _toString.apply(this, arguments); - if (chars) { + characters: function(chars2, start, length) { + chars2 = _toString.apply(this, arguments); + if (chars2) { if (this.cdata) { - var charNode = this.doc.createCDATASection(chars); + var charNode = this.doc.createCDATASection(chars2); } else { - var charNode = this.doc.createTextNode(chars); + var charNode = this.doc.createTextNode(chars2); } if (this.currentElement) { this.currentElement.appendChild(charNode); - } else if (/^\s*$/.test(chars)) { + } else if (/^\s*$/.test(chars2)) { this.doc.appendChild(charNode); } this.locator && position(this.locator, charNode); @@ -79956,9 +79956,9 @@ var require_dom_parser = __commonJS({ } }, //LexicalHandler - comment: function(chars, start, length) { - chars = _toString.apply(this, arguments); - var comm = this.doc.createComment(chars); + comment: function(chars2, start, length) { + chars2 = _toString.apply(this, arguments); + var comm = this.doc.createComment(chars2); this.locator && position(this.locator, comm); appendElement(this, comm); }, @@ -79996,14 +79996,14 @@ var require_dom_parser = __commonJS({ return "\n@" + (l2.systemId || "") + "#[line:" + l2.lineNumber + ",col:" + l2.columnNumber + "]"; } } - function _toString(chars, start, length) { - if (typeof chars == "string") { - return chars.substr(start, length); + function _toString(chars2, start, length) { + if (typeof chars2 == "string") { + return chars2.substr(start, length); } else { - if (chars.length >= start + length || start) { - return new java.lang.String(chars, start, length) + ""; + if (chars2.length >= start + length || start) { + return new java.lang.String(chars2, start, length) + ""; } - return chars; + return chars2; } } "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g, function(key) { @@ -82608,8 +82608,8 @@ var require_writer = __commonJS({ "node_modules/.pnpm/mammoth@1.12.3/node_modules/mammoth/lib/xml/writer.js"(exports2) { var _3 = (init_index_all(), __toCommonJS(index_all_exports)); var xmlbuilder = require_lib6(); - exports2.writeString = writeString; - function writeString(root2, namespaces) { + exports2.writeString = writeString2; + function writeString2(root2, namespaces) { var uriToPrefix = _3.invert(namespaces); var nodeWriters = { element: writeElement, @@ -82705,9 +82705,9 @@ var require_office_xml_reader = __commonJS({ return collapseAlternateContent(document2)[0]; }); } - function readXmlFromZipFile(docxFile, path) { - if (docxFile.exists(path)) { - return docxFile.read(path, "utf-8").then(stripUtf8Bom).then(read); + function readXmlFromZipFile(docxFile, path2) { + if (docxFile.exists(path2)) { + return docxFile.read(path2, "utf-8").then(stripUtf8Bom).then(read); } else { return promises.resolve(null); } @@ -84487,10 +84487,10 @@ var require_body_reader = __commonJS({ } } function findEmbeddedImageFile(relationshipId) { - var path = uris.uriToZipEntryName("word", relationships.findTargetByRelationshipId(relationshipId)); + var path2 = uris.uriToZipEntryName("word", relationships.findTargetByRelationshipId(relationshipId)); return { - path, - read: docxFile.read.bind(docxFile, path) + path: path2, + read: docxFile.read.bind(docxFile, path2) }; } function readImage(imageFile, altText) { @@ -84727,12 +84727,12 @@ var require_content_types_reader = __commonJS({ } function contentTypes(overrides, extensionDefaults) { return { - findContentType: function(path) { - var overrideContentType = overrides[path]; + findContentType: function(path2) { + var overrideContentType = overrides[path2]; if (overrideContentType) { return overrideContentType; } else { - var pathParts = path.split("."); + var pathParts = path2.split("."); var extension = pathParts[pathParts.length - 1]; if (Object.prototype.hasOwnProperty.call(extensionDefaults, extension)) { return extensionDefaults[extension]; @@ -84989,12 +84989,12 @@ var require_comments_reader = __commonJS({ var require_path_is_absolute = __commonJS({ "node_modules/.pnpm/path-is-absolute@1.0.1/node_modules/path-is-absolute/index.js"(exports2, module2) { "use strict"; - function posix(path) { - return path.charAt(0) === "/"; + function posix(path2) { + return path2.charAt(0) === "/"; } - function win32(path) { + function win32(path2) { var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/; - var result2 = splitDeviceRe.exec(path); + var result2 = splitDeviceRe.exec(path2); var device = result2[1] || ""; var isUnc = Boolean(device && device.charAt(1) !== ":"); return Boolean(result2[2] || isUnc); @@ -85028,19 +85028,19 @@ var require_files = __commonJS({ } var base = options.relativeToFile ? dirname2(options.relativeToFile) : null; function read(uri, encoding) { - return resolveUri(uri).then(function(path) { - return readFile2(path, encoding).caught(function(error62) { + return resolveUri(uri).then(function(path2) { + return readFile2(path2, encoding).caught(function(error62) { var message2 = "could not open external image: '" + uri + "' (document directory: '" + base + "')\n" + error62.message; return promises.reject(new Error(message2)); }); }); } function resolveUri(uri) { - var path = uriToPath(uri); - if (isAbsolutePath(path)) { - return promises.resolve(path); + var path2 = uriToPath(uri); + if (isAbsolutePath(path2)) { + return promises.resolve(path2); } else if (base) { - return promises.resolve(resolvePath(base, path)); + return promises.resolve(resolvePath(base, path2)); } else { return promises.reject(new Error("could not find external image '" + uri + "', path of input document is unknown")); } @@ -85056,11 +85056,11 @@ var require_files = __commonJS({ } var uri = url2.parse(uriString); if (isLocalFileUri(uri) || isRelativeUri(uri)) { - var path = decodeURIComponent(uri.path); - if (platform === "win32" && /^\/[a-z]:/i.test(path)) { - return path.slice(1); + var path2 = decodeURIComponent(uri.path); + if (platform === "win32" && /^\/[a-z]:/i.test(path2)) { + return path2.slice(1); } else { - return path; + return path2; } } else { throw new Error("Could not convert URI to path: " + uriString); @@ -85260,18 +85260,18 @@ var require_docx_reader = __commonJS({ readElement: contentTypesReader.readContentTypesFromXml, defaultValue: contentTypesReader.defaultContentTypes }); - function readNumberingFromZipFile(zipFile, path, styles) { + function readNumberingFromZipFile(zipFile, path2, styles) { return xmlFileReader({ - filename: path, + filename: path2, readElement: function(element) { return numberingXml.readNumberingXml(element, { styles }); }, defaultValue: numberingXml.defaultNumbering })(zipFile); } - function readStylesFromZipFile(zipFile, path) { + function readStylesFromZipFile(zipFile, path2) { return xmlFileReader({ - filename: path, + filename: path2, readElement: stylesReader.readStylesXml, defaultValue: stylesReader.defaultStyles })(zipFile); @@ -85302,10 +85302,10 @@ var require_style_map = __commonJS({ }); } function updateRelationships(docxFile) { - var path = "word/_rels/document.xml.rels"; + var path2 = "word/_rels/document.xml.rels"; var relationshipsUri = "http://schemas.openxmlformats.org/package/2006/relationships"; var relationshipElementName = "{" + relationshipsUri + "}Relationship"; - return docxFile.read(path, "utf8").then(xml.readString).then(function(relationshipsContainer) { + return docxFile.read(path2, "utf8").then(xml.readString).then(function(relationshipsContainer) { var relationships = relationshipsContainer.children; addOrUpdateElement(relationships, relationshipElementName, "Id", { "Id": "rMammothStyleMap", @@ -85313,21 +85313,21 @@ var require_style_map = __commonJS({ "Target": styleMapAbsolutePath }); var namespaces = { "": relationshipsUri }; - return docxFile.write(path, xml.writeString(relationshipsContainer, namespaces)); + return docxFile.write(path2, xml.writeString(relationshipsContainer, namespaces)); }); } function updateContentTypes(docxFile) { - var path = "[Content_Types].xml"; + var path2 = "[Content_Types].xml"; var contentTypesUri = "http://schemas.openxmlformats.org/package/2006/content-types"; var overrideName = "{" + contentTypesUri + "}Override"; - return docxFile.read(path, "utf8").then(xml.readString).then(function(typesElement) { + return docxFile.read(path2, "utf8").then(xml.readString).then(function(typesElement) { var children = typesElement.children; addOrUpdateElement(children, overrideName, "PartName", { "PartName": styleMapAbsolutePath, "ContentType": "text/prs.mammoth.style-map" }); var namespaces = { "": contentTypesUri }; - return docxFile.write(path, xml.writeString(typesElement, namespaces)); + return docxFile.write(path2, xml.writeString(typesElement, namespaces)); }); } function addOrUpdateElement(elements, name, identifyingAttribute, attributes) { @@ -85588,7 +85588,7 @@ var require_images = __commonJS({ "node_modules/.pnpm/mammoth@1.12.3/node_modules/mammoth/lib/images.js"(exports2) { var _3 = (init_index_all(), __toCommonJS(index_all_exports)); var promises = require_promises(); - var Html = require_html(); + var Html2 = require_html(); exports2.imgElement = imgElement; function imgElement(func) { return function(element, messages3) { @@ -85598,7 +85598,7 @@ var require_images = __commonJS({ attributes.alt = element.altText; } _3.extend(attributes, result2); - return [Html.freshElement("img", attributes)]; + return [Html2.freshElement("img", attributes)]; }); }; } @@ -85914,7 +85914,7 @@ var require_document_to_html = __commonJS({ var htmlPaths = require_html_paths(); var results = require_results(); var images = require_images(); - var Html = require_html(); + var Html2 = require_html(); var writers = require_writers(); exports2.DocumentConverter = DocumentConverter; function DocumentConverter(options) { @@ -85948,9 +85948,9 @@ var require_document_to_html = __commonJS({ } }); var deferredValues = /* @__PURE__ */ Object.create(null); - return promises.mapSeries(deferredNodes, function(deferred) { - return deferred.value().then(function(value) { - deferredValues[deferred.id] = value; + return promises.mapSeries(deferredNodes, function(deferred2) { + return deferred2.value().then(function(value) { + deferredValues[deferred2.id] = value; }); }).then(function() { function replaceDeferred(nodes) { @@ -85972,7 +85972,7 @@ var require_document_to_html = __commonJS({ prettyPrint: options.prettyPrint, outputFormat: options.outputFormat }); - Html.write(writer, Html.simplify(replaceDeferred(html))); + Html2.write(writer, Html2.simplify(replaceDeferred(html))); return new results.Result(writer.asString(), messages3); }); } @@ -85998,7 +85998,7 @@ var require_document_to_html = __commonJS({ if (ignoreEmptyParagraphs) { return content; } else { - return [Html.forceWrite].concat(content); + return [Html2.forceWrite].concat(content); } }); } @@ -86019,9 +86019,9 @@ var require_document_to_html = __commonJS({ }; var paths = []; if (run.highlight !== null) { - var path = findHtmlPath({ type: "highlight", color: run.highlight }); - if (path) { - paths.push(path); + var path2 = findHtmlPath({ type: "highlight", color: run.highlight }); + if (path2) { + paths.push(path2); } } if (run.isSmallCaps) { @@ -86056,15 +86056,15 @@ var require_document_to_html = __commonJS({ messages3.push(unrecognisedStyleWarning("run", run)); } paths.push(stylePath); - paths.forEach(function(path2) { - nodes = path2.wrap.bind(path2, nodes); + paths.forEach(function(path3) { + nodes = path3.wrap.bind(path3, nodes); }); return nodes(); } function findHtmlPathForRunProperty(elementType, defaultTagName) { - var path = findHtmlPath({ type: elementType }); - if (path) { - return path; + var path2 = findHtmlPath({ type: elementType }); + if (path2) { + return path2; } else if (defaultTagName) { return htmlPaths.element(defaultTagName, {}, { fresh: false }); } else { @@ -86141,16 +86141,16 @@ var require_document_to_html = __commonJS({ _3.extend({}, options2, { isTableHeader: false }) ); children = [ - Html.freshElement("thead", {}, headRows), - Html.freshElement("tbody", {}, bodyRows) + Html2.freshElement("thead", {}, headRows), + Html2.freshElement("tbody", {}, bodyRows) ]; } - return [Html.forceWrite].concat(children); + return [Html2.forceWrite].concat(children); } function convertTableRow(element, messages3, options2) { var children = convertElements(element.children, messages3, options2); return [ - Html.freshElement("tr", {}, [Html.forceWrite].concat(children)) + Html2.freshElement("tr", {}, [Html2.forceWrite].concat(children)) ]; } function convertTableCell(element, messages3, options2) { @@ -86164,7 +86164,7 @@ var require_document_to_html = __commonJS({ attributes.rowspan = element.rowSpan.toString(); } return [ - Html.freshElement(tagName, attributes, [Html.forceWrite].concat(children)) + Html2.freshElement(tagName, attributes, [Html2.forceWrite].concat(children)) ]; } function convertCommentReference(reference, messages3, options2) { @@ -86174,10 +86174,10 @@ var require_document_to_html = __commonJS({ var label = "[" + commentAuthorLabel(comment) + count + "]"; referencedComments.push({ label, comment }); return [ - Html.freshElement("a", { + Html2.freshElement("a", { href: "#" + referentHtmlId("comment", reference.commentId), id: referenceHtmlId("comment", reference.commentId) - }, [Html.text(label)]) + }, [Html2.text(label)]) ]; }); } @@ -86185,20 +86185,20 @@ var require_document_to_html = __commonJS({ var label = referencedComment.label; var comment = referencedComment.comment; var body = convertElements(comment.body, messages3, options2).concat([ - Html.nonFreshElement("p", {}, [ - Html.text(" "), - Html.freshElement("a", { "href": "#" + referenceHtmlId("comment", comment.commentId) }, [ - Html.text("\u2191") + Html2.nonFreshElement("p", {}, [ + Html2.text(" "), + Html2.freshElement("a", { "href": "#" + referenceHtmlId("comment", comment.commentId) }, [ + Html2.text("\u2191") ]) ]) ]); return [ - Html.freshElement( + Html2.freshElement( "dt", { "id": referentHtmlId("comment", comment.commentId) }, - [Html.text("Comment " + label)] + [Html2.text("Comment " + label)] ), - Html.freshElement("dd", {}, body) + Html2.freshElement("dd", {}, body) ]; } function convertBreak(element, messages3, options2) { @@ -86224,8 +86224,8 @@ var require_document_to_html = __commonJS({ }); var notesNodes = convertElements(notes, messages3, options2); return children.concat([ - Html.freshElement("ol", {}, notesNodes), - Html.freshElement("dl", {}, flatMap(referencedComments, function(referencedComment) { + Html2.freshElement("ol", {}, notesNodes), + Html2.freshElement("dl", {}, flatMap(referencedComments, function(referencedComment) { return convertComment(referencedComment, messages3, options2); })) ]); @@ -86233,10 +86233,10 @@ var require_document_to_html = __commonJS({ "paragraph": convertParagraph, "run": convertRun, "text": function(element, messages3, options2) { - return [Html.text(element.value)]; + return [Html2.text(element.value)]; }, "tab": function(element, messages3, options2) { - return [Html.text(" ")]; + return [Html2.text(" ")]; }, "hyperlink": function(element, messages3, options2) { var href = element.anchor ? "#" + htmlId(element.anchor) : element.href; @@ -86245,37 +86245,37 @@ var require_document_to_html = __commonJS({ attributes.target = element.targetFrame; } var children = convertElements(element.children, messages3, options2); - return [Html.nonFreshElement("a", attributes, children)]; + return [Html2.nonFreshElement("a", attributes, children)]; }, "checkbox": function(element) { var attributes = { type: "checkbox" }; if (element.checked) { attributes["checked"] = "checked"; } - return [Html.freshElement("input", attributes)]; + return [Html2.freshElement("input", attributes)]; }, "bookmarkStart": function(element, messages3, options2) { - var anchor2 = Html.freshElement("a", { + var anchor2 = Html2.freshElement("a", { id: htmlId(element.name) - }, [Html.forceWrite]); + }, [Html2.forceWrite]); return [anchor2]; }, "noteReference": function(element, messages3, options2) { noteReferences.push(element); - var anchor2 = Html.freshElement("a", { + var anchor2 = Html2.freshElement("a", { href: "#" + noteHtmlId(element), id: noteRefHtmlId(element) - }, [Html.text("[" + noteNumber++ + "]")]); - return [Html.freshElement("sup", {}, [anchor2])]; + }, [Html2.text("[" + noteNumber++ + "]")]); + return [Html2.freshElement("sup", {}, [anchor2])]; }, "note": function(element, messages3, options2) { var children = convertElements(element.body, messages3, options2); - var backLink = Html.elementWithTag(htmlPaths.element("p", {}, { fresh: false }), [ - Html.text(" "), - Html.freshElement("a", { href: "#" + noteRefHtmlId(element) }, [Html.text("\u2191")]) + var backLink = Html2.elementWithTag(htmlPaths.element("p", {}, { fresh: false }), [ + Html2.text(" "), + Html2.freshElement("a", { href: "#" + noteRefHtmlId(element) }, [Html2.text("\u2191")]) ]); var body = children.concat([backLink]); - return Html.freshElement("li", { id: noteHtmlId(element) }, body); + return Html2.freshElement("li", { id: noteHtmlId(element) }, body); }, "commentReference": convertCommentReference, "comment": convertComment, @@ -87789,11 +87789,11 @@ var require_unzip = __commonJS({ var require_underline = __commonJS({ "node_modules/.pnpm/mammoth@1.12.3/node_modules/mammoth/lib/underline.js"(exports2) { var htmlPaths = require_html_paths(); - var Html = require_html(); + var Html2 = require_html(); exports2.element = element; function element(name) { return function(html) { - return Html.elementWithTag(htmlPaths.element(name), [html]); + return Html2.elementWithTag(htmlPaths.element(name), [html]); }; } } @@ -87891,6 +87891,62158 @@ var require_lib7 = __commonJS({ } }); +// node_modules/.pnpm/pdfjs-dist@5.4.296/node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs +var pdf_worker_exports = {}; +__export(pdf_worker_exports, { + WorkerMessageHandler: () => WorkerMessageHandler +}); +function __webpack_require__2(moduleId) { + var cachedModule = __webpack_module_cache__2[moduleId]; + if (cachedModule !== void 0) { + return cachedModule.exports; + } + var module2 = __webpack_module_cache__2[moduleId] = { + /******/ + // no module.id needed + /******/ + // no module.loaded needed + /******/ + exports: {} + /******/ + }; + __webpack_modules__2[moduleId].call(module2.exports, module2, module2.exports, __webpack_require__2); + return module2.exports; +} +function setVerbosityLevel2(level) { + if (Number.isInteger(level)) { + verbosity2 = level; + } +} +function getVerbosityLevel2() { + return verbosity2; +} +function info2(msg) { + if (verbosity2 >= VerbosityLevel2.INFOS) { + console.info(`Info: ${msg}`); + } +} +function warn2(msg) { + if (verbosity2 >= VerbosityLevel2.WARNINGS) { + console.warn(`Warning: ${msg}`); + } +} +function unreachable2(msg) { + throw new Error(msg); +} +function assert3(cond, msg) { + if (!cond) { + unreachable2(msg); + } +} +function _isValidProtocol2(url2) { + switch (url2?.protocol) { + case "http:": + case "https:": + case "ftp:": + case "mailto:": + case "tel:": + return true; + default: + return false; + } +} +function createValidAbsoluteUrl2(url2, baseUrl = null, options = null) { + if (!url2) { + return null; + } + if (options && typeof url2 === "string") { + if (options.addDefaultProtocol && url2.startsWith("www.")) { + const dots = url2.match(/\./g); + if (dots?.length >= 2) { + url2 = `http://${url2}`; + } + } + if (options.tryConvertEncoding) { + try { + url2 = stringToUTF8String2(url2); + } catch { + } + } + } + const absoluteUrl = baseUrl ? URL.parse(url2, baseUrl) : URL.parse(url2); + return _isValidProtocol2(absoluteUrl) ? absoluteUrl : null; +} +function shadow2(obj2, prop, value, nonSerializable2 = false) { + Object.defineProperty(obj2, prop, { + value, + enumerable: !nonSerializable2, + configurable: true, + writable: false + }); + return value; +} +function bytesToString2(bytes) { + if (typeof bytes !== "object" || bytes?.length === void 0) { + unreachable2("Invalid argument for bytesToString"); + } + const length = bytes.length; + const MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + const strBuf = []; + for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + const chunk2 = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk2)); + } + return strBuf.join(""); +} +function stringToBytes2(str) { + if (typeof str !== "string") { + unreachable2("Invalid argument for stringToBytes"); + } + const length = str.length; + const bytes = new Uint8Array(length); + for (let i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 255; + } + return bytes; +} +function string322(value) { + return String.fromCharCode(value >> 24 & 255, value >> 16 & 255, value >> 8 & 255, value & 255); +} +function objectSize(obj2) { + return Object.keys(obj2).length; +} +function isLittleEndian2() { + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + return view32[0] === 1; +} +function isEvalSupported2() { + try { + new Function(""); + return true; + } catch { + return false; + } +} +function stringToPDFString(str, keepEscapeSequence = false) { + if (str[0] >= "\xEF") { + let encoding; + if (str[0] === "\xFE" && str[1] === "\xFF") { + encoding = "utf-16be"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xFF" && str[1] === "\xFE") { + encoding = "utf-16le"; + if (str.length % 2 === 1) { + str = str.slice(0, -1); + } + } else if (str[0] === "\xEF" && str[1] === "\xBB" && str[2] === "\xBF") { + encoding = "utf-8"; + } + if (encoding) { + try { + const decoder2 = new TextDecoder(encoding, { + fatal: true + }); + const buffer2 = stringToBytes2(str); + const decoded = decoder2.decode(buffer2); + if (keepEscapeSequence || !decoded.includes("\x1B")) { + return decoded; + } + return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, ""); + } catch (ex) { + warn2(`stringToPDFString: "${ex}".`); + } + } + } + const strBuf = []; + for (let i = 0, ii = str.length; i < ii; i++) { + const charCode = str.charCodeAt(i); + if (!keepEscapeSequence && charCode === 27) { + while (++i < ii && str.charCodeAt(i) !== 27) { + } + continue; + } + const code = PDFStringTranslateTable[charCode]; + strBuf.push(code ? String.fromCharCode(code) : str.charAt(i)); + } + return strBuf.join(""); +} +function stringToUTF8String2(str) { + return decodeURIComponent(escape(str)); +} +function utf8StringToString(str) { + return unescape(encodeURIComponent(str)); +} +function isArrayEqual(arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + for (let i = 0, ii = arr1.length; i < ii; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + return true; +} +function getModificationDate(date6 = /* @__PURE__ */ new Date()) { + if (!(date6 instanceof Date)) { + date6 = new Date(date6); + } + const buffer2 = [date6.getUTCFullYear().toString(), (date6.getUTCMonth() + 1).toString().padStart(2, "0"), date6.getUTCDate().toString().padStart(2, "0"), date6.getUTCHours().toString().padStart(2, "0"), date6.getUTCMinutes().toString().padStart(2, "0"), date6.getUTCSeconds().toString().padStart(2, "0")]; + return buffer2.join(""); +} +function normalizeUnicode2(str) { + if (!NormalizeRegex2) { + NormalizeRegex2 = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; + NormalizationMap2 = /* @__PURE__ */ new Map([["\uFB05", "\u017Ft"]]); + } + return str.replaceAll(NormalizeRegex2, (_3, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap2.get(p2)); +} +function _isValidExplicitDest2(validRef, validName, dest) { + if (!Array.isArray(dest) || dest.length < 2) { + return false; + } + const [page, zoom, ...args] = dest; + if (!validRef(page) && !Number.isInteger(page)) { + return false; + } + if (!validName(zoom)) { + return false; + } + const argsLen = args.length; + let allowNull = true; + switch (zoom.name) { + case "XYZ": + if (argsLen < 2 || argsLen > 3) { + return false; + } + break; + case "Fit": + case "FitB": + return argsLen === 0; + case "FitH": + case "FitBH": + case "FitV": + case "FitBV": + if (argsLen > 1) { + return false; + } + break; + case "FitR": + if (argsLen !== 4) { + return false; + } + allowNull = false; + break; + default: + return false; + } + for (const arg of args) { + if (typeof arg === "number" || allowNull && arg === null) { + continue; + } + return false; + } + return true; +} +function MathClamp2(v, min2, max2) { + return Math.min(Math.max(v, min2), max2); +} +function toHexUtil(arr) { + if (Uint8Array.prototype.toHex) { + return arr.toHex(); + } + return Array.from(arr, (num) => hexNumbers2[num]).join(""); +} +function fromBase64Util2(str) { + if (Uint8Array.fromBase64) { + return Uint8Array.fromBase64(str); + } + return stringToBytes2(atob(str)); +} +function clearPrimitiveCaches() { + CmdCache = /* @__PURE__ */ Object.create(null); + NameCache = /* @__PURE__ */ Object.create(null); + RefCache = /* @__PURE__ */ Object.create(null); +} +function isName(v, name) { + return v instanceof Name2 && (name === void 0 || v.name === name); +} +function isCmd(v, cmd) { + return v instanceof Cmd && (cmd === void 0 || v.cmd === cmd); +} +function isDict(v, type) { + return v instanceof Dict && (type === void 0 || isName(v.get("Type"), type)); +} +function isRefsEqual(v1, v2) { + return v1.num === v2.num && v1.gen === v2.gen; +} +function getLookupTableFactory(initializer3) { + let lookup; + return function() { + if (initializer3) { + lookup = /* @__PURE__ */ Object.create(null); + initializer3(lookup); + initializer3 = null; + } + return lookup; + }; +} +function arrayBuffersToBytes(arr) { + const length = arr.length; + if (length === 0) { + return new Uint8Array(0); + } + if (length === 1) { + return new Uint8Array(arr[0]); + } + let dataLength = 0; + for (let i = 0; i < length; i++) { + dataLength += arr[i].byteLength; + } + const data = new Uint8Array(dataLength); + let pos = 0; + for (let i = 0; i < length; i++) { + const item = new Uint8Array(arr[i]); + data.set(item, pos); + pos += item.byteLength; + } + return data; +} +async function fetchBinaryData(url2) { + const response = await fetch(url2); + if (!response.ok) { + throw new Error(`Failed to fetch file "${url2}" with "${response.statusText}".`); + } + return new Uint8Array(await response.arrayBuffer()); +} +function getInheritableProperty({ + dict, + key, + getArray = false, + stopWhenFound = true +}) { + let values3; + const visited = new RefSet(); + while (dict instanceof Dict && !(dict.objId && visited.has(dict.objId))) { + if (dict.objId) { + visited.put(dict.objId); + } + const value = getArray ? dict.getArray(key) : dict.get(key); + if (value !== void 0) { + if (stopWhenFound) { + return value; + } + (values3 ||= []).push(value); + } + dict = dict.get("Parent"); + } + return values3; +} +function getParentToUpdate(dict, ref, xref) { + const visited = new RefSet(); + const firstDict = dict; + const result2 = { + dict: null, + ref: null + }; + while (dict instanceof Dict && !visited.has(ref)) { + visited.put(ref); + if (dict.has("T")) { + break; + } + ref = dict.getRaw("Parent"); + if (!(ref instanceof Ref)) { + return result2; + } + dict = xref.fetch(ref); + } + if (dict instanceof Dict && dict !== firstDict) { + result2.dict = dict; + result2.ref = ref; + } + return result2; +} +function toRomanNumerals(number4, lowerCase = false) { + assert3(Number.isInteger(number4) && number4 > 0, "The number should be a positive integer."); + const roman = "M".repeat(number4 / 1e3 | 0) + ROMAN_NUMBER_MAP[number4 % 1e3 / 100 | 0] + ROMAN_NUMBER_MAP[10 + (number4 % 100 / 10 | 0)] + ROMAN_NUMBER_MAP[20 + number4 % 10]; + return lowerCase ? roman.toLowerCase() : roman; +} +function log2(x) { + return x > 0 ? Math.ceil(Math.log2(x)) : 0; +} +function readInt8(data, offset) { + return data[offset] << 24 >> 24; +} +function readInt16(data, offset) { + return (data[offset] << 24 | data[offset + 1] << 16) >> 16; +} +function readUint16(data, offset) { + return data[offset] << 8 | data[offset + 1]; +} +function readUint32(data, offset) { + return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0; +} +function isWhiteSpace(ch2) { + return ch2 === 32 || ch2 === 9 || ch2 === 13 || ch2 === 10; +} +function isBooleanArray(arr, len) { + return Array.isArray(arr) && (len === null || arr.length === len) && arr.every((x) => typeof x === "boolean"); +} +function isNumberArray(arr, len) { + if (Array.isArray(arr)) { + return (len === null || arr.length === len) && arr.every((x) => typeof x === "number"); + } + return ArrayBuffer.isView(arr) && !(arr instanceof BigInt64Array || arr instanceof BigUint64Array) && (len === null || arr.length === len); +} +function lookupMatrix(arr, fallback) { + return isNumberArray(arr, 6) ? arr : fallback; +} +function lookupRect(arr, fallback) { + return isNumberArray(arr, 4) ? arr : fallback; +} +function lookupNormalRect(arr, fallback) { + return isNumberArray(arr, 4) ? Util2.normalizeRect(arr) : fallback; +} +function parseXFAPath(path2) { + const positionPattern = /(.+)\[(\d+)\]$/; + return path2.split(".").map((component) => { + const m = component.match(positionPattern); + if (m) { + return { + name: m[1], + pos: parseInt(m[2], 10) + }; + } + return { + name: component, + pos: 0 + }; + }); +} +function escapePDFName(str) { + const buffer2 = []; + let start = 0; + for (let i = 0, ii = str.length; i < ii; i++) { + const char2 = str.charCodeAt(i); + if (char2 < 33 || char2 > 126 || char2 === 35 || char2 === 40 || char2 === 41 || char2 === 60 || char2 === 62 || char2 === 91 || char2 === 93 || char2 === 123 || char2 === 125 || char2 === 47 || char2 === 37) { + if (start < i) { + buffer2.push(str.substring(start, i)); + } + buffer2.push(`#${char2.toString(16)}`); + start = i + 1; + } + } + if (buffer2.length === 0) { + return str; + } + if (start < str.length) { + buffer2.push(str.substring(start, str.length)); + } + return buffer2.join(""); +} +function escapeString(str) { + return str.replaceAll(/([()\\\n\r])/g, (match) => { + if (match === "\n") { + return "\\n"; + } else if (match === "\r") { + return "\\r"; + } + return `\\${match}`; + }); +} +function _collectJS(entry, xref, list, parents) { + if (!entry) { + return; + } + let parent = null; + if (entry instanceof Ref) { + if (parents.has(entry)) { + return; + } + parent = entry; + parents.put(parent); + entry = xref.fetch(entry); + } + if (Array.isArray(entry)) { + for (const element of entry) { + _collectJS(element, xref, list, parents); + } + } else if (entry instanceof Dict) { + if (isName(entry.get("S"), "JavaScript")) { + const js = entry.get("JS"); + let code; + if (js instanceof BaseStream) { + code = js.getString(); + } else if (typeof js === "string") { + code = js; + } + code &&= stringToPDFString(code, true).replaceAll("\0", ""); + if (code) { + list.push(code.trim()); + } + } + _collectJS(entry.getRaw("Next"), xref, list, parents); + } + if (parent) { + parents.remove(parent); + } +} +function collectActions(xref, dict, eventType) { + const actions = /* @__PURE__ */ Object.create(null); + const additionalActionsDicts = getInheritableProperty({ + dict, + key: "AA", + stopWhenFound: false + }); + if (additionalActionsDicts) { + for (let i = additionalActionsDicts.length - 1; i >= 0; i--) { + const additionalActions = additionalActionsDicts[i]; + if (!(additionalActions instanceof Dict)) { + continue; + } + for (const key of additionalActions.getKeys()) { + const action = eventType[key]; + if (!action) { + continue; + } + const actionDict = additionalActions.getRaw(key); + const parents = new RefSet(); + const list = []; + _collectJS(actionDict, xref, list, parents); + if (list.length > 0) { + actions[action] = list; + } + } + } + } + if (dict.has("A")) { + const actionDict = dict.get("A"); + const parents = new RefSet(); + const list = []; + _collectJS(actionDict, xref, list, parents); + if (list.length > 0) { + actions.Action = list; + } + } + return objectSize(actions) > 0 ? actions : null; +} +function* codePointIter(str) { + for (let i = 0, ii = str.length; i < ii; i++) { + const char2 = str.codePointAt(i); + if (char2 > 55295 && (char2 < 57344 || char2 > 65533)) { + i++; + } + yield char2; + } +} +function encodeToXmlString(str) { + const buffer2 = []; + let start = 0; + for (let i = 0, ii = str.length; i < ii; i++) { + const char2 = str.codePointAt(i); + if (32 <= char2 && char2 <= 126) { + const entity = XMLEntities[char2]; + if (entity) { + if (start < i) { + buffer2.push(str.substring(start, i)); + } + buffer2.push(entity); + start = i + 1; + } + } else { + if (start < i) { + buffer2.push(str.substring(start, i)); + } + buffer2.push(`&#x${char2.toString(16).toUpperCase()};`); + if (char2 > 55295 && (char2 < 57344 || char2 > 65533)) { + i++; + } + start = i + 1; + } + } + if (buffer2.length === 0) { + return str; + } + if (start < str.length) { + buffer2.push(str.substring(start, str.length)); + } + return buffer2.join(""); +} +function validateFontName(fontFamily, mustWarn = false) { + const m = /^("|').*("|')$/.exec(fontFamily); + if (m && m[1] === m[2]) { + const re2 = new RegExp(`[^\\\\]${m[1]}`); + if (re2.test(fontFamily.slice(1, -1))) { + if (mustWarn) { + warn2(`FontFamily contains unescaped ${m[1]}: ${fontFamily}.`); + } + return false; + } + } else { + for (const ident of fontFamily.split(/[ \t]+/)) { + if (/^(\d|(-(\d|-)))/.test(ident) || !/^[\w-\\]+$/.test(ident)) { + if (mustWarn) { + warn2(`FontFamily contains invalid : ${fontFamily}.`); + } + return false; + } + } + } + return true; +} +function validateCSSFont(cssFontInfo) { + const DEFAULT_CSS_FONT_OBLIQUE = "14"; + const DEFAULT_CSS_FONT_WEIGHT = "400"; + const CSS_FONT_WEIGHT_VALUES = /* @__PURE__ */ new Set(["100", "200", "300", "400", "500", "600", "700", "800", "900", "1000", "normal", "bold", "bolder", "lighter"]); + const { + fontFamily, + fontWeight, + italicAngle + } = cssFontInfo; + if (!validateFontName(fontFamily, true)) { + return false; + } + const weight = fontWeight ? fontWeight.toString() : ""; + cssFontInfo.fontWeight = CSS_FONT_WEIGHT_VALUES.has(weight) ? weight : DEFAULT_CSS_FONT_WEIGHT; + const angle = parseFloat(italicAngle); + cssFontInfo.italicAngle = isNaN(angle) || angle < -90 || angle > 90 ? DEFAULT_CSS_FONT_OBLIQUE : italicAngle.toString(); + return true; +} +function recoverJsURL(str) { + const URL_OPEN_METHODS = ["app.launchURL", "window.open", "xfa.host.gotoURL"]; + const regex = new RegExp("^\\s*(" + URL_OPEN_METHODS.join("|").replaceAll(".", "\\.") + `)\\((?:'|")([^'"]*)(?:'|")(?:,\\s*(\\w+)\\)|\\))`, "i"); + const jsUrl = regex.exec(str); + if (jsUrl?.[2]) { + return { + url: jsUrl[2], + newWindow: jsUrl[1] === "app.launchURL" && jsUrl[3] === "true" + }; + } + return null; +} +function numberToString(value) { + if (Number.isInteger(value)) { + return value.toString(); + } + const roundedValue = Math.round(value * 100); + if (roundedValue % 100 === 0) { + return (roundedValue / 100).toString(); + } + if (roundedValue % 10 === 0) { + return value.toFixed(1); + } + return value.toFixed(2); +} +function getNewAnnotationsMap(annotationStorage) { + if (!annotationStorage) { + return null; + } + const newAnnotationsByPage = /* @__PURE__ */ new Map(); + for (const [key, value] of annotationStorage) { + if (!key.startsWith(AnnotationEditorPrefix2)) { + continue; + } + let annotations = newAnnotationsByPage.get(value.pageIndex); + if (!annotations) { + annotations = []; + newAnnotationsByPage.set(value.pageIndex, annotations); + } + annotations.push(value); + } + return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null; +} +function stringToAsciiOrUTF16BE(str) { + if (str === null || str === void 0) { + return str; + } + return isAscii(str) ? str : stringToUTF16String(str, true); +} +function isAscii(str) { + if (typeof str !== "string") { + return false; + } + return !str || /^[\x00-\x7F]*$/.test(str); +} +function stringToUTF16HexString(str) { + const buf = []; + for (let i = 0, ii = str.length; i < ii; i++) { + const char2 = str.charCodeAt(i); + buf.push(hexNumbers2[char2 >> 8 & 255], hexNumbers2[char2 & 255]); + } + return buf.join(""); +} +function stringToUTF16String(str, bigEndian = false) { + const buf = []; + if (bigEndian) { + buf.push("\xFE\xFF"); + } + for (let i = 0, ii = str.length; i < ii; i++) { + const char2 = str.charCodeAt(i); + buf.push(String.fromCharCode(char2 >> 8 & 255), String.fromCharCode(char2 & 255)); + } + return buf.join(""); +} +function getRotationMatrix(rotation, width, height) { + switch (rotation) { + case 90: + return [0, 1, -1, 0, width, 0]; + case 180: + return [-1, 0, 0, -1, width, height]; + case 270: + return [0, -1, 1, 0, 0, height]; + default: + throw new Error("Invalid rotation"); + } +} +function getSizeInBytes(x) { + return Math.ceil(Math.ceil(Math.log2(1 + x)) / 8); +} +function copy_result(ptr, len) { + const { + _mustAddAlpha, + _destBuffer, + _destOffset, + _destLength, + _memoryArray + } = QCMS; + if (len === _destLength) { + _destBuffer.set(_memoryArray.subarray(ptr, ptr + len), _destOffset); + return; + } + if (_mustAddAlpha) { + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; + _destBuffer[j + 3] = 255; + } + } else { + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; + } + } +} +function copy_rgb(ptr) { + const { + _destBuffer, + _destOffset, + _memoryArray + } = QCMS; + _destBuffer[_destOffset] = _memoryArray[ptr]; + _destBuffer[_destOffset + 1] = _memoryArray[ptr + 1]; + _destBuffer[_destOffset + 2] = _memoryArray[ptr + 2]; +} +function make_cssRGB(ptr) { + const { + _memoryArray + } = QCMS; + QCMS._cssColor = QCMS._makeHexColor(_memoryArray[ptr], _memoryArray[ptr + 1], _memoryArray[ptr + 2]); +} +function getUint8ArrayMemory0() { + if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { + cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8ArrayMemory0; +} +function getStringFromWasm0(ptr, len) { + ptr = ptr >>> 0; + return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); +} +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1, 1) >>> 0; + getUint8ArrayMemory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} +function qcms_convert_array(transformer, src) { + const ptr0 = passArray8ToWasm0(src, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + wasm.qcms_convert_array(transformer, ptr0, len0); +} +function qcms_convert_one(transformer, src, css) { + wasm.qcms_convert_one(transformer, src, css); +} +function qcms_convert_three(transformer, src1, src2, src3, css) { + wasm.qcms_convert_three(transformer, src1, src2, src3, css); +} +function qcms_convert_four(transformer, src1, src2, src3, src4, css) { + wasm.qcms_convert_four(transformer, src1, src2, src3, src4, css); +} +function qcms_transformer_from_memory(mem, in_type, intent) { + const ptr0 = passArray8ToWasm0(mem, wasm.__wbindgen_malloc); + const len0 = WASM_VECTOR_LEN; + const ret2 = wasm.qcms_transformer_from_memory(ptr0, len0, in_type, intent); + return ret2 >>> 0; +} +function qcms_drop_transformer(transformer) { + wasm.qcms_drop_transformer(transformer); +} +async function __wbg_load(module2, imports) { + if (typeof Response === "function" && module2 instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === "function") { + try { + return await WebAssembly.instantiateStreaming(module2, imports); + } catch (e) { + if (module2.headers.get("Content-Type") != "application/wasm") { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + } else { + throw e; + } + } + } + const bytes = await module2.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + } else { + const instance = await WebAssembly.instantiate(module2, imports); + if (instance instanceof WebAssembly.Instance) { + return { + instance, + module: module2 + }; + } else { + return instance; + } + } +} +function __wbg_get_imports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbg_copyresult_b08ee7d273f295dd = function(arg0, arg1) { + copy_result(arg0 >>> 0, arg1 >>> 0); + }; + imports.wbg.__wbg_copyrgb_d60ce17bb05d9b67 = function(arg0) { + copy_rgb(arg0 >>> 0); + }; + imports.wbg.__wbg_makecssRGB_893bf0cd9fdb302d = function(arg0) { + make_cssRGB(arg0 >>> 0); + }; + imports.wbg.__wbindgen_init_externref_table = function() { + const table2 = wasm.__wbindgen_export_0; + const offset = table2.grow(4); + table2.set(0, void 0); + table2.set(offset + 0, void 0); + table2.set(offset + 1, null); + table2.set(offset + 2, true); + table2.set(offset + 3, false); + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + return imports; +} +function __wbg_init_memory(imports, memory) { +} +function __wbg_finalize_init(instance, module2) { + wasm = instance.exports; + __wbg_init.__wbindgen_wasm_module = module2; + cachedUint8ArrayMemory0 = null; + wasm.__wbindgen_start(); + return wasm; +} +function initSync(module2) { + if (wasm !== void 0) return wasm; + if (typeof module2 !== "undefined") { + if (Object.getPrototypeOf(module2) === Object.prototype) { + ({ + module: module2 + } = module2); + } else { + console.warn("using deprecated parameters for `initSync()`; pass a single object instead"); + } + } + const imports = __wbg_get_imports(); + __wbg_init_memory(imports); + if (!(module2 instanceof WebAssembly.Module)) { + module2 = new WebAssembly.Module(module2); + } + const instance = new WebAssembly.Instance(module2, imports); + return __wbg_finalize_init(instance, module2); +} +async function __wbg_init(module_or_path) { + if (wasm !== void 0) return wasm; + if (typeof module_or_path !== "undefined") { + if (Object.getPrototypeOf(module_or_path) === Object.prototype) { + ({ + module_or_path + } = module_or_path); + } else { + console.warn("using deprecated parameters for the initialization function; pass a single object instead"); + } + } + const imports = __wbg_get_imports(); + if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) { + module_or_path = fetch(module_or_path); + } + __wbg_init_memory(imports); + const { + instance, + module: module2 + } = await __wbg_load(await module_or_path, imports); + return __wbg_finalize_init(instance, module2); +} +function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) { + const COMPONENTS = 3; + alpha01 = alpha01 !== 1 ? 0 : alpha01; + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let newIndex = 0, oldIndex; + const xScaled = new Uint16Array(w2); + const w1Scanline = w1 * COMPONENTS; + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (let i = 0; i < h2; i++) { + const py = Math.floor(i * yRatio) * w1Scanline; + for (let j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + dest[newIndex++] = src[oldIndex++]; + newIndex += alpha01; + } + } +} +function resizeRgbaImage(src, dest, w1, h1, w2, h2, alpha01) { + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let newIndex = 0; + const xScaled = new Uint16Array(w2); + if (alpha01 === 1) { + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio); + } + const src32 = new Uint32Array(src.buffer); + const dest32 = new Uint32Array(dest.buffer); + const rgbMask = FeatureTest2.isLittleEndian ? 16777215 : 4294967040; + for (let i = 0; i < h2; i++) { + const buf = src32.subarray(Math.floor(i * yRatio) * w1); + for (let j = 0; j < w2; j++) { + dest32[newIndex++] |= buf[xScaled[j]] & rgbMask; + } + } + } else { + const COMPONENTS = 4; + const w1Scanline = w1 * COMPONENTS; + for (let i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio) * COMPONENTS; + } + for (let i = 0; i < h2; i++) { + const buf = src.subarray(Math.floor(i * yRatio) * w1Scanline); + for (let j = 0; j < w2; j++) { + const oldIndex = xScaled[j]; + dest[newIndex++] = buf[oldIndex]; + dest[newIndex++] = buf[oldIndex + 1]; + dest[newIndex++] = buf[oldIndex + 2]; + } + } + } +} +function copyRgbaImage(src, dest, alpha01) { + if (alpha01 === 1) { + const src32 = new Uint32Array(src.buffer); + const dest32 = new Uint32Array(dest.buffer); + const rgbMask = FeatureTest2.isLittleEndian ? 16777215 : 4294967040; + for (let i = 0, ii = src32.length; i < ii; i++) { + dest32[i] |= src32[i] & rgbMask; + } + } else { + let j = 0; + for (let i = 0, ii = src.length; i < ii; i += 4) { + dest[j++] = src[i]; + dest[j++] = src[i + 1]; + dest[j++] = src[i + 2]; + } + } +} +function fetchSync(url2) { + const xhr = new XMLHttpRequest(); + xhr.open("GET", url2, false); + xhr.responseType = "arraybuffer"; + xhr.send(null); + return xhr.response; +} +function convertToRGBA(params) { + switch (params.kind) { + case ImageKind2.GRAYSCALE_1BPP: + return convertBlackAndWhiteToRGBA2(params); + case ImageKind2.RGB_24BPP: + return convertRGBToRGBA(params); + } + return null; +} +function convertBlackAndWhiteToRGBA2({ + src, + srcPos = 0, + dest, + width, + height, + nonBlackColor = 4294967295, + inverseDecode = false +}) { + const black = FeatureTest2.isLittleEndian ? 4278190080 : 255; + const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor]; + const widthInSource = width >> 3; + const widthRemainder = width & 7; + const srcLength = src.length; + dest = new Uint32Array(dest.buffer); + let destPos = 0; + for (let i = 0; i < height; i++) { + for (const max2 = srcPos + widthInSource; srcPos < max2; srcPos++) { + const elem2 = srcPos < srcLength ? src[srcPos] : 255; + dest[destPos++] = elem2 & 128 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 64 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 32 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 16 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 8 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 4 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 2 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 1 ? oneMapping : zeroMapping; + } + if (widthRemainder === 0) { + continue; + } + const elem = srcPos < srcLength ? src[srcPos++] : 255; + for (let j = 0; j < widthRemainder; j++) { + dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; + } + } + return { + srcPos, + destPos + }; +} +function convertRGBToRGBA({ + src, + srcPos = 0, + dest, + destPos = 0, + width, + height +}) { + let i = 0; + const len = width * height * 3; + const len32 = len >> 2; + const src32 = new Uint32Array(src.buffer, srcPos, len32); + if (FeatureTest2.isLittleEndian) { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 4278190080; + dest[destPos + 1] = s1 >>> 24 | s2 << 8 | 4278190080; + dest[destPos + 2] = s2 >>> 16 | s3 << 16 | 4278190080; + dest[destPos + 3] = s3 >>> 8 | 4278190080; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] | src[j + 1] << 8 | src[j + 2] << 16 | 4278190080; + } + } else { + for (; i < len32 - 2; i += 3, destPos += 4) { + const s1 = src32[i]; + const s2 = src32[i + 1]; + const s3 = src32[i + 2]; + dest[destPos] = s1 | 255; + dest[destPos + 1] = s1 << 24 | s2 >>> 8 | 255; + dest[destPos + 2] = s2 << 16 | s3 >>> 16 | 255; + dest[destPos + 3] = s3 << 8 | 255; + } + for (let j = i * 4, jj = srcPos + len; j < jj; j += 3) { + dest[destPos++] = src[j] << 24 | src[j + 1] << 16 | src[j + 2] << 8 | 255; + } + } + return { + srcPos: srcPos + len, + destPos + }; +} +function grayToRGBA(src, dest) { + if (FeatureTest2.isLittleEndian) { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 65793 | 4278190080; + } + } else { + for (let i = 0, ii = src.length; i < ii; i++) { + dest[i] = src[i] * 16843008 | 255; + } + } +} +function buildHuffmanTable(codeLengths, values3) { + let k = 0, i, j, length = 16; + while (length > 0 && !codeLengths[length - 1]) { + length--; + } + const code = [{ + children: [], + index: 0 + }]; + let p = code[0], q; + for (i = 0; i < length; i++) { + for (j = 0; j < codeLengths[i]; j++) { + p = code.pop(); + p.children[p.index] = values3[k]; + while (p.index > 0) { + p = code.pop(); + } + p.index++; + code.push(p); + while (code.length <= i) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + k++; + } + if (i + 1 < length) { + code.push(q = { + children: [], + index: 0 + }); + p.children[p.index] = q.children; + p = q; + } + } + return code[0].children; +} +function getBlockBufferOffset(component, row, col) { + return 64 * ((component.blocksPerLine + 1) * row + col); +} +function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, parseDNLMarker = false) { + const mcusPerLine = frame.mcusPerLine; + const progressive = frame.progressive; + const startOffset = offset; + let bitsData = 0, bitsCount = 0; + function readBit() { + if (bitsCount > 0) { + bitsCount--; + return bitsData >> bitsCount & 1; + } + bitsData = data[offset++]; + if (bitsData === 255) { + const nextByte = data[offset++]; + if (nextByte) { + if (nextByte === 220 && parseDNLMarker) { + offset += 2; + const scanLines = readUint16(data, offset); + offset += 2; + if (scanLines > 0 && scanLines !== frame.scanLines) { + throw new DNLMarkerError("Found DNL marker (0xFFDC) while parsing scan data", scanLines); + } + } else if (nextByte === 217) { + if (parseDNLMarker) { + const maybeScanLines = blockRow * (frame.precision === 8 ? 8 : 0); + if (maybeScanLines > 0 && Math.round(frame.scanLines / maybeScanLines) >= 5) { + throw new DNLMarkerError("Found EOI marker (0xFFD9) while parsing scan data, possibly caused by incorrect `scanLines` parameter", maybeScanLines); + } + } + throw new EOIMarkerError("Found EOI marker (0xFFD9) while parsing scan data"); + } + throw new JpegError(`unexpected marker ${(bitsData << 8 | nextByte).toString(16)}`); + } + } + bitsCount = 7; + return bitsData >>> 7; + } + function decodeHuffman(tree) { + let node2 = tree; + while (true) { + node2 = node2[readBit()]; + switch (typeof node2) { + case "number": + return node2; + case "object": + continue; + } + throw new JpegError("invalid huffman sequence"); + } + } + function receive(length) { + let n2 = 0; + while (length > 0) { + n2 = n2 << 1 | readBit(); + length--; + } + return n2; + } + function receiveAndExtend(length) { + if (length === 1) { + return readBit() === 1 ? 1 : -1; + } + const n2 = receive(length); + if (n2 >= 1 << length - 1) { + return n2; + } + return n2 + (-1 << length) + 1; + } + function decodeBaseline(component2, blockOffset) { + const t = decodeHuffman(component2.huffmanTableDC); + const diff = t === 0 ? 0 : receiveAndExtend(t); + component2.blockData[blockOffset] = component2.pred += diff; + let k2 = 1; + while (k2 < 64) { + const rs = decodeHuffman(component2.huffmanTableAC); + const s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + break; + } + k2 += 16; + continue; + } + k2 += r; + const z2 = dctZigZag[k2]; + component2.blockData[blockOffset + z2] = receiveAndExtend(s); + k2++; + } + } + function decodeDCFirst(component2, blockOffset) { + const t = decodeHuffman(component2.huffmanTableDC); + const diff = t === 0 ? 0 : receiveAndExtend(t) << successive; + component2.blockData[blockOffset] = component2.pred += diff; + } + function decodeDCSuccessive(component2, blockOffset) { + component2.blockData[blockOffset] |= readBit() << successive; + } + let eobrun = 0; + function decodeACFirst(component2, blockOffset) { + if (eobrun > 0) { + eobrun--; + return; + } + let k2 = spectralStart; + const e = spectralEnd; + while (k2 <= e) { + const rs = decodeHuffman(component2.huffmanTableAC); + const s = rs & 15, r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r) - 1; + break; + } + k2 += 16; + continue; + } + k2 += r; + const z2 = dctZigZag[k2]; + component2.blockData[blockOffset + z2] = receiveAndExtend(s) * (1 << successive); + k2++; + } + } + let successiveACState = 0, successiveACNextValue; + function decodeACSuccessive(component2, blockOffset) { + let k2 = spectralStart; + const e = spectralEnd; + let r = 0; + let s; + let rs; + while (k2 <= e) { + const offsetZ = blockOffset + dctZigZag[k2]; + const sign = component2.blockData[offsetZ] < 0 ? -1 : 1; + switch (successiveACState) { + case 0: + rs = decodeHuffman(component2.huffmanTableAC); + s = rs & 15; + r = rs >> 4; + if (s === 0) { + if (r < 15) { + eobrun = receive(r) + (1 << r); + successiveACState = 4; + } else { + r = 16; + successiveACState = 1; + } + } else { + if (s !== 1) { + throw new JpegError("invalid ACn encoding"); + } + successiveACNextValue = receiveAndExtend(s); + successiveACState = r ? 2 : 3; + } + continue; + case 1: + case 2: + if (component2.blockData[offsetZ]) { + component2.blockData[offsetZ] += sign * (readBit() << successive); + } else { + r--; + if (r === 0) { + successiveACState = successiveACState === 2 ? 3 : 0; + } + } + break; + case 3: + if (component2.blockData[offsetZ]) { + component2.blockData[offsetZ] += sign * (readBit() << successive); + } else { + component2.blockData[offsetZ] = successiveACNextValue << successive; + successiveACState = 0; + } + break; + case 4: + if (component2.blockData[offsetZ]) { + component2.blockData[offsetZ] += sign * (readBit() << successive); + } + break; + } + k2++; + } + if (successiveACState === 4) { + eobrun--; + if (eobrun === 0) { + successiveACState = 0; + } + } + } + let blockRow = 0; + function decodeMcu(component2, decode4, mcu2, row, col) { + const mcuRow = mcu2 / mcusPerLine | 0; + const mcuCol = mcu2 % mcusPerLine; + blockRow = mcuRow * component2.v + row; + const blockCol = mcuCol * component2.h + col; + const blockOffset = getBlockBufferOffset(component2, blockRow, blockCol); + decode4(component2, blockOffset); + } + function decodeBlock(component2, decode4, mcu2) { + blockRow = mcu2 / component2.blocksPerLine | 0; + const blockCol = mcu2 % component2.blocksPerLine; + const blockOffset = getBlockBufferOffset(component2, blockRow, blockCol); + decode4(component2, blockOffset); + } + const componentsLength = components.length; + let component, i, j, k, n; + let decodeFn; + if (progressive) { + if (spectralStart === 0) { + decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive; + } else { + decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive; + } + } else { + decodeFn = decodeBaseline; + } + let mcu = 0, fileMarker; + const mcuExpected = componentsLength === 1 ? components[0].blocksPerLine * components[0].blocksPerColumn : mcusPerLine * frame.mcusPerColumn; + let h, v; + while (mcu <= mcuExpected) { + const mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected; + if (mcuToRead > 0) { + for (i = 0; i < componentsLength; i++) { + components[i].pred = 0; + } + eobrun = 0; + if (componentsLength === 1) { + component = components[0]; + for (n = 0; n < mcuToRead; n++) { + decodeBlock(component, decodeFn, mcu); + mcu++; + } + } else { + for (n = 0; n < mcuToRead; n++) { + for (i = 0; i < componentsLength; i++) { + component = components[i]; + h = component.h; + v = component.v; + for (j = 0; j < v; j++) { + for (k = 0; k < h; k++) { + decodeMcu(component, decodeFn, mcu, j, k); + } + } + } + mcu++; + } + } + } + bitsCount = 0; + fileMarker = findNextFileMarker(data, offset); + if (!fileMarker) { + break; + } + if (fileMarker.invalid) { + const partialMsg = mcuToRead > 0 ? "unexpected" : "excessive"; + warn2(`decodeScan - ${partialMsg} MCU data, current marker is: ${fileMarker.invalid}`); + offset = fileMarker.offset; + } + if (fileMarker.marker >= 65488 && fileMarker.marker <= 65495) { + offset += 2; + } else { + break; + } + } + return offset - startOffset; +} +function quantizeAndInverse(component, blockBufferOffset, p) { + const qt = component.quantizationTable, blockData = component.blockData; + let v0, v1, v2, v3, v4, v5, v6, v7; + let p0, p1, p2, p3, p4, p5, p6, p7; + let t; + if (!qt) { + throw new JpegError("missing required Quantization Table."); + } + for (let row = 0; row < 64; row += 8) { + p0 = blockData[blockBufferOffset + row]; + p1 = blockData[blockBufferOffset + row + 1]; + p2 = blockData[blockBufferOffset + row + 2]; + p3 = blockData[blockBufferOffset + row + 3]; + p4 = blockData[blockBufferOffset + row + 4]; + p5 = blockData[blockBufferOffset + row + 5]; + p6 = blockData[blockBufferOffset + row + 6]; + p7 = blockData[blockBufferOffset + row + 7]; + p0 *= qt[row]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 512 >> 10; + p[row] = t; + p[row + 1] = t; + p[row + 2] = t; + p[row + 3] = t; + p[row + 4] = t; + p[row + 5] = t; + p[row + 6] = t; + p[row + 7] = t; + continue; + } + p1 *= qt[row + 1]; + p2 *= qt[row + 2]; + p3 *= qt[row + 3]; + p4 *= qt[row + 4]; + p5 *= qt[row + 5]; + p6 *= qt[row + 6]; + p7 *= qt[row + 7]; + v0 = dctSqrt2 * p0 + 128 >> 8; + v1 = dctSqrt2 * p4 + 128 >> 8; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8; + v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8; + v5 = p3 << 4; + v6 = p5 << 4; + v0 = v0 + v1 + 1 >> 1; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8; + v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p[row] = v0 + v7; + p[row + 7] = v0 - v7; + p[row + 1] = v1 + v6; + p[row + 6] = v1 - v6; + p[row + 2] = v2 + v5; + p[row + 5] = v2 - v5; + p[row + 3] = v3 + v4; + p[row + 4] = v3 - v4; + } + for (let col = 0; col < 8; ++col) { + p0 = p[col]; + p1 = p[col + 8]; + p2 = p[col + 16]; + p3 = p[col + 24]; + p4 = p[col + 32]; + p5 = p[col + 40]; + p6 = p[col + 48]; + p7 = p[col + 56]; + if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) { + t = dctSqrt2 * p0 + 8192 >> 14; + if (t < -2040) { + t = 0; + } else if (t >= 2024) { + t = 255; + } else { + t = t + 2056 >> 4; + } + blockData[blockBufferOffset + col] = t; + blockData[blockBufferOffset + col + 8] = t; + blockData[blockBufferOffset + col + 16] = t; + blockData[blockBufferOffset + col + 24] = t; + blockData[blockBufferOffset + col + 32] = t; + blockData[blockBufferOffset + col + 40] = t; + blockData[blockBufferOffset + col + 48] = t; + blockData[blockBufferOffset + col + 56] = t; + continue; + } + v0 = dctSqrt2 * p0 + 2048 >> 12; + v1 = dctSqrt2 * p4 + 2048 >> 12; + v2 = p2; + v3 = p6; + v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12; + v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12; + v5 = p3; + v6 = p5; + v0 = (v0 + v1 + 1 >> 1) + 4112; + v1 = v0 - v1; + t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12; + v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12; + v3 = t; + v4 = v4 + v6 + 1 >> 1; + v6 = v4 - v6; + v7 = v7 + v5 + 1 >> 1; + v5 = v7 - v5; + v0 = v0 + v3 + 1 >> 1; + v3 = v0 - v3; + v1 = v1 + v2 + 1 >> 1; + v2 = v1 - v2; + t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12; + v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12; + v7 = t; + t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12; + v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12; + v6 = t; + p0 = v0 + v7; + p7 = v0 - v7; + p1 = v1 + v6; + p6 = v1 - v6; + p2 = v2 + v5; + p5 = v2 - v5; + p3 = v3 + v4; + p4 = v3 - v4; + if (p0 < 16) { + p0 = 0; + } else if (p0 >= 4080) { + p0 = 255; + } else { + p0 >>= 4; + } + if (p1 < 16) { + p1 = 0; + } else if (p1 >= 4080) { + p1 = 255; + } else { + p1 >>= 4; + } + if (p2 < 16) { + p2 = 0; + } else if (p2 >= 4080) { + p2 = 255; + } else { + p2 >>= 4; + } + if (p3 < 16) { + p3 = 0; + } else if (p3 >= 4080) { + p3 = 255; + } else { + p3 >>= 4; + } + if (p4 < 16) { + p4 = 0; + } else if (p4 >= 4080) { + p4 = 255; + } else { + p4 >>= 4; + } + if (p5 < 16) { + p5 = 0; + } else if (p5 >= 4080) { + p5 = 255; + } else { + p5 >>= 4; + } + if (p6 < 16) { + p6 = 0; + } else if (p6 >= 4080) { + p6 = 255; + } else { + p6 >>= 4; + } + if (p7 < 16) { + p7 = 0; + } else if (p7 >= 4080) { + p7 = 255; + } else { + p7 >>= 4; + } + blockData[blockBufferOffset + col] = p0; + blockData[blockBufferOffset + col + 8] = p1; + blockData[blockBufferOffset + col + 16] = p2; + blockData[blockBufferOffset + col + 24] = p3; + blockData[blockBufferOffset + col + 32] = p4; + blockData[blockBufferOffset + col + 40] = p5; + blockData[blockBufferOffset + col + 48] = p6; + blockData[blockBufferOffset + col + 56] = p7; + } +} +function buildComponentData(frame, component) { + const blocksPerLine = component.blocksPerLine; + const blocksPerColumn = component.blocksPerColumn; + const computationBuffer = new Int16Array(64); + for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) { + const offset = getBlockBufferOffset(component, blockRow, blockCol); + quantizeAndInverse(component, offset, computationBuffer); + } + } + return component.blockData; +} +function findNextFileMarker(data, currentPos, startPos = currentPos) { + const maxPos = data.length - 1; + let newPos = startPos < currentPos ? startPos : currentPos; + if (currentPos >= maxPos) { + return null; + } + const currentMarker = readUint16(data, currentPos); + if (currentMarker >= 65472 && currentMarker <= 65534) { + return { + invalid: null, + marker: currentMarker, + offset: currentPos + }; + } + let newMarker = readUint16(data, newPos); + while (!(newMarker >= 65472 && newMarker <= 65534)) { + if (++newPos >= maxPos) { + return null; + } + newMarker = readUint16(data, newPos); + } + return { + invalid: currentMarker.toString(16), + marker: newMarker, + offset: newPos + }; +} +function prepareComponents(frame) { + const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); + const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); + for (const component of frame.components) { + const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH); + const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV); + const blocksPerLineForMcu = mcusPerLine * component.h; + const blocksPerColumnForMcu = mcusPerColumn * component.v; + const blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1); + component.blockData = new Int16Array(blocksBufferSize); + component.blocksPerLine = blocksPerLine; + component.blocksPerColumn = blocksPerColumn; + } + frame.mcusPerLine = mcusPerLine; + frame.mcusPerColumn = mcusPerColumn; +} +function readDataBlock(data, offset) { + const length = readUint16(data, offset); + offset += 2; + let endOffset = offset + length - 2; + const fileMarker = findNextFileMarker(data, endOffset, offset); + if (fileMarker?.invalid) { + warn2("readDataBlock - incorrect length, current marker is: " + fileMarker.invalid); + endOffset = fileMarker.offset; + } + const array2 = data.subarray(offset, endOffset); + return { + appData: array2, + oldOffset: offset, + newOffset: offset + array2.length + }; +} +function skipData(data, offset) { + const length = readUint16(data, offset); + offset += 2; + const endOffset = offset + length - 2; + const fileMarker = findNextFileMarker(data, endOffset, offset); + if (fileMarker?.invalid) { + return fileMarker.offset; + } + return endOffset; +} +async function OpenJPEG(moduleArg = {}) { + var moduleRtn; + var Module = moduleArg; + var ENVIRONMENT_IS_WEB = true; + var ENVIRONMENT_IS_WORKER = false; + var arguments_ = []; + var thisProgram = "./this.program"; + var quit_ = (status, toThrow) => { + throw toThrow; + }; + var _scriptName = import.meta.url; + var scriptDirectory = ""; + var readAsync, readBinary; + if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) { + try { + scriptDirectory = new URL(".", _scriptName).href; + } catch { + } + readAsync = async (url2) => { + var response = await fetch(url2, { + credentials: "same-origin" + }); + if (response.ok) { + return response.arrayBuffer(); + } + throw new Error(response.status + " : " + response.url); + }; + } else { + } + var out = console.log.bind(console); + var err = console.error.bind(console); + var wasmBinary; + var ABORT = false; + var EXITSTATUS; + var readyPromiseResolve, readyPromiseReject; + var wasmMemory; + var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64; + var HEAP64, HEAPU64; + var runtimeInitialized = false; + function updateMemoryViews() { + var b2 = wasmMemory.buffer; + HEAP8 = new Int8Array(b2); + HEAP16 = new Int16Array(b2); + HEAPU8 = new Uint8Array(b2); + HEAPU16 = new Uint16Array(b2); + HEAP32 = new Int32Array(b2); + HEAPU32 = new Uint32Array(b2); + HEAPF32 = new Float32Array(b2); + HEAPF64 = new Float64Array(b2); + HEAP64 = new BigInt64Array(b2); + HEAPU64 = new BigUint64Array(b2); + } + function preRun() { + if (Module["preRun"]) { + if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]]; + while (Module["preRun"].length) { + addOnPreRun(Module["preRun"].shift()); + } + } + callRuntimeCallbacks(onPreRuns); + } + function initRuntime() { + runtimeInitialized = true; + wasmExports["s"](); + } + function postRun() { + if (Module["postRun"]) { + if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]]; + while (Module["postRun"].length) { + addOnPostRun(Module["postRun"].shift()); + } + } + callRuntimeCallbacks(onPostRuns); + } + function abort(what) { + Module["onAbort"]?.(what); + what = "Aborted(" + what + ")"; + err(what); + ABORT = true; + what += ". Build with -sASSERTIONS for more info."; + var e = new WebAssembly.RuntimeError(what); + readyPromiseReject?.(e); + throw e; + } + var wasmBinaryFile; + function getWasmImports() { + return { + a: wasmImports + }; + } + async function createWasm() { + function receiveInstance(instance, module2) { + wasmExports = instance.exports; + wasmMemory = wasmExports["r"]; + updateMemoryViews(); + assignWasmExports(wasmExports); + return wasmExports; + } + var info3 = getWasmImports(); + return new Promise((resolve2, reject2) => { + Module["instantiateWasm"](info3, (mod, inst) => { + resolve2(receiveInstance(mod, inst)); + }); + }); + } + class ExitStatus { + name = "ExitStatus"; + constructor(status) { + this.message = `Program terminated with exit(${status})`; + this.status = status; + } + } + var callRuntimeCallbacks = (callbacks) => { + while (callbacks.length > 0) { + callbacks.shift()(Module); + } + }; + var onPostRuns = []; + var addOnPostRun = (cb2) => onPostRuns.push(cb2); + var onPreRuns = []; + var addOnPreRun = (cb2) => onPreRuns.push(cb2); + var noExitRuntime = true; + var __abort_js = () => abort(""); + var runtimeKeepaliveCounter = 0; + var __emscripten_runtime_keepalive_clear = () => { + noExitRuntime = false; + runtimeKeepaliveCounter = 0; + }; + var timers = {}; + var handleException = (e) => { + if (e instanceof ExitStatus || e == "unwind") { + return EXITSTATUS; + } + quit_(1, e); + }; + var keepRuntimeAlive = () => noExitRuntime || runtimeKeepaliveCounter > 0; + var _proc_exit = (code) => { + EXITSTATUS = code; + if (!keepRuntimeAlive()) { + Module["onExit"]?.(code); + ABORT = true; + } + quit_(code, new ExitStatus(code)); + }; + var exitJS = (status, implicit) => { + EXITSTATUS = status; + _proc_exit(status); + }; + var _exit = exitJS; + var maybeExit = () => { + if (!keepRuntimeAlive()) { + try { + _exit(EXITSTATUS); + } catch (e) { + handleException(e); + } + } + }; + var callUserCallback = (func) => { + if (ABORT) { + return; + } + try { + func(); + maybeExit(); + } catch (e) { + handleException(e); + } + }; + var _emscripten_get_now = () => performance.now(); + var __setitimer_js = (which, timeout_ms) => { + if (timers[which]) { + clearTimeout(timers[which].id); + delete timers[which]; + } + if (!timeout_ms) return 0; + var id = setTimeout(() => { + delete timers[which]; + callUserCallback(() => __emscripten_timeout(which, _emscripten_get_now())); + }, timeout_ms); + timers[which] = { + id, + timeout_ms + }; + return 0; + }; + function _copy_pixels_1(compG_ptr, nb_pixels) { + compG_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + imageData.set(compG); + } + function _copy_pixels_3(compR_ptr, compG_ptr, compB_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 3); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[3 * i] = compR[i]; + imageData[3 * i + 1] = compG[i]; + imageData[3 * i + 2] = compB[i]; + } + } + function _copy_pixels_4(compR_ptr, compG_ptr, compB_ptr, compA_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + compA_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + const compA = HEAP32.subarray(compA_ptr, compA_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = compR[i]; + imageData[4 * i + 1] = compG[i]; + imageData[4 * i + 2] = compB[i]; + imageData[4 * i + 3] = compA[i]; + } + } + var getHeapMax = () => 2147483648; + var alignMemory = (size3, alignment) => Math.ceil(size3 / alignment) * alignment; + var growMemory = (size3) => { + var oldHeapSize = wasmMemory.buffer.byteLength; + var pages = (size3 - oldHeapSize + 65535) / 65536 | 0; + try { + wasmMemory.grow(pages); + updateMemoryViews(); + return 1; + } catch (e) { + } + }; + var _emscripten_resize_heap = (requestedSize) => { + var oldSize = HEAPU8.length; + requestedSize >>>= 0; + var maxHeapSize = getHeapMax(); + if (requestedSize > maxHeapSize) { + return false; + } + for (var cutDown = 1; cutDown <= 4; cutDown *= 2) { + var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown); + overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296); + var newSize = Math.min(maxHeapSize, alignMemory(Math.max(requestedSize, overGrownHeapSize), 65536)); + var replacement = growMemory(newSize); + if (replacement) { + return true; + } + } + return false; + }; + var ENV = {}; + var getExecutableName = () => thisProgram || "./this.program"; + var getEnvStrings = () => { + if (!getEnvStrings.strings) { + var lang = (typeof navigator == "object" && navigator.language || "C").replace("-", "_") + ".UTF-8"; + var env3 = { + USER: "web_user", + LOGNAME: "web_user", + PATH: "/", + PWD: "/", + HOME: "/home/web_user", + LANG: lang, + _: getExecutableName() + }; + for (var x in ENV) { + if (ENV[x] === void 0) delete env3[x]; + else env3[x] = ENV[x]; + } + var strings = []; + for (var x in env3) { + strings.push(`${x}=${env3[x]}`); + } + getEnvStrings.strings = strings; + } + return getEnvStrings.strings; + }; + var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { + if (!(maxBytesToWrite > 0)) return 0; + var startIdx = outIdx; + var endIdx = outIdx + maxBytesToWrite - 1; + for (var i = 0; i < str.length; ++i) { + var u = str.codePointAt(i); + if (u <= 127) { + if (outIdx >= endIdx) break; + heap[outIdx++] = u; + } else if (u <= 2047) { + if (outIdx + 1 >= endIdx) break; + heap[outIdx++] = 192 | u >> 6; + heap[outIdx++] = 128 | u & 63; + } else if (u <= 65535) { + if (outIdx + 2 >= endIdx) break; + heap[outIdx++] = 224 | u >> 12; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63; + } else { + if (outIdx + 3 >= endIdx) break; + heap[outIdx++] = 240 | u >> 18; + heap[outIdx++] = 128 | u >> 12 & 63; + heap[outIdx++] = 128 | u >> 6 & 63; + heap[outIdx++] = 128 | u & 63; + i++; + } + } + heap[outIdx] = 0; + return outIdx - startIdx; + }; + var stringToUTF8 = (str, outPtr, maxBytesToWrite) => stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); + var _environ_get = (__environ, environ_buf) => { + var bufSize = 0; + var envp = 0; + for (var string4 of getEnvStrings()) { + var ptr = environ_buf + bufSize; + HEAPU32[__environ + envp >> 2] = ptr; + bufSize += stringToUTF8(string4, ptr, Infinity) + 1; + envp += 4; + } + return 0; + }; + var lengthBytesUTF8 = (str) => { + var len = 0; + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + if (c <= 127) { + len++; + } else if (c <= 2047) { + len += 2; + } else if (c >= 55296 && c <= 57343) { + len += 4; + ++i; + } else { + len += 3; + } + } + return len; + }; + var _environ_sizes_get = (penviron_count, penviron_buf_size) => { + var strings = getEnvStrings(); + HEAPU32[penviron_count >> 2] = strings.length; + var bufSize = 0; + for (var string4 of strings) { + bufSize += lengthBytesUTF8(string4) + 1; + } + HEAPU32[penviron_buf_size >> 2] = bufSize; + return 0; + }; + var INT53_MAX = 9007199254740992; + var INT53_MIN = -9007199254740992; + var bigintToI53Checked = (num) => num < INT53_MIN || num > INT53_MAX ? NaN : Number(num); + function _fd_seek(fd, offset, whence, newOffset) { + offset = bigintToI53Checked(offset); + return 70; + } + var printCharBuffers = [null, [], []]; + var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder() : void 0; + var findStringEnd = (heapOrArray, idx, maxBytesToRead, ignoreNul) => { + var maxIdx = idx + maxBytesToRead; + if (ignoreNul) return maxIdx; + while (heapOrArray[idx] && !(idx >= maxIdx)) ++idx; + return idx; + }; + var UTF8ArrayToString = (heapOrArray, idx = 0, maxBytesToRead, ignoreNul) => { + var endPtr = findStringEnd(heapOrArray, idx, maxBytesToRead, ignoreNul); + if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) { + return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr)); + } + var str = ""; + while (idx < endPtr) { + var u0 = heapOrArray[idx++]; + if (!(u0 & 128)) { + str += String.fromCharCode(u0); + continue; + } + var u1 = heapOrArray[idx++] & 63; + if ((u0 & 224) == 192) { + str += String.fromCharCode((u0 & 31) << 6 | u1); + continue; + } + var u2 = heapOrArray[idx++] & 63; + if ((u0 & 240) == 224) { + u0 = (u0 & 15) << 12 | u1 << 6 | u2; + } else { + u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63; + } + if (u0 < 65536) { + str += String.fromCharCode(u0); + } else { + var ch2 = u0 - 65536; + str += String.fromCharCode(55296 | ch2 >> 10, 56320 | ch2 & 1023); + } + } + return str; + }; + var printChar = (stream, curr) => { + var buffer2 = printCharBuffers[stream]; + if (curr === 0 || curr === 10) { + (stream === 1 ? out : err)(UTF8ArrayToString(buffer2)); + buffer2.length = 0; + } else { + buffer2.push(curr); + } + }; + var UTF8ToString = (ptr, maxBytesToRead, ignoreNul) => ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead, ignoreNul) : ""; + var _fd_write = (fd, iov, iovcnt, pnum) => { + var num = 0; + for (var i = 0; i < iovcnt; i++) { + var ptr = HEAPU32[iov >> 2]; + var len = HEAPU32[iov + 4 >> 2]; + iov += 8; + for (var j = 0; j < len; j++) { + printChar(fd, HEAPU8[ptr + j]); + } + num += len; + } + HEAPU32[pnum >> 2] = num; + return 0; + }; + function _gray_to_rgba(compG_ptr, nb_pixels) { + compG_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = imageData[4 * i + 1] = imageData[4 * i + 2] = compG[i]; + imageData[4 * i + 3] = 255; + } + } + function _graya_to_rgba(compG_ptr, compA_ptr, nb_pixels) { + compG_ptr >>= 2; + compA_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compA = HEAP32.subarray(compA_ptr, compA_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = imageData[4 * i + 1] = imageData[4 * i + 2] = compG[i]; + imageData[4 * i + 3] = compA[i]; + } + } + function _jsPrintWarning(message_ptr) { + const message2 = UTF8ToString(message_ptr); + (Module.warn || console.warn)(`OpenJPEG: ${message2}`); + } + function _rgb_to_rgba(compR_ptr, compG_ptr, compB_ptr, nb_pixels) { + compR_ptr >>= 2; + compG_ptr >>= 2; + compB_ptr >>= 2; + const imageData = Module.imageData = new Uint8ClampedArray(nb_pixels * 4); + const compR = HEAP32.subarray(compR_ptr, compR_ptr + nb_pixels); + const compG = HEAP32.subarray(compG_ptr, compG_ptr + nb_pixels); + const compB = HEAP32.subarray(compB_ptr, compB_ptr + nb_pixels); + for (let i = 0; i < nb_pixels; i++) { + imageData[4 * i] = compR[i]; + imageData[4 * i + 1] = compG[i]; + imageData[4 * i + 2] = compB[i]; + imageData[4 * i + 3] = 255; + } + } + function _storeErrorMessage(message_ptr) { + const message2 = UTF8ToString(message_ptr); + if (!Module.errorMessages) { + Module.errorMessages = message2; + } else { + Module.errorMessages += "\n" + message2; + } + } + var writeArrayToMemory = (array2, buffer2) => { + HEAP8.set(array2, buffer2); + }; + if (Module["noExitRuntime"]) noExitRuntime = Module["noExitRuntime"]; + if (Module["print"]) out = Module["print"]; + if (Module["printErr"]) err = Module["printErr"]; + if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"]; + if (Module["arguments"]) arguments_ = Module["arguments"]; + if (Module["thisProgram"]) thisProgram = Module["thisProgram"]; + if (Module["preInit"]) { + if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]]; + while (Module["preInit"].length > 0) { + Module["preInit"].shift()(); + } + } + Module["writeArrayToMemory"] = writeArrayToMemory; + var _malloc, _free, _jp2_decode, __emscripten_timeout; + function assignWasmExports(wasmExports2) { + Module["_malloc"] = _malloc = wasmExports2["t"]; + Module["_free"] = _free = wasmExports2["u"]; + Module["_jp2_decode"] = _jp2_decode = wasmExports2["v"]; + __emscripten_timeout = wasmExports2["w"]; + } + var wasmImports = { + k: __abort_js, + j: __emscripten_runtime_keepalive_clear, + l: __setitimer_js, + f: _copy_pixels_1, + e: _copy_pixels_3, + d: _copy_pixels_4, + m: _emscripten_resize_heap, + o: _environ_get, + p: _environ_sizes_get, + n: _fd_seek, + b: _fd_write, + q: _gray_to_rgba, + h: _graya_to_rgba, + c: _jsPrintWarning, + i: _proc_exit, + g: _rgb_to_rgba, + a: _storeErrorMessage + }; + function run() { + preRun(); + function doRun() { + Module["calledRun"] = true; + if (ABORT) return; + initRuntime(); + readyPromiseResolve?.(Module); + Module["onRuntimeInitialized"]?.(); + postRun(); + } + if (Module["setStatus"]) { + Module["setStatus"]("Running..."); + setTimeout(() => { + setTimeout(() => Module["setStatus"](""), 1); + doRun(); + }, 1); + } else { + doRun(); + } + } + var wasmExports; + wasmExports = await createWasm(); + run(); + if (runtimeInitialized) { + moduleRtn = Module; + } else { + moduleRtn = new Promise((resolve2, reject2) => { + readyPromiseResolve = resolve2; + readyPromiseReject = reject2; + }); + } + return moduleRtn; +} +function addState(parentState, pattern, checkFn, iterateFn, processFn) { + let state = parentState; + for (let i = 0, ii = pattern.length - 1; i < ii; i++) { + const item = pattern[i]; + state = state[item] ||= []; + } + state[pattern.at(-1)] = { + checkFn, + iterateFn, + processFn + }; +} +function hexToInt(a, size3) { + let n = 0; + for (let i = 0; i <= size3; i++) { + n = n << 8 | a[i]; + } + return n >>> 0; +} +function hexToStr(a, size3) { + if (size3 === 1) { + return String.fromCharCode(a[0], a[1]); + } + if (size3 === 3) { + return String.fromCharCode(a[0], a[1], a[2], a[3]); + } + return String.fromCharCode(...a.subarray(0, size3 + 1)); +} +function addHex(a, b2, size3) { + let c = 0; + for (let i = size3; i >= 0; i--) { + c += a[i] + b2[i]; + a[i] = c & 255; + c >>= 8; + } +} +function incHex(a, size3) { + let c = 1; + for (let i = size3; i >= 0 && c > 0; i--) { + c += a[i]; + a[i] = c & 255; + c >>= 8; + } +} +function decodeInteger(contextCache, procedure, decoder2) { + const contexts = contextCache.getContexts(procedure); + let prev = 1; + function readBits(length) { + let v = 0; + for (let i = 0; i < length; i++) { + const bit2 = decoder2.readBit(contexts, prev); + prev = prev < 256 ? prev << 1 | bit2 : (prev << 1 | bit2) & 511 | 256; + v = v << 1 | bit2; + } + return v >>> 0; + } + const sign = readBits(1); + const value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2); + let signedValue; + if (sign === 0) { + signedValue = value; + } else if (value > 0) { + signedValue = -value; + } + if (signedValue >= MIN_INT_32 && signedValue <= MAX_INT_32) { + return signedValue; + } + return null; +} +function decodeIAID(contextCache, decoder2, codeLength) { + const contexts = contextCache.getContexts("IAID"); + let prev = 1; + for (let i = 0; i < codeLength; i++) { + const bit2 = decoder2.readBit(contexts, prev); + prev = prev << 1 | bit2; + } + if (codeLength < 31) { + return prev & (1 << codeLength) - 1; + } + return prev & 2147483647; +} +function decodeBitmapTemplate0(width, height, decodingContext) { + const decoder2 = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GB"); + const bitmap = []; + let contextLabel, i, j, pixel, row, row1, row2; + const OLD_PIXEL_MASK = 31735; + for (i = 0; i < height; i++) { + row = bitmap[i] = new Uint8Array(width); + row1 = i < 1 ? row : bitmap[i - 1]; + row2 = i < 2 ? row : bitmap[i - 2]; + contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4; + for (j = 0; j < width; j++) { + row[j] = pixel = decoder2.readBit(contexts, contextLabel); + contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel; + } + } + return bitmap; +} +function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) { + if (mmr) { + const input2 = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); + return decodeMMRBitmap(input2, width, height, false); + } + if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) { + return decodeBitmapTemplate0(width, height, decodingContext); + } + const useskip = !!skip; + const template2 = CodingTemplates[templateIndex].concat(at); + template2.sort((a, b2) => a.y - b2.y || a.x - b2.x); + const templateLength = template2.length; + const templateX = new Int8Array(templateLength); + const templateY = new Int8Array(templateLength); + const changingTemplateEntries = []; + let reuseMask = 0, minX = 0, maxX = 0, minY = 0; + let c, k; + for (k = 0; k < templateLength; k++) { + templateX[k] = template2[k].x; + templateY[k] = template2[k].y; + minX = Math.min(minX, template2[k].x); + maxX = Math.max(maxX, template2[k].x); + minY = Math.min(minY, template2[k].y); + if (k < templateLength - 1 && template2[k].y === template2[k + 1].y && template2[k].x === template2[k + 1].x - 1) { + reuseMask |= 1 << templateLength - 1 - k; + } else { + changingTemplateEntries.push(k); + } + } + const changingEntriesLength = changingTemplateEntries.length; + const changingTemplateX = new Int8Array(changingEntriesLength); + const changingTemplateY = new Int8Array(changingEntriesLength); + const changingTemplateBit = new Uint16Array(changingEntriesLength); + for (c = 0; c < changingEntriesLength; c++) { + k = changingTemplateEntries[c]; + changingTemplateX[c] = template2[k].x; + changingTemplateY[c] = template2[k].y; + changingTemplateBit[c] = 1 << templateLength - 1 - k; + } + const sbb_left = -minX; + const sbb_top = -minY; + const sbb_right = width - maxX; + const pseudoPixelContext = ReusedContexts[templateIndex]; + let row = new Uint8Array(width); + const bitmap = []; + const decoder2 = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GB"); + let ltp = 0, j, i0, j0, contextLabel = 0, bit2, shift; + for (let i = 0; i < height; i++) { + if (prediction) { + const sltp = decoder2.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + bitmap.push(row); + continue; + } + } + row = new Uint8Array(row); + bitmap.push(row); + for (j = 0; j < width; j++) { + if (useskip && skip[i][j]) { + row[j] = 0; + continue; + } + if (j >= sbb_left && j < sbb_right && i >= sbb_top) { + contextLabel = contextLabel << 1 & reuseMask; + for (k = 0; k < changingEntriesLength; k++) { + i0 = i + changingTemplateY[k]; + j0 = j + changingTemplateX[k]; + bit2 = bitmap[i0][j0]; + if (bit2) { + bit2 = changingTemplateBit[k]; + contextLabel |= bit2; + } + } + } else { + contextLabel = 0; + shift = templateLength - 1; + for (k = 0; k < templateLength; k++, shift--) { + j0 = j + templateX[k]; + if (j0 >= 0 && j0 < width) { + i0 = i + templateY[k]; + if (i0 >= 0) { + bit2 = bitmap[i0][j0]; + if (bit2) { + contextLabel |= bit2 << shift; + } + } + } + } + } + const pixel = decoder2.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; +} +function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) { + let codingTemplate = RefinementTemplates[templateIndex].coding; + if (templateIndex === 0) { + codingTemplate = codingTemplate.concat([at[0]]); + } + const codingTemplateLength = codingTemplate.length; + const codingTemplateX = new Int32Array(codingTemplateLength); + const codingTemplateY = new Int32Array(codingTemplateLength); + let k; + for (k = 0; k < codingTemplateLength; k++) { + codingTemplateX[k] = codingTemplate[k].x; + codingTemplateY[k] = codingTemplate[k].y; + } + let referenceTemplate = RefinementTemplates[templateIndex].reference; + if (templateIndex === 0) { + referenceTemplate = referenceTemplate.concat([at[1]]); + } + const referenceTemplateLength = referenceTemplate.length; + const referenceTemplateX = new Int32Array(referenceTemplateLength); + const referenceTemplateY = new Int32Array(referenceTemplateLength); + for (k = 0; k < referenceTemplateLength; k++) { + referenceTemplateX[k] = referenceTemplate[k].x; + referenceTemplateY[k] = referenceTemplate[k].y; + } + const referenceWidth = referenceBitmap[0].length; + const referenceHeight = referenceBitmap.length; + const pseudoPixelContext = RefinementReusedContexts[templateIndex]; + const bitmap = []; + const decoder2 = decodingContext.decoder; + const contexts = decodingContext.contextCache.getContexts("GR"); + let ltp = 0; + for (let i = 0; i < height; i++) { + if (prediction) { + const sltp = decoder2.readBit(contexts, pseudoPixelContext); + ltp ^= sltp; + if (ltp) { + throw new Jbig2Error("prediction is not supported"); + } + } + const row = new Uint8Array(width); + bitmap.push(row); + for (let j = 0; j < width; j++) { + let i0, j0; + let contextLabel = 0; + for (k = 0; k < codingTemplateLength; k++) { + i0 = i + codingTemplateY[k]; + j0 = j + codingTemplateX[k]; + if (i0 < 0 || j0 < 0 || j0 >= width) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | bitmap[i0][j0]; + } + } + for (k = 0; k < referenceTemplateLength; k++) { + i0 = i + referenceTemplateY[k] - offsetY; + j0 = j + referenceTemplateX[k] - offsetX; + if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) { + contextLabel <<= 1; + } else { + contextLabel = contextLabel << 1 | referenceBitmap[i0][j0]; + } + } + const pixel = decoder2.readBit(contexts, contextLabel); + row[j] = pixel; + } + } + return bitmap; +} +function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) { + if (huffman && refinement) { + throw new Jbig2Error("symbol refinement with Huffman is not supported"); + } + const newSymbols = []; + let currentHeight = 0; + let symbolCodeLength = log2(symbols.length + numberOfNewSymbols); + const decoder2 = decodingContext.decoder; + const contextCache = decodingContext.contextCache; + let tableB1, symbolWidths; + if (huffman) { + tableB1 = getStandardTable(1); + symbolWidths = []; + symbolCodeLength = Math.max(symbolCodeLength, 1); + } + while (newSymbols.length < numberOfNewSymbols) { + const deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, "IADH", decoder2); + currentHeight += deltaHeight; + let currentWidth = 0, totalWidth = 0; + const firstSymbol = huffman ? symbolWidths.length : 0; + while (true) { + const deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, "IADW", decoder2); + if (deltaWidth === null) { + break; + } + currentWidth += deltaWidth; + totalWidth += currentWidth; + let bitmap; + if (refinement) { + const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder2); + if (numberOfInstances > 1) { + bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput); + } else { + const symbolId = decodeIAID(contextCache, decoder2, symbolCodeLength); + const rdx = decodeInteger(contextCache, "IARDX", decoder2); + const rdy = decodeInteger(contextCache, "IARDY", decoder2); + const symbol2 = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length]; + bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol2, rdx, rdy, false, refinementAt, decodingContext); + } + newSymbols.push(bitmap); + } else if (huffman) { + symbolWidths.push(currentWidth); + } else { + bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext); + newSymbols.push(bitmap); + } + } + if (huffman && !refinement) { + const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput); + huffmanInput.byteAlign(); + let collectiveBitmap; + if (bitmapSize === 0) { + collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight); + } else { + const originalEnd = huffmanInput.end; + const bitmapEnd = huffmanInput.position + bitmapSize; + huffmanInput.end = bitmapEnd; + collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false); + huffmanInput.end = originalEnd; + huffmanInput.position = bitmapEnd; + } + const numberOfSymbolsDecoded = symbolWidths.length; + if (firstSymbol === numberOfSymbolsDecoded - 1) { + newSymbols.push(collectiveBitmap); + } else { + let i2, y, xMin = 0, xMax, bitmapWidth, symbolBitmap; + for (i2 = firstSymbol; i2 < numberOfSymbolsDecoded; i2++) { + bitmapWidth = symbolWidths[i2]; + xMax = xMin + bitmapWidth; + symbolBitmap = []; + for (y = 0; y < currentHeight; y++) { + symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); + } + newSymbols.push(symbolBitmap); + xMin = xMax; + } + } + } + } + const exportedSymbols = [], flags = []; + let currentFlag = false, i, ii; + const totalSymbolsLength = symbols.length + numberOfNewSymbols; + while (flags.length < totalSymbolsLength) { + let runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, "IAEX", decoder2); + while (runLength--) { + flags.push(currentFlag); + } + currentFlag = !currentFlag; + } + for (i = 0, ii = symbols.length; i < ii; i++) { + if (flags[i]) { + exportedSymbols.push(symbols[i]); + } + } + for (let j = 0; j < numberOfNewSymbols; i++, j++) { + if (flags[i]) { + exportedSymbols.push(newSymbols[j]); + } + } + return exportedSymbols; +} +function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) { + if (huffman && refinement) { + throw new Jbig2Error("refinement with Huffman is not supported"); + } + const bitmap = []; + let i, row; + for (i = 0; i < height; i++) { + row = new Uint8Array(width); + if (defaultPixelValue) { + row.fill(defaultPixelValue); + } + bitmap.push(row); + } + const decoder2 = decodingContext.decoder; + const contextCache = decodingContext.contextCache; + let stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, "IADT", decoder2); + let firstS = 0; + i = 0; + while (i < numberOfSymbolInstances) { + const deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, "IADT", decoder2); + stripT += deltaT; + const deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, "IAFS", decoder2); + firstS += deltaFirstS; + let currentS = firstS; + do { + let currentT = 0; + if (stripSize > 1) { + currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, "IAIT", decoder2); + } + const t = stripSize * stripT + currentT; + const symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder2, symbolCodeLength); + const applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, "IARI", decoder2)); + let symbolBitmap = inputSymbols[symbolId]; + let symbolWidth = symbolBitmap[0].length; + let symbolHeight = symbolBitmap.length; + if (applyRefinement) { + const rdw = decodeInteger(contextCache, "IARDW", decoder2); + const rdh = decodeInteger(contextCache, "IARDH", decoder2); + const rdx = decodeInteger(contextCache, "IARDX", decoder2); + const rdy = decodeInteger(contextCache, "IARDY", decoder2); + symbolWidth += rdw; + symbolHeight += rdh; + symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext); + } + let increment = 0; + if (!transposed) { + if (referenceCorner > 1) { + currentS += symbolWidth - 1; + } else { + increment = symbolWidth - 1; + } + } else if (!(referenceCorner & 1)) { + currentS += symbolHeight - 1; + } else { + increment = symbolHeight - 1; + } + const offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1); + const offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0); + let s2, t2, symbolRow; + if (transposed) { + for (s2 = 0; s2 < symbolHeight; s2++) { + row = bitmap[offsetS + s2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[s2]; + const maxWidth = Math.min(width - offsetT, symbolWidth); + switch (combinationOperator) { + case 0: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] |= symbolRow[t2]; + } + break; + case 2: + for (t2 = 0; t2 < maxWidth; t2++) { + row[offsetT + t2] ^= symbolRow[t2]; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + } else { + for (t2 = 0; t2 < symbolHeight; t2++) { + row = bitmap[offsetT + t2]; + if (!row) { + continue; + } + symbolRow = symbolBitmap[t2]; + switch (combinationOperator) { + case 0: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] |= symbolRow[s2]; + } + break; + case 2: + for (s2 = 0; s2 < symbolWidth; s2++) { + row[offsetS + s2] ^= symbolRow[s2]; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + } + i++; + const deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, "IADS", decoder2); + if (deltaS === null) { + break; + } + currentS += increment + deltaS + dsOffset; + } while (true); + } + return bitmap; +} +function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template2, decodingContext) { + const at = []; + if (!mmr) { + at.push({ + x: -patternWidth, + y: 0 + }); + if (template2 === 0) { + at.push({ + x: -3, + y: -1 + }, { + x: 2, + y: -2 + }, { + x: -2, + y: -2 + }); + } + } + const collectiveWidth = (maxPatternIndex + 1) * patternWidth; + const collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template2, false, null, at, decodingContext); + const patterns = []; + for (let i = 0; i <= maxPatternIndex; i++) { + const patternBitmap = []; + const xMin = patternWidth * i; + const xMax = xMin + patternWidth; + for (let y = 0; y < patternHeight; y++) { + patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax)); + } + patterns.push(patternBitmap); + } + return patterns; +} +function decodeHalftoneRegion(mmr, patterns, template2, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) { + const skip = null; + if (enableSkip) { + throw new Jbig2Error("skip is not supported"); + } + if (combinationOperator !== 0) { + throw new Jbig2Error(`operator "${combinationOperator}" is not supported in halftone region`); + } + const regionBitmap = []; + let i, j, row; + for (i = 0; i < regionHeight; i++) { + row = new Uint8Array(regionWidth); + if (defaultPixelValue) { + row.fill(defaultPixelValue); + } + regionBitmap.push(row); + } + const numberOfPatterns = patterns.length; + const pattern0 = patterns[0]; + const patternWidth = pattern0[0].length, patternHeight = pattern0.length; + const bitsPerValue = log2(numberOfPatterns); + const at = []; + if (!mmr) { + at.push({ + x: template2 <= 1 ? 3 : 2, + y: -1 + }); + if (template2 === 0) { + at.push({ + x: -3, + y: -1 + }, { + x: 2, + y: -2 + }, { + x: -2, + y: -2 + }); + } + } + const grayScaleBitPlanes = []; + let mmrInput, bitmap; + if (mmr) { + mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end); + } + for (i = bitsPerValue - 1; i >= 0; i--) { + if (mmr) { + bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true); + } else { + bitmap = decodeBitmap(false, gridWidth, gridHeight, template2, false, skip, at, decodingContext); + } + grayScaleBitPlanes[i] = bitmap; + } + let mg, ng, bit2, patternIndex, patternBitmap, x, y, patternRow, regionRow; + for (mg = 0; mg < gridHeight; mg++) { + for (ng = 0; ng < gridWidth; ng++) { + bit2 = 0; + patternIndex = 0; + for (j = bitsPerValue - 1; j >= 0; j--) { + bit2 ^= grayScaleBitPlanes[j][mg][ng]; + patternIndex |= bit2 << j; + } + patternBitmap = patterns[patternIndex]; + x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8; + y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8; + if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) { + for (i = 0; i < patternHeight; i++) { + regionRow = regionBitmap[y + i]; + patternRow = patternBitmap[i]; + for (j = 0; j < patternWidth; j++) { + regionRow[x + j] |= patternRow[j]; + } + } + } else { + let regionX, regionY; + for (i = 0; i < patternHeight; i++) { + regionY = y + i; + if (regionY < 0 || regionY >= regionHeight) { + continue; + } + regionRow = regionBitmap[regionY]; + patternRow = patternBitmap[i]; + for (j = 0; j < patternWidth; j++) { + regionX = x + j; + if (regionX >= 0 && regionX < regionWidth) { + regionRow[regionX] |= patternRow[j]; + } + } + } + } + } + } + return regionBitmap; +} +function readSegmentHeader(data, start) { + const segmentHeader = {}; + segmentHeader.number = readUint32(data, start); + const flags = data[start + 4]; + const segmentType = flags & 63; + if (!SegmentTypes[segmentType]) { + throw new Jbig2Error("invalid segment type: " + segmentType); + } + segmentHeader.type = segmentType; + segmentHeader.typeName = SegmentTypes[segmentType]; + segmentHeader.deferredNonRetain = !!(flags & 128); + const pageAssociationFieldSize = !!(flags & 64); + const referredFlags = data[start + 5]; + let referredToCount = referredFlags >> 5 & 7; + const retainBits = [referredFlags & 31]; + let position = start + 6; + if (referredFlags === 7) { + referredToCount = readUint32(data, position - 1) & 536870911; + position += 3; + let bytes = referredToCount + 7 >> 3; + retainBits[0] = data[position++]; + while (--bytes > 0) { + retainBits.push(data[position++]); + } + } else if (referredFlags === 5 || referredFlags === 6) { + throw new Jbig2Error("invalid referred-to flags"); + } + segmentHeader.retainBits = retainBits; + let referredToSegmentNumberSize = 4; + if (segmentHeader.number <= 256) { + referredToSegmentNumberSize = 1; + } else if (segmentHeader.number <= 65536) { + referredToSegmentNumberSize = 2; + } + const referredTo = []; + let i, ii; + for (i = 0; i < referredToCount; i++) { + let number4; + if (referredToSegmentNumberSize === 1) { + number4 = data[position]; + } else if (referredToSegmentNumberSize === 2) { + number4 = readUint16(data, position); + } else { + number4 = readUint32(data, position); + } + referredTo.push(number4); + position += referredToSegmentNumberSize; + } + segmentHeader.referredTo = referredTo; + if (!pageAssociationFieldSize) { + segmentHeader.pageAssociation = data[position++]; + } else { + segmentHeader.pageAssociation = readUint32(data, position); + position += 4; + } + segmentHeader.length = readUint32(data, position); + position += 4; + if (segmentHeader.length === 4294967295) { + if (segmentType === 38) { + const genericRegionInfo = readRegionSegmentInformation(data, position); + const genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength]; + const genericRegionMmr = !!(genericRegionSegmentFlags & 1); + const searchPatternLength = 6; + const searchPattern = new Uint8Array(searchPatternLength); + if (!genericRegionMmr) { + searchPattern[0] = 255; + searchPattern[1] = 172; + } + searchPattern[2] = genericRegionInfo.height >>> 24 & 255; + searchPattern[3] = genericRegionInfo.height >> 16 & 255; + searchPattern[4] = genericRegionInfo.height >> 8 & 255; + searchPattern[5] = genericRegionInfo.height & 255; + for (i = position, ii = data.length; i < ii; i++) { + let j = 0; + while (j < searchPatternLength && searchPattern[j] === data[i + j]) { + j++; + } + if (j === searchPatternLength) { + segmentHeader.length = i + searchPatternLength; + break; + } + } + if (segmentHeader.length === 4294967295) { + throw new Jbig2Error("segment end was not found"); + } + } else { + throw new Jbig2Error("invalid unknown segment length"); + } + } + segmentHeader.headerEnd = position; + return segmentHeader; +} +function readSegments(header, data, start, end) { + const segments = []; + let position = start; + while (position < end) { + const segmentHeader = readSegmentHeader(data, position); + position = segmentHeader.headerEnd; + const segment = { + header: segmentHeader, + data + }; + if (!header.randomAccess) { + segment.start = position; + position += segmentHeader.length; + segment.end = position; + } + segments.push(segment); + if (segmentHeader.type === 51) { + break; + } + } + if (header.randomAccess) { + for (let i = 0, ii = segments.length; i < ii; i++) { + segments[i].start = position; + position += segments[i].header.length; + segments[i].end = position; + } + } + return segments; +} +function readRegionSegmentInformation(data, start) { + return { + width: readUint32(data, start), + height: readUint32(data, start + 4), + x: readUint32(data, start + 8), + y: readUint32(data, start + 12), + combinationOperator: data[start + 16] & 7 + }; +} +function processSegment(segment, visitor) { + const header = segment.header; + const data = segment.data, end = segment.end; + let position = segment.start; + let args, at, i, atLength; + switch (header.type) { + case 0: + const dictionary = {}; + const dictionaryFlags = readUint16(data, position); + dictionary.huffman = !!(dictionaryFlags & 1); + dictionary.refinement = !!(dictionaryFlags & 2); + dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3; + dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3; + dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1; + dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1; + dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256); + dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512); + dictionary.template = dictionaryFlags >> 10 & 3; + dictionary.refinementTemplate = dictionaryFlags >> 12 & 1; + position += 2; + if (!dictionary.huffman) { + atLength = dictionary.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.at = at; + } + if (dictionary.refinement && !dictionary.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + dictionary.refinementAt = at; + } + dictionary.numberOfExportedSymbols = readUint32(data, position); + position += 4; + dictionary.numberOfNewSymbols = readUint32(data, position); + position += 4; + args = [dictionary, header.number, header.referredTo, data, position, end]; + break; + case 6: + case 7: + const textRegion = {}; + textRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const textRegionSegmentFlags = readUint16(data, position); + position += 2; + textRegion.huffman = !!(textRegionSegmentFlags & 1); + textRegion.refinement = !!(textRegionSegmentFlags & 2); + textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3; + textRegion.stripSize = 1 << textRegion.logStripSize; + textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3; + textRegion.transposed = !!(textRegionSegmentFlags & 64); + textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3; + textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1; + textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27; + textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1; + if (textRegion.huffman) { + const textRegionHuffmanFlags = readUint16(data, position); + position += 2; + textRegion.huffmanFS = textRegionHuffmanFlags & 3; + textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3; + textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3; + textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3; + textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3; + textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3; + textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3; + textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 16384); + } + if (textRegion.refinement && !textRegion.refinementTemplate) { + at = []; + for (i = 0; i < 2; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + textRegion.refinementAt = at; + } + textRegion.numberOfSymbolInstances = readUint32(data, position); + position += 4; + args = [textRegion, header.referredTo, data, position, end]; + break; + case 16: + const patternDictionary = {}; + const patternDictionaryFlags = data[position++]; + patternDictionary.mmr = !!(patternDictionaryFlags & 1); + patternDictionary.template = patternDictionaryFlags >> 1 & 3; + patternDictionary.patternWidth = data[position++]; + patternDictionary.patternHeight = data[position++]; + patternDictionary.maxPatternIndex = readUint32(data, position); + position += 4; + args = [patternDictionary, header.number, data, position, end]; + break; + case 22: + case 23: + const halftoneRegion = {}; + halftoneRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const halftoneRegionFlags = data[position++]; + halftoneRegion.mmr = !!(halftoneRegionFlags & 1); + halftoneRegion.template = halftoneRegionFlags >> 1 & 3; + halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8); + halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7; + halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1; + halftoneRegion.gridWidth = readUint32(data, position); + position += 4; + halftoneRegion.gridHeight = readUint32(data, position); + position += 4; + halftoneRegion.gridOffsetX = readUint32(data, position) & 4294967295; + position += 4; + halftoneRegion.gridOffsetY = readUint32(data, position) & 4294967295; + position += 4; + halftoneRegion.gridVectorX = readUint16(data, position); + position += 2; + halftoneRegion.gridVectorY = readUint16(data, position); + position += 2; + args = [halftoneRegion, header.referredTo, data, position, end]; + break; + case 38: + case 39: + const genericRegion = {}; + genericRegion.info = readRegionSegmentInformation(data, position); + position += RegionSegmentInformationFieldLength; + const genericRegionSegmentFlags = data[position++]; + genericRegion.mmr = !!(genericRegionSegmentFlags & 1); + genericRegion.template = genericRegionSegmentFlags >> 1 & 3; + genericRegion.prediction = !!(genericRegionSegmentFlags & 8); + if (!genericRegion.mmr) { + atLength = genericRegion.template === 0 ? 4 : 1; + at = []; + for (i = 0; i < atLength; i++) { + at.push({ + x: readInt8(data, position), + y: readInt8(data, position + 1) + }); + position += 2; + } + genericRegion.at = at; + } + args = [genericRegion, data, position, end]; + break; + case 48: + const pageInfo = { + width: readUint32(data, position), + height: readUint32(data, position + 4), + resolutionX: readUint32(data, position + 8), + resolutionY: readUint32(data, position + 12) + }; + if (pageInfo.height === 4294967295) { + delete pageInfo.height; + } + const pageSegmentFlags = data[position + 16]; + readUint16(data, position + 17); + pageInfo.lossless = !!(pageSegmentFlags & 1); + pageInfo.refinement = !!(pageSegmentFlags & 2); + pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1; + pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3; + pageInfo.requiresBuffer = !!(pageSegmentFlags & 32); + pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64); + args = [pageInfo]; + break; + case 49: + break; + case 50: + break; + case 51: + break; + case 53: + args = [header.number, data, position, end]; + break; + case 62: + break; + default: + throw new Jbig2Error(`segment type ${header.typeName}(${header.type}) is not implemented`); + } + const callbackName = "on" + header.typeName; + if (callbackName in visitor) { + visitor[callbackName].apply(visitor, args); + } +} +function processSegments(segments, visitor) { + for (let i = 0, ii = segments.length; i < ii; i++) { + processSegment(segments[i], visitor); + } +} +function parseJbig2Chunks(chunks) { + const visitor = new SimpleSegmentVisitor(); + for (let i = 0, ii = chunks.length; i < ii; i++) { + const chunk2 = chunks[i]; + const segments = readSegments({}, chunk2.data, chunk2.start, chunk2.end); + processSegments(segments, visitor); + } + return visitor.buffer; +} +function decodeTablesSegment(data, start, end) { + const flags = data[start]; + const lowestValue = readUint32(data, start + 1) & 4294967295; + const highestValue = readUint32(data, start + 5) & 4294967295; + const reader = new Reader(data, start + 9, end); + const prefixSizeBits = (flags >> 1 & 7) + 1; + const rangeSizeBits = (flags >> 4 & 7) + 1; + const lines = []; + let prefixLength, rangeLength, currentRangeLow = lowestValue; + do { + prefixLength = reader.readBits(prefixSizeBits); + rangeLength = reader.readBits(rangeSizeBits); + lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0])); + currentRangeLow += 1 << rangeLength; + } while (currentRangeLow < highestValue); + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"])); + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0])); + if (flags & 1) { + prefixLength = reader.readBits(prefixSizeBits); + lines.push(new HuffmanLine([prefixLength, 0])); + } + return new HuffmanTable(lines, false); +} +function getStandardTable(number4) { + let table2 = standardTablesCache[number4]; + if (table2) { + return table2; + } + let lines; + switch (number4) { + case 1: + lines = [[0, 1, 4, 0], [16, 2, 8, 2], [272, 3, 16, 6], [65808, 3, 32, 7]]; + break; + case 2: + lines = [[0, 1, 0, 0], [1, 2, 0, 2], [2, 3, 0, 6], [3, 4, 3, 14], [11, 5, 6, 30], [75, 6, 32, 62], [6, 63]]; + break; + case 3: + lines = [[-256, 8, 8, 254], [0, 1, 0, 0], [1, 2, 0, 2], [2, 3, 0, 6], [3, 4, 3, 14], [11, 5, 6, 30], [-257, 8, 32, 255, "lower"], [75, 7, 32, 126], [6, 62]]; + break; + case 4: + lines = [[1, 1, 0, 0], [2, 2, 0, 2], [3, 3, 0, 6], [4, 4, 3, 14], [12, 5, 6, 30], [76, 5, 32, 31]]; + break; + case 5: + lines = [[-255, 7, 8, 126], [1, 1, 0, 0], [2, 2, 0, 2], [3, 3, 0, 6], [4, 4, 3, 14], [12, 5, 6, 30], [-256, 7, 32, 127, "lower"], [76, 6, 32, 62]]; + break; + case 6: + lines = [[-2048, 5, 10, 28], [-1024, 4, 9, 8], [-512, 4, 8, 9], [-256, 4, 7, 10], [-128, 5, 6, 29], [-64, 5, 5, 30], [-32, 4, 5, 11], [0, 2, 7, 0], [128, 3, 7, 2], [256, 3, 8, 3], [512, 4, 9, 12], [1024, 4, 10, 13], [-2049, 6, 32, 62, "lower"], [2048, 6, 32, 63]]; + break; + case 7: + lines = [[-1024, 4, 9, 8], [-512, 3, 8, 0], [-256, 4, 7, 9], [-128, 5, 6, 26], [-64, 5, 5, 27], [-32, 4, 5, 10], [0, 4, 5, 11], [32, 5, 5, 28], [64, 5, 6, 29], [128, 4, 7, 12], [256, 3, 8, 1], [512, 3, 9, 2], [1024, 3, 10, 3], [-1025, 5, 32, 30, "lower"], [2048, 5, 32, 31]]; + break; + case 8: + lines = [[-15, 8, 3, 252], [-7, 9, 1, 508], [-5, 8, 1, 253], [-3, 9, 0, 509], [-2, 7, 0, 124], [-1, 4, 0, 10], [0, 2, 1, 0], [2, 5, 0, 26], [3, 6, 0, 58], [4, 3, 4, 4], [20, 6, 1, 59], [22, 4, 4, 11], [38, 4, 5, 12], [70, 5, 6, 27], [134, 5, 7, 28], [262, 6, 7, 60], [390, 7, 8, 125], [646, 6, 10, 61], [-16, 9, 32, 510, "lower"], [1670, 9, 32, 511], [2, 1]]; + break; + case 9: + lines = [[-31, 8, 4, 252], [-15, 9, 2, 508], [-11, 8, 2, 253], [-7, 9, 1, 509], [-5, 7, 1, 124], [-3, 4, 1, 10], [-1, 3, 1, 2], [1, 3, 1, 3], [3, 5, 1, 26], [5, 6, 1, 58], [7, 3, 5, 4], [39, 6, 2, 59], [43, 4, 5, 11], [75, 4, 6, 12], [139, 5, 7, 27], [267, 5, 8, 28], [523, 6, 8, 60], [779, 7, 9, 125], [1291, 6, 11, 61], [-32, 9, 32, 510, "lower"], [3339, 9, 32, 511], [2, 0]]; + break; + case 10: + lines = [[-21, 7, 4, 122], [-5, 8, 0, 252], [-4, 7, 0, 123], [-3, 5, 0, 24], [-2, 2, 2, 0], [2, 5, 0, 25], [3, 6, 0, 54], [4, 7, 0, 124], [5, 8, 0, 253], [6, 2, 6, 1], [70, 5, 5, 26], [102, 6, 5, 55], [134, 6, 6, 56], [198, 6, 7, 57], [326, 6, 8, 58], [582, 6, 9, 59], [1094, 6, 10, 60], [2118, 7, 11, 125], [-22, 8, 32, 254, "lower"], [4166, 8, 32, 255], [2, 2]]; + break; + case 11: + lines = [[1, 1, 0, 0], [2, 2, 1, 2], [4, 4, 0, 12], [5, 4, 1, 13], [7, 5, 1, 28], [9, 5, 2, 29], [13, 6, 2, 60], [17, 7, 2, 122], [21, 7, 3, 123], [29, 7, 4, 124], [45, 7, 5, 125], [77, 7, 6, 126], [141, 7, 32, 127]]; + break; + case 12: + lines = [[1, 1, 0, 0], [2, 2, 0, 2], [3, 3, 1, 6], [5, 5, 0, 28], [6, 5, 1, 29], [8, 6, 1, 60], [10, 7, 0, 122], [11, 7, 1, 123], [13, 7, 2, 124], [17, 7, 3, 125], [25, 7, 4, 126], [41, 8, 5, 254], [73, 8, 32, 255]]; + break; + case 13: + lines = [[1, 1, 0, 0], [2, 3, 0, 4], [3, 4, 0, 12], [4, 5, 0, 28], [5, 4, 1, 13], [7, 3, 3, 5], [15, 6, 1, 58], [17, 6, 2, 59], [21, 6, 3, 60], [29, 6, 4, 61], [45, 6, 5, 62], [77, 7, 6, 126], [141, 7, 32, 127]]; + break; + case 14: + lines = [[-2, 3, 0, 4], [-1, 3, 0, 5], [0, 1, 0, 0], [1, 3, 0, 6], [2, 3, 0, 7]]; + break; + case 15: + lines = [[-24, 7, 4, 124], [-8, 6, 2, 60], [-4, 5, 1, 28], [-2, 4, 0, 12], [-1, 3, 0, 4], [0, 1, 0, 0], [1, 3, 0, 5], [2, 4, 0, 13], [3, 5, 1, 29], [5, 6, 2, 61], [9, 7, 4, 125], [-25, 7, 32, 126, "lower"], [25, 7, 32, 127]]; + break; + default: + throw new Jbig2Error(`standard table B.${number4} does not exist`); + } + for (let i = 0, ii = lines.length; i < ii; i++) { + lines[i] = new HuffmanLine(lines[i]); + } + table2 = new HuffmanTable(lines, true); + standardTablesCache[number4] = table2; + return table2; +} +function getCustomHuffmanTable(index2, referredTo, customTables) { + let currentIndex = 0; + for (let i = 0, ii = referredTo.length; i < ii; i++) { + const table2 = customTables[referredTo[i]]; + if (table2) { + if (index2 === currentIndex) { + return table2; + } + currentIndex++; + } + } + throw new Jbig2Error("can't find custom Huffman table"); +} +function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) { + const codes = []; + for (let i = 0; i <= 34; i++) { + const codeLength = reader.readBits(4); + codes.push(new HuffmanLine([i, codeLength, 0, 0])); + } + const runCodesTable = new HuffmanTable(codes, false); + codes.length = 0; + for (let i = 0; i < numberOfSymbols; ) { + const codeLength = runCodesTable.decode(reader); + if (codeLength >= 32) { + let repeatedLength, numberOfRepeats, j; + switch (codeLength) { + case 32: + if (i === 0) { + throw new Jbig2Error("no previous value in symbol ID table"); + } + numberOfRepeats = reader.readBits(2) + 3; + repeatedLength = codes[i - 1].prefixLength; + break; + case 33: + numberOfRepeats = reader.readBits(3) + 3; + repeatedLength = 0; + break; + case 34: + numberOfRepeats = reader.readBits(7) + 11; + repeatedLength = 0; + break; + default: + throw new Jbig2Error("invalid code length in symbol ID table"); + } + for (j = 0; j < numberOfRepeats; j++) { + codes.push(new HuffmanLine([i, repeatedLength, 0, 0])); + i++; + } + } else { + codes.push(new HuffmanLine([i, codeLength, 0, 0])); + i++; + } + } + reader.byteAlign(); + const symbolIDTable = new HuffmanTable(codes, false); + let customIndex = 0, tableFirstS, tableDeltaS, tableDeltaT; + switch (textRegion.huffmanFS) { + case 0: + case 1: + tableFirstS = getStandardTable(textRegion.huffmanFS + 6); + break; + case 3: + tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman FS selector"); + } + switch (textRegion.huffmanDS) { + case 0: + case 1: + case 2: + tableDeltaS = getStandardTable(textRegion.huffmanDS + 8); + break; + case 3: + tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DS selector"); + } + switch (textRegion.huffmanDT) { + case 0: + case 1: + case 2: + tableDeltaT = getStandardTable(textRegion.huffmanDT + 11); + break; + case 3: + tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DT selector"); + } + if (textRegion.refinement) { + throw new Jbig2Error("refinement with Huffman is not supported"); + } + return { + symbolIDTable, + tableFirstS, + tableDeltaS, + tableDeltaT + }; +} +function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) { + let customIndex = 0, tableDeltaHeight, tableDeltaWidth; + switch (dictionary.huffmanDHSelector) { + case 0: + case 1: + tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4); + break; + case 3: + tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DH selector"); + } + switch (dictionary.huffmanDWSelector) { + case 0: + case 1: + tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2); + break; + case 3: + tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + break; + default: + throw new Jbig2Error("invalid Huffman DW selector"); + } + let tableBitmapSize, tableAggregateInstances; + if (dictionary.bitmapSizeSelector) { + tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables); + customIndex++; + } else { + tableBitmapSize = getStandardTable(1); + } + if (dictionary.aggregationInstancesSelector) { + tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables); + } else { + tableAggregateInstances = getStandardTable(1); + } + return { + tableDeltaHeight, + tableDeltaWidth, + tableBitmapSize, + tableAggregateInstances + }; +} +function readUncompressedBitmap(reader, width, height) { + const bitmap = []; + for (let y = 0; y < height; y++) { + const row = new Uint8Array(width); + bitmap.push(row); + for (let x = 0; x < width; x++) { + row[x] = reader.readBit(); + } + reader.byteAlign(); + } + return bitmap; +} +function decodeMMRBitmap(input2, width, height, endOfBlock) { + const params = { + K: -1, + Columns: width, + Rows: height, + BlackIs1: true, + EndOfBlock: endOfBlock + }; + const decoder2 = new CCITTFaxDecoder(input2, params); + const bitmap = []; + let currentByte, eof = false; + for (let y = 0; y < height; y++) { + const row = new Uint8Array(width); + bitmap.push(row); + let shift = -1; + for (let x = 0; x < width; x++) { + if (shift < 0) { + currentByte = decoder2.readNextChar(); + if (currentByte === -1) { + currentByte = 0; + eof = true; + } + shift = 7; + } + row[x] = currentByte >> shift & 1; + shift--; + } + } + if (endOfBlock && !eof) { + const lookForEOFLimit = 5; + for (let i = 0; i < lookForEOFLimit; i++) { + if (decoder2.readNextChar() === -1) { + break; + } + } + } + return bitmap; +} +function getInlineImageCacheKey(bytes) { + const strBuf = [], ii = bytes.length; + let i = 0; + while (i < ii - 1) { + strBuf.push(bytes[i++] << 8 | bytes[i++]); + } + if (i < ii) { + strBuf.push(bytes[i]); + } + return ii + "_" + String.fromCharCode.apply(null, strBuf); +} +function toHexDigit(ch2) { + if (ch2 >= 48 && ch2 <= 57) { + return ch2 & 15; + } + if (ch2 >= 65 && ch2 <= 70 || ch2 >= 97 && ch2 <= 102) { + return (ch2 & 15) + 9; + } + return -1; +} +function strToInt(str) { + let a = 0; + for (let i = 0; i < str.length; i++) { + a = a << 8 | str.charCodeAt(i); + } + return a >>> 0; +} +function expectString(obj2) { + if (typeof obj2 !== "string") { + throw new FormatError3("Malformed CMap: expected string."); + } +} +function expectInt(obj2) { + if (!Number.isInteger(obj2)) { + throw new FormatError3("Malformed CMap: expected int."); + } +} +function parseBfChar(cMap, lexer) { + while (true) { + let obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } + if (isCmd(obj2, "endbfchar")) { + return; + } + expectString(obj2); + const src = strToInt(obj2); + obj2 = lexer.getObj(); + expectString(obj2); + const dst = obj2; + cMap.mapOne(src, dst); + } +} +function parseBfRange(cMap, lexer) { + while (true) { + let obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } + if (isCmd(obj2, "endbfrange")) { + return; + } + expectString(obj2); + const low = strToInt(obj2); + obj2 = lexer.getObj(); + expectString(obj2); + const high = strToInt(obj2); + obj2 = lexer.getObj(); + if (Number.isInteger(obj2) || typeof obj2 === "string") { + const dstLow = Number.isInteger(obj2) ? String.fromCharCode(obj2) : obj2; + cMap.mapBfRange(low, high, dstLow); + } else if (isCmd(obj2, "[")) { + obj2 = lexer.getObj(); + const array2 = []; + while (!isCmd(obj2, "]") && obj2 !== EOF) { + array2.push(obj2); + obj2 = lexer.getObj(); + } + cMap.mapBfRangeToArray(low, high, array2); + } else { + break; + } + } + throw new FormatError3("Invalid bf range."); +} +function parseCidChar(cMap, lexer) { + while (true) { + let obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } + if (isCmd(obj2, "endcidchar")) { + return; + } + expectString(obj2); + const src = strToInt(obj2); + obj2 = lexer.getObj(); + expectInt(obj2); + const dst = obj2; + cMap.mapOne(src, dst); + } +} +function parseCidRange(cMap, lexer) { + while (true) { + let obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } + if (isCmd(obj2, "endcidrange")) { + return; + } + expectString(obj2); + const low = strToInt(obj2); + obj2 = lexer.getObj(); + expectString(obj2); + const high = strToInt(obj2); + obj2 = lexer.getObj(); + expectInt(obj2); + const dstLow = obj2; + cMap.mapCidRange(low, high, dstLow); + } +} +function parseCodespaceRange(cMap, lexer) { + while (true) { + let obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } + if (isCmd(obj2, "endcodespacerange")) { + return; + } + if (typeof obj2 !== "string") { + break; + } + const low = strToInt(obj2); + obj2 = lexer.getObj(); + if (typeof obj2 !== "string") { + break; + } + const high = strToInt(obj2); + cMap.addCodespaceRange(obj2.length, low, high); + } + throw new FormatError3("Invalid codespace range."); +} +function parseWMode(cMap, lexer) { + const obj2 = lexer.getObj(); + if (Number.isInteger(obj2)) { + cMap.vertical = !!obj2; + } +} +function parseCMapName(cMap, lexer) { + const obj2 = lexer.getObj(); + if (obj2 instanceof Name2) { + cMap.name = obj2.name; + } +} +async function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) { + let previous, embeddedUseCMap; + objLoop: while (true) { + try { + const obj2 = lexer.getObj(); + if (obj2 === EOF) { + break; + } else if (obj2 instanceof Name2) { + if (obj2.name === "WMode") { + parseWMode(cMap, lexer); + } else if (obj2.name === "CMapName") { + parseCMapName(cMap, lexer); + } + previous = obj2; + } else if (obj2 instanceof Cmd) { + switch (obj2.cmd) { + case "endcmap": + break objLoop; + case "usecmap": + if (previous instanceof Name2) { + embeddedUseCMap = previous.name; + } + break; + case "begincodespacerange": + parseCodespaceRange(cMap, lexer); + break; + case "beginbfchar": + parseBfChar(cMap, lexer); + break; + case "begincidchar": + parseCidChar(cMap, lexer); + break; + case "beginbfrange": + parseBfRange(cMap, lexer); + break; + case "begincidrange": + parseCidRange(cMap, lexer); + break; + } + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Invalid cMap data: " + ex); + continue; + } + } + if (!useCMap && embeddedUseCMap) { + useCMap = embeddedUseCMap; + } + if (useCMap) { + return extendCMap(cMap, fetchBuiltInCMap, useCMap); + } + return cMap; +} +async function extendCMap(cMap, fetchBuiltInCMap, useCMap) { + cMap.useCMap = await createBuiltInCMap(useCMap, fetchBuiltInCMap); + if (cMap.numCodespaceRanges === 0) { + const useCodespaceRanges = cMap.useCMap.codespaceRanges; + for (let i = 0; i < useCodespaceRanges.length; i++) { + cMap.codespaceRanges[i] = useCodespaceRanges[i].slice(); + } + cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges; + } + cMap.useCMap.forEach(function(key, value) { + if (!cMap.contains(key)) { + cMap.mapOne(key, value); + } + }); + return cMap; +} +async function createBuiltInCMap(name, fetchBuiltInCMap) { + if (name === "Identity-H") { + return new IdentityCMap(false, 2); + } else if (name === "Identity-V") { + return new IdentityCMap(true, 2); + } + if (!BUILT_IN_CMAPS.includes(name)) { + throw new Error("Unknown CMap name: " + name); + } + if (!fetchBuiltInCMap) { + throw new Error("Built-in CMap parameters are not provided."); + } + const { + cMapData, + isCompressed + } = await fetchBuiltInCMap(name); + const cMap = new CMap(true); + if (isCompressed) { + return new BinaryCMapReader().process(cMapData, cMap, (useCMap) => extendCMap(cMap, fetchBuiltInCMap, useCMap)); + } + const lexer = new Lexer(new Stream3(cMapData)); + return parseCMap(cMap, lexer, fetchBuiltInCMap, null); +} +function getEncoding(encodingName) { + switch (encodingName) { + case "WinAnsiEncoding": + return WinAnsiEncoding; + case "StandardEncoding": + return StandardEncoding; + case "MacRomanEncoding": + return MacRomanEncoding; + case "SymbolSetEncoding": + return SymbolSetEncoding; + case "ZapfDingbatsEncoding": + return ZapfDingbatsEncoding; + case "ExpertEncoding": + return ExpertEncoding; + case "MacExpertEncoding": + return MacExpertEncoding; + default: + return null; + } +} +function mapSpecialUnicodeValues(code) { + if (code >= 65520 && code <= 65535) { + return 0; + } else if (code >= 62976 && code <= 63743) { + return getSpecialPUASymbols()[code] || code; + } else if (code === 173) { + return 45; + } + return code; +} +function getUnicodeForGlyph(name, glyphsUnicodeMap) { + let unicode = glyphsUnicodeMap[name]; + if (unicode !== void 0) { + return unicode; + } + if (!name) { + return -1; + } + if (name[0] === "u") { + const nameLen = name.length; + let hexStr; + if (nameLen === 7 && name[1] === "n" && name[2] === "i") { + hexStr = name.substring(3); + } else if (nameLen >= 5 && nameLen <= 7) { + hexStr = name.substring(1); + } else { + return -1; + } + if (hexStr === hexStr.toUpperCase()) { + unicode = parseInt(hexStr, 16); + if (unicode >= 0) { + return unicode; + } + } + } + return -1; +} +function getUnicodeRangeFor(value, lastPosition = -1) { + if (lastPosition !== -1) { + const range2 = UnicodeRanges[lastPosition]; + for (let i = 0, ii = range2.length; i < ii; i += 2) { + if (value >= range2[i] && value <= range2[i + 1]) { + return lastPosition; + } + } + } + for (let i = 0, ii = UnicodeRanges.length; i < ii; i++) { + const range2 = UnicodeRanges[i]; + for (let j = 0, jj = range2.length; j < jj; j += 2) { + if (value >= range2[j] && value <= range2[j + 1]) { + return i; + } + } + } + return -1; +} +function getCharUnicodeCategory(char2) { + const cachedCategory = CategoryCache.get(char2); + if (cachedCategory) { + return cachedCategory; + } + const groups = char2.match(SpecialCharRegExp); + const category = { + isWhitespace: !!groups?.[1], + isZeroWidthDiacritic: !!groups?.[2], + isInvisibleFormatMark: !!groups?.[3] + }; + CategoryCache.set(char2, category); + return category; +} +function clearUnicodeCaches() { + CategoryCache.clear(); +} +function recoverGlyphName(name, glyphsUnicodeMap) { + if (glyphsUnicodeMap[name] !== void 0) { + return name; + } + const unicode = getUnicodeForGlyph(name, glyphsUnicodeMap); + if (unicode !== -1) { + for (const key in glyphsUnicodeMap) { + if (glyphsUnicodeMap[key] === unicode) { + return key; + } + } + } + info2("Unable to recover a standard glyph name for: " + name); + return name; +} +function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) { + const charCodeToGlyphId = /* @__PURE__ */ Object.create(null); + let glyphId, charCode, baseEncoding; + const isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + if (properties.isInternalFont) { + baseEncoding = builtInEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } else if (properties.baseEncodingName) { + baseEncoding = getEncoding(properties.baseEncodingName); + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } else if (isSymbolicFont) { + for (charCode in builtInEncoding) { + charCodeToGlyphId[charCode] = builtInEncoding[charCode]; + } + } else { + baseEncoding = StandardEncoding; + for (charCode = 0; charCode < baseEncoding.length; charCode++) { + glyphId = glyphNames.indexOf(baseEncoding[charCode]); + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } + const differences = properties.differences; + let glyphsUnicodeMap; + if (differences) { + for (charCode in differences) { + const glyphName = differences[charCode]; + glyphId = glyphNames.indexOf(glyphName); + if (glyphId === -1) { + if (!glyphsUnicodeMap) { + glyphsUnicodeMap = getGlyphsUnicode(); + } + const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + if (standardGlyphName !== glyphName) { + glyphId = glyphNames.indexOf(standardGlyphName); + } + } + charCodeToGlyphId[charCode] = glyphId >= 0 ? glyphId : 0; + } + } + return charCodeToGlyphId; +} +function normalizeFontName(name) { + return name.replaceAll(/[,_]/g, "-").replaceAll(/\s/g, ""); +} +function compileType3Glyph({ + data: img, + width, + height +}) { + if (width > MAX_SIZE_TO_COMPILE || height > MAX_SIZE_TO_COMPILE) { + return null; + } + const POINT_TO_PROCESS_LIMIT = 1e3; + const POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]); + const width1 = width + 1; + const points = new Uint8Array(width1 * (height + 1)); + let i, j, j0; + const lineSize = width + 7 & ~7; + const data = new Uint8Array(lineSize * height); + let pos = 0; + for (const elem of img) { + let mask = 128; + while (mask > 0) { + data[pos++] = elem & mask ? 0 : 255; + mask >>= 1; + } + } + let count = 0; + pos = 0; + if (data[pos] !== 0) { + points[0] = 1; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j] = data[pos] ? 2 : 1; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j] = 2; + ++count; + } + for (i = 1; i < height; i++) { + pos = i * lineSize; + j0 = i * width1; + if (data[pos - lineSize] !== data[pos]) { + points[j0] = data[pos] ? 1 : 8; + ++count; + } + let sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0); + for (j = 1; j < width; j++) { + sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0); + if (POINT_TYPES[sum]) { + points[j0 + j] = POINT_TYPES[sum]; + ++count; + } + pos++; + } + if (data[pos - lineSize] !== data[pos]) { + points[j0 + j] = data[pos] ? 2 : 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + } + pos = lineSize * (height - 1); + j0 = i * width1; + if (data[pos] !== 0) { + points[j0] = 8; + ++count; + } + for (j = 1; j < width; j++) { + if (data[pos] !== data[pos + 1]) { + points[j0 + j] = data[pos] ? 4 : 8; + ++count; + } + pos++; + } + if (data[pos] !== 0) { + points[j0 + j] = 4; + ++count; + } + if (count > POINT_TO_PROCESS_LIMIT) { + return null; + } + const steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]); + const pathBuf = []; + const { + a, + b: b2, + c, + d, + e, + f + } = new DOMMatrix().scaleSelf(1 / width, -1 / height).translateSelf(0, -height); + for (i = 0; count && i <= height; i++) { + let p = i * width1; + const end = p + width; + while (p < end && !points[p]) { + p++; + } + if (p === end) { + continue; + } + let x = p % width1; + let y = i; + pathBuf.push(DrawOPS3.moveTo, a * x + c * y + e, b2 * x + d * y + f); + const p0 = p; + let type = points[p]; + do { + const step = steps[type]; + do { + p += step; + } while (!points[p]); + const pp = points[p]; + if (pp !== 5 && pp !== 10) { + type = pp; + points[p] = 0; + } else { + type = pp & 51 * type >> 4; + points[p] &= type >> 2 | type << 2; + } + x = p % width1; + y = p / width1 | 0; + pathBuf.push(DrawOPS3.lineTo, a * x + c * y + e, b2 * x + d * y + f); + if (!points[p]) { + --count; + } + } while (p0 !== p); + --i; + } + return [OPS2.rawFillPath, [new Float32Array(pathBuf)], new Float32Array([0, 0, width, height])]; +} +function getStandardFontName(name) { + const fontName = normalizeFontName(name); + const stdFontMap = getStdFontMap(); + return stdFontMap[fontName]; +} +function isKnownFontName(name) { + const fontName = normalizeFontName(name); + return !!(getStdFontMap()[fontName] || getNonStdFontMap()[fontName] || getSerifFonts()[fontName] || getSymbolsFonts()[fontName]); +} +function getFloat214(data, offset) { + return readInt16(data, offset) / 16384; +} +function getSubroutineBias(subrs) { + const numSubrs = subrs.length; + let bias = 32768; + if (numSubrs < 1240) { + bias = 107; + } else if (numSubrs < 33900) { + bias = 1131; + } + return bias; +} +function parseCmap(data, start, end) { + const offset = readUint16(data, start + 2) === 1 ? readUint32(data, start + 8) : readUint32(data, start + 16); + const format = readUint16(data, start + offset); + let ranges, p, i; + if (format === 4) { + readUint16(data, start + offset + 2); + const segCount = readUint16(data, start + offset + 6) >> 1; + p = start + offset + 14; + ranges = []; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i] = { + end: readUint16(data, p) + }; + } + p += 2; + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].start = readUint16(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + ranges[i].idDelta = readUint16(data, p); + } + for (i = 0; i < segCount; i++, p += 2) { + let idOffset = readUint16(data, p); + if (idOffset === 0) { + continue; + } + ranges[i].ids = []; + for (let j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) { + ranges[i].ids[j] = readUint16(data, p + idOffset); + idOffset += 2; + } + } + return ranges; + } else if (format === 12) { + const groups = readUint32(data, start + offset + 12); + p = start + offset + 16; + ranges = []; + for (i = 0; i < groups; i++) { + start = readUint32(data, p); + ranges.push({ + start, + end: readUint32(data, p + 4), + idDelta: readUint32(data, p + 8) - start + }); + p += 12; + } + return ranges; + } + throw new FormatError3(`unsupported cmap: ${format}`); +} +function parseCff(data, start, end, seacAnalysisEnabled) { + const properties = {}; + const parser = new CFFParser(new Stream3(data, start, end - start), properties, seacAnalysisEnabled); + const cff = parser.parse(); + return { + glyphs: cff.charStrings.objects, + subrs: cff.topDict.privateDict?.subrsIndex?.objects, + gsubrs: cff.globalSubrIndex?.objects, + isCFFCIDFont: cff.isCIDFont, + fdSelect: cff.fdSelect, + fdArray: cff.fdArray + }; +} +function parseGlyfTable(glyf, loca, isGlyphLocationsLong) { + let itemSize, itemDecode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = readUint32; + } else { + itemSize = 2; + itemDecode = (data, offset) => 2 * readUint16(data, offset); + } + const glyphs = []; + let startOffset = itemDecode(loca, 0); + for (let j = itemSize; j < loca.length; j += itemSize) { + const endOffset = itemDecode(loca, j); + glyphs.push(glyf.subarray(startOffset, endOffset)); + startOffset = endOffset; + } + return glyphs; +} +function lookupCmap(ranges, unicode) { + const code = unicode.codePointAt(0); + let gid = 0, l2 = 0, r = ranges.length - 1; + while (l2 < r) { + const c = l2 + r + 1 >> 1; + if (code < ranges[c].start) { + r = c - 1; + } else { + l2 = c; + } + } + if (ranges[l2].start <= code && code <= ranges[l2].end) { + gid = ranges[l2].idDelta + (ranges[l2].ids ? ranges[l2].ids[code - ranges[l2].start] : code) & 65535; + } + return { + charCode: code, + glyphId: gid + }; +} +function compileGlyf(code, cmds, font) { + function moveTo(x2, y2) { + if (firstPoint) { + cmds.add("L", firstPoint); + } + firstPoint = [x2, y2]; + cmds.add("M", [x2, y2]); + } + function lineTo(x2, y2) { + cmds.add("L", [x2, y2]); + } + function quadraticCurveTo(xa, ya, x2, y2) { + cmds.add("Q", [xa, ya, x2, y2]); + } + let i = 0; + const numberOfContours = readInt16(code, i); + let flags; + let firstPoint = null; + let x = 0, y = 0; + i += 10; + if (numberOfContours < 0) { + do { + flags = readUint16(code, i); + const glyphIndex = readUint16(code, i + 2); + i += 4; + let arg1, arg2; + if (flags & 1) { + if (flags & 2) { + arg1 = readInt16(code, i); + arg2 = readInt16(code, i + 2); + } else { + arg1 = readUint16(code, i); + arg2 = readUint16(code, i + 2); + } + i += 4; + } else if (flags & 2) { + arg1 = readInt8(code, i++); + arg2 = readInt8(code, i++); + } else { + arg1 = code[i++]; + arg2 = code[i++]; + } + if (flags & 2) { + x = arg1; + y = arg2; + } else { + x = 0; + y = 0; + } + let scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0; + if (flags & 8) { + scaleX = scaleY = getFloat214(code, i); + i += 2; + } else if (flags & 64) { + scaleX = getFloat214(code, i); + scaleY = getFloat214(code, i + 2); + i += 4; + } else if (flags & 128) { + scaleX = getFloat214(code, i); + scale01 = getFloat214(code, i + 2); + scale10 = getFloat214(code, i + 4); + scaleY = getFloat214(code, i + 6); + i += 8; + } + const subglyph = font.glyphs[glyphIndex]; + if (subglyph) { + cmds.save(); + cmds.transform([scaleX, scale01, scale10, scaleY, x, y]); + if (!(flags & 2)) { + } + compileGlyf(subglyph, cmds, font); + cmds.restore(); + } + } while (flags & 32); + } else { + const endPtsOfContours = []; + let j, jj; + for (j = 0; j < numberOfContours; j++) { + endPtsOfContours.push(readUint16(code, i)); + i += 2; + } + const instructionLength = readUint16(code, i); + i += 2 + instructionLength; + const numberOfPoints = endPtsOfContours.at(-1) + 1; + const points = []; + while (points.length < numberOfPoints) { + flags = code[i++]; + let repeat = 1; + if (flags & 8) { + repeat += code[i++]; + } + while (repeat-- > 0) { + points.push({ + flags + }); + } + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 18) { + case 0: + x += readInt16(code, i); + i += 2; + break; + case 2: + x -= code[i++]; + break; + case 18: + x += code[i++]; + break; + } + points[j].x = x; + } + for (j = 0; j < numberOfPoints; j++) { + switch (points[j].flags & 36) { + case 0: + y += readInt16(code, i); + i += 2; + break; + case 4: + y -= code[i++]; + break; + case 36: + y += code[i++]; + break; + } + points[j].y = y; + } + let startPoint = 0; + for (i = 0; i < numberOfContours; i++) { + const endPoint = endPtsOfContours[i]; + const contour = points.slice(startPoint, endPoint + 1); + if (contour[0].flags & 1) { + contour.push(contour[0]); + } else if (contour.at(-1).flags & 1) { + contour.unshift(contour.at(-1)); + } else { + const p = { + flags: 1, + x: (contour[0].x + contour.at(-1).x) / 2, + y: (contour[0].y + contour.at(-1).y) / 2 + }; + contour.unshift(p); + contour.push(p); + } + moveTo(contour[0].x, contour[0].y); + for (j = 1, jj = contour.length; j < jj; j++) { + if (contour[j].flags & 1) { + lineTo(contour[j].x, contour[j].y); + } else if (contour[j + 1].flags & 1) { + quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y); + j++; + } else { + quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2); + } + } + startPoint = endPoint + 1; + } + } +} +function compileCharString(charStringCode, cmds, font, glyphId) { + function moveTo(x2, y2) { + if (firstPoint) { + cmds.add("L", firstPoint); + } + firstPoint = [x2, y2]; + cmds.add("M", [x2, y2]); + } + function lineTo(x2, y2) { + cmds.add("L", [x2, y2]); + } + function bezierCurveTo(x1, y1, x2, y2, x3, y3) { + cmds.add("C", [x1, y1, x2, y2, x3, y3]); + } + const stack = []; + let x = 0, y = 0; + let stems = 0; + let firstPoint = null; + function parse4(code) { + let i = 0; + while (i < code.length) { + let stackClean = false; + let v = code[i++]; + let xa, xb, ya, yb, y1, y2, y3, n, subrCode; + switch (v) { + case 1: + stems += stack.length >> 1; + stackClean = true; + break; + case 3: + stems += stack.length >> 1; + stackClean = true; + break; + case 4: + y += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 5: + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + break; + case 6: + while (stack.length > 0) { + x += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + y += stack.shift(); + lineTo(x, y); + } + break; + case 7: + while (stack.length > 0) { + y += stack.shift(); + lineTo(x, y); + if (stack.length === 0) { + break; + } + x += stack.shift(); + lineTo(x, y); + } + break; + case 8: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 10: + n = stack.pop(); + subrCode = null; + if (font.isCFFCIDFont) { + const fdIndex = font.fdSelect.getFDIndex(glyphId); + if (fdIndex >= 0 && fdIndex < font.fdArray.length) { + const fontDict = font.fdArray[fdIndex]; + let subrs; + if (fontDict.privateDict?.subrsIndex) { + subrs = fontDict.privateDict.subrsIndex.objects; + } + if (subrs) { + n += getSubroutineBias(subrs); + subrCode = subrs[n]; + } + } else { + warn2("Invalid fd index for glyph index."); + } + } else { + subrCode = font.subrs[n + font.subrsBias]; + } + if (subrCode) { + parse4(subrCode); + } + break; + case 11: + return; + case 12: + v = code[i++]; + switch (v) { + case 34: + xa = x + stack.shift(); + xb = xa + stack.shift(); + y1 = y + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y, xb, y1, x, y1); + xa = x + stack.shift(); + xb = xa + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y, x, y); + break; + case 35: + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + stack.pop(); + break; + case 36: + xa = x + stack.shift(); + y1 = y + stack.shift(); + xb = xa + stack.shift(); + y2 = y1 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y1, xb, y2, x, y2); + xa = x + stack.shift(); + xb = xa + stack.shift(); + y3 = y2 + stack.shift(); + x = xb + stack.shift(); + bezierCurveTo(xa, y2, xb, y3, x, y); + break; + case 37: + const x0 = x, y0 = y; + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb; + if (Math.abs(x - x0) > Math.abs(y - y0)) { + x += stack.shift(); + } else { + y += stack.shift(); + } + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + default: + throw new FormatError3(`unknown operator: 12 ${v}`); + } + break; + case 14: + if (stack.length >= 4) { + const achar = stack.pop(); + const bchar = stack.pop(); + y = stack.pop(); + x = stack.pop(); + cmds.save(); + cmds.translate(x, y); + let cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); + cmds.restore(); + cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])); + compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId); + } + return; + case 18: + stems += stack.length >> 1; + stackClean = true; + break; + case 19: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 20: + stems += stack.length >> 1; + i += stems + 7 >> 3; + stackClean = true; + break; + case 21: + y += stack.pop(); + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 22: + x += stack.pop(); + moveTo(x, y); + stackClean = true; + break; + case 23: + stems += stack.length >> 1; + stackClean = true; + break; + case 24: + while (stack.length > 2) { + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + break; + case 25: + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + lineTo(x, y); + } + xa = x + stack.shift(); + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + break; + case 26: + if (stack.length % 2) { + x += stack.shift(); + } + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb; + y = yb + stack.shift(); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 27: + if (stack.length % 2) { + y += stack.shift(); + } + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb; + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 28: + stack.push(readInt16(code, i)); + i += 2; + break; + case 29: + n = stack.pop() + font.gsubrsBias; + subrCode = font.gsubrs[n]; + if (subrCode) { + parse4(subrCode); + } + break; + case 30: + while (stack.length > 0) { + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + case 31: + while (stack.length > 0) { + xa = x + stack.shift(); + ya = y; + xb = xa + stack.shift(); + yb = ya + stack.shift(); + y = yb + stack.shift(); + x = xb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + if (stack.length === 0) { + break; + } + xa = x; + ya = y + stack.shift(); + xb = xa + stack.shift(); + yb = ya + stack.shift(); + x = xb + stack.shift(); + y = yb + (stack.length === 1 ? stack.shift() : 0); + bezierCurveTo(xa, ya, xb, yb, x, y); + } + break; + default: + if (v < 32) { + throw new FormatError3(`unknown operator: ${v}`); + } + if (v < 247) { + stack.push(v - 139); + } else if (v < 251) { + stack.push((v - 247) * 256 + code[i++] + 108); + } else if (v < 255) { + stack.push(-(v - 251) * 256 - code[i++] - 108); + } else { + stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536); + i += 4; + } + break; + } + if (stackClean) { + stack.length = 0; + } + } + } + parse4(charStringCode); +} +function writeInt16(dest, offset, num) { + dest[offset] = num >> 8 & 255; + dest[offset + 1] = num & 255; +} +function writeInt32(dest, offset, num) { + dest[offset] = num >> 24 & 255; + dest[offset + 1] = num >> 16 & 255; + dest[offset + 2] = num >> 8 & 255; + dest[offset + 3] = num & 255; +} +function writeData(dest, offset, data) { + if (data instanceof Uint8Array) { + dest.set(data, offset); + } else if (typeof data === "string") { + for (let i = 0, ii = data.length; i < ii; i++) { + dest[offset++] = data.charCodeAt(i) & 255; + } + } else { + for (const num of data) { + dest[offset++] = num & 255; + } + } +} +function isHexDigit(code) { + return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102; +} +function decrypt(data, key, discardNumber) { + if (discardNumber >= data.length) { + return new Uint8Array(0); + } + const c1 = 52845, c2 = 22719; + let r = key | 0, i, j; + for (i = 0; i < discardNumber; i++) { + r = (data[i] + r) * c1 + c2 & (1 << 16) - 1; + } + const count = data.length - discardNumber; + const decrypted = new Uint8Array(count); + for (i = discardNumber, j = 0; j < count; i++, j++) { + const value = data[i]; + decrypted[j] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + return decrypted; +} +function decryptAscii(data, key, discardNumber) { + const c1 = 52845, c2 = 22719; + let r = key | 0; + const count = data.length, maybeLength = count >>> 1; + const decrypted = new Uint8Array(maybeLength); + let i, j; + for (i = 0, j = 0; i < count; i++) { + const digit1 = data[i]; + if (!isHexDigit(digit1)) { + continue; + } + i++; + let digit2; + while (i < count && !isHexDigit(digit2 = data[i])) { + i++; + } + if (i < count) { + const value = parseInt(String.fromCharCode(digit1, digit2), 16); + decrypted[j++] = value ^ r >> 8; + r = (value + r) * c1 + c2 & (1 << 16) - 1; + } + } + return decrypted.slice(discardNumber, j); +} +function isSpecial(c) { + return c === 47 || c === 91 || c === 93 || c === 123 || c === 125 || c === 40 || c === 41; +} +function findBlock(streamBytes, signature, startIndex) { + const streamBytesLength = streamBytes.length; + const signatureLength = signature.length; + const scanLength = streamBytesLength - signatureLength; + let i = startIndex, found = false; + while (i < scanLength) { + let j = 0; + while (j < signatureLength && streamBytes[i + j] === signature[j]) { + j++; + } + if (j >= signatureLength) { + i += j; + while (i < streamBytesLength && isWhiteSpace(streamBytes[i])) { + i++; + } + found = true; + break; + } + i++; + } + return { + found, + length: i + }; +} +function getHeaderBlock(stream, suggestedLength) { + const EEXEC_SIGNATURE = [101, 101, 120, 101, 99]; + const streamStartPos = stream.pos; + let headerBytes, headerBytesLength, block; + try { + headerBytes = stream.getBytes(suggestedLength); + headerBytesLength = headerBytes.length; + } catch { + } + if (headerBytesLength === suggestedLength) { + block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length); + if (block.found && block.length === suggestedLength) { + return { + stream: new Stream3(headerBytes), + length: suggestedLength + }; + } + } + warn2('Invalid "Length1" property in Type1 font -- trying to recover.'); + stream.pos = streamStartPos; + const SCAN_BLOCK_LENGTH = 2048; + let actualLength; + while (true) { + const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); + block = findBlock(scanBytes, EEXEC_SIGNATURE, 0); + if (block.length === 0) { + break; + } + stream.pos += block.length; + if (block.found) { + actualLength = stream.pos - streamStartPos; + break; + } + } + stream.pos = streamStartPos; + if (actualLength) { + return { + stream: new Stream3(stream.getBytes(actualLength)), + length: actualLength + }; + } + warn2('Unable to recover "Length1" property in Type1 font -- using as is.'); + return { + stream: new Stream3(stream.getBytes(suggestedLength)), + length: suggestedLength + }; +} +function getEexecBlock(stream, suggestedLength) { + const eexecBytes = stream.getBytes(); + if (eexecBytes.length === 0) { + throw new FormatError3("getEexecBlock - no font program found."); + } + return { + stream: new Stream3(eexecBytes), + length: eexecBytes.length + }; +} +function adjustWidths(properties) { + if (!properties.fontMatrix) { + return; + } + if (properties.fontMatrix[0] === FONT_IDENTITY_MATRIX2[0]) { + return; + } + const scale = 1e-3 / properties.fontMatrix[0]; + const glyphsWidths = properties.widths; + for (const glyph in glyphsWidths) { + glyphsWidths[glyph] *= scale; + } + properties.defaultWidth *= scale; +} +function adjustTrueTypeToUnicode(properties, isSymbolicFont, nameRecords) { + if (properties.isInternalFont) { + return; + } + if (properties.hasIncludedToUnicodeMap) { + return; + } + if (properties.hasEncoding) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + if (!isSymbolicFont) { + return; + } + if (nameRecords.length === 0) { + return; + } + if (properties.defaultEncoding === WinAnsiEncoding) { + return; + } + for (const r of nameRecords) { + if (!isWinNameRecord(r)) { + return; + } + } + const encoding = WinAnsiEncoding; + const toUnicode = [], glyphsUnicodeMap = getGlyphsUnicode(); + for (const charCode in encoding) { + const glyphName = encoding[charCode]; + if (glyphName === "") { + continue; + } + const unicode = glyphsUnicodeMap[glyphName]; + if (unicode === void 0) { + continue; + } + toUnicode[charCode] = String.fromCharCode(unicode); + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +function adjustType1ToUnicode(properties, builtInEncoding) { + if (properties.isInternalFont) { + return; + } + if (properties.hasIncludedToUnicodeMap) { + return; + } + if (builtInEncoding === properties.defaultEncoding) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + const toUnicode = [], glyphsUnicodeMap = getGlyphsUnicode(); + for (const charCode in builtInEncoding) { + if (properties.hasEncoding) { + if (properties.baseEncodingName || properties.differences[charCode] !== void 0) { + continue; + } + } + const glyphName = builtInEncoding[charCode]; + const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + toUnicode[charCode] = String.fromCharCode(unicode); + } + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +function amendFallbackToUnicode(properties) { + if (!properties.fallbackToUnicode) { + return; + } + if (properties.toUnicode instanceof IdentityToUnicodeMap) { + return; + } + const toUnicode = []; + for (const charCode in properties.fallbackToUnicode) { + if (properties.toUnicode.has(charCode)) { + continue; + } + toUnicode[charCode] = properties.fallbackToUnicode[charCode]; + } + if (toUnicode.length > 0) { + properties.toUnicode.amend(toUnicode); + } +} +function int16(b0, b1) { + return (b0 << 8) + b1; +} +function writeSignedInt16(bytes, index2, value) { + bytes[index2 + 1] = value; + bytes[index2] = value >>> 8; +} +function signedInt16(b0, b1) { + const value = (b0 << 8) + b1; + return value & 1 << 15 ? value - 65536 : value; +} +function writeUint32(bytes, index2, value) { + bytes[index2 + 3] = value & 255; + bytes[index2 + 2] = value >>> 8; + bytes[index2 + 1] = value >>> 16; + bytes[index2] = value >>> 24; +} +function int322(b0, b1, b2, b3) { + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; +} +function string16(value) { + return String.fromCharCode(value >> 8 & 255, value & 255); +} +function safeString16(value) { + if (value > 32767) { + value = 32767; + } else if (value < -32768) { + value = -32768; + } + return String.fromCharCode(value >> 8 & 255, value & 255); +} +function isTrueTypeFile(file2) { + const header = file2.peekBytes(4); + return readUint32(header, 0) === 65536 || bytesToString2(header) === "true"; +} +function isTrueTypeCollectionFile(file2) { + const header = file2.peekBytes(4); + return bytesToString2(header) === "ttcf"; +} +function isOpenTypeFile(file2) { + const header = file2.peekBytes(4); + return bytesToString2(header) === "OTTO"; +} +function isType1File(file2) { + const header = file2.peekBytes(2); + if (header[0] === 37 && header[1] === 33) { + return true; + } + if (header[0] === 128 && header[1] === 1) { + return true; + } + return false; +} +function isCFFFile(file2) { + const header = file2.peekBytes(4); + if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) { + return true; + } + return false; +} +function getFontFileType(file2, { + type, + subtype, + composite +}) { + let fileType, fileSubtype; + if (isTrueTypeFile(file2) || isTrueTypeCollectionFile(file2)) { + fileType = composite ? "CIDFontType2" : "TrueType"; + } else if (isOpenTypeFile(file2)) { + fileType = composite ? "CIDFontType2" : "OpenType"; + } else if (isType1File(file2)) { + if (composite) { + fileType = "CIDFontType0"; + } else { + fileType = type === "MMType1" ? "MMType1" : "Type1"; + } + } else if (isCFFFile(file2)) { + if (composite) { + fileType = "CIDFontType0"; + fileSubtype = "CIDFontType0C"; + } else { + fileType = type === "MMType1" ? "MMType1" : "Type1"; + fileSubtype = "Type1C"; + } + } else { + warn2("getFontFileType: Unable to detect correct font file Type/Subtype."); + fileType = type; + fileSubtype = subtype; + } + return [fileType, fileSubtype]; +} +function applyStandardFontGlyphMap(map3, glyphMap) { + for (const charCode in glyphMap) { + map3[+charCode] = glyphMap[charCode]; + } +} +function buildToFontChar(encoding, glyphsUnicodeMap, differences) { + const toFontChar = []; + let unicode; + for (let i = 0, ii = encoding.length; i < ii; i++) { + unicode = getUnicodeForGlyph(encoding[i], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[i] = unicode; + } + } + for (const charCode in differences) { + unicode = getUnicodeForGlyph(differences[charCode], glyphsUnicodeMap); + if (unicode !== -1) { + toFontChar[+charCode] = unicode; + } + } + return toFontChar; +} +function isMacNameRecord(r) { + return r.platform === 1 && r.encoding === 0 && r.language === 0; +} +function isWinNameRecord(r) { + return r.platform === 3 && r.encoding === 1 && r.language === 1033; +} +function convertCidString(charCode, cid, shouldThrow = false) { + switch (cid.length) { + case 1: + return cid.charCodeAt(0); + case 2: + return cid.charCodeAt(0) << 8 | cid.charCodeAt(1); + } + const msg = `Unsupported CID string (charCode ${charCode}): "${cid}".`; + if (shouldThrow) { + throw new FormatError3(msg); + } + warn2(msg); + return cid; +} +function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId, toUnicode) { + const newMap = /* @__PURE__ */ Object.create(null); + const toUnicodeExtraMap = /* @__PURE__ */ new Map(); + const toFontChar = []; + const usedGlyphIds = /* @__PURE__ */ new Set(); + let privateUseAreaIndex = 0; + const privateUseOffetStart = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; + let nextAvailableFontCharCode = privateUseOffetStart; + let privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; + const isInPrivateArea = (code) => PRIVATE_USE_AREAS[0][0] <= code && code <= PRIVATE_USE_AREAS[0][1] || PRIVATE_USE_AREAS[1][0] <= code && code <= PRIVATE_USE_AREAS[1][1]; + let LIGATURE_TO_UNICODE = null; + for (const originalCharCode in charCodeToGlyphId) { + let glyphId = charCodeToGlyphId[originalCharCode]; + if (!hasGlyph(glyphId)) { + continue; + } + if (nextAvailableFontCharCode > privateUseOffetEnd) { + privateUseAreaIndex++; + if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) { + warn2("Ran out of space in font private use area."); + break; + } + nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0]; + privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1]; + } + const fontCharCode = nextAvailableFontCharCode++; + if (glyphId === 0) { + glyphId = newGlyphZeroId; + } + let unicode = toUnicode.get(originalCharCode); + if (typeof unicode === "string") { + if (unicode.length === 1) { + unicode = unicode.codePointAt(0); + } else { + if (!LIGATURE_TO_UNICODE) { + LIGATURE_TO_UNICODE = /* @__PURE__ */ new Map(); + for (let i = 64256; i <= 64335; i++) { + const normalized = String.fromCharCode(i).normalize("NFKD"); + if (normalized.length > 1) { + LIGATURE_TO_UNICODE.set(normalized, i); + } + } + } + unicode = LIGATURE_TO_UNICODE.get(unicode) || unicode.codePointAt(0); + } + } + if (unicode && !isInPrivateArea(unicode) && !usedGlyphIds.has(glyphId)) { + toUnicodeExtraMap.set(unicode, glyphId); + usedGlyphIds.add(glyphId); + } + newMap[fontCharCode] = glyphId; + toFontChar[originalCharCode] = fontCharCode; + } + return { + toFontChar, + charCodeToGlyphId: newMap, + toUnicodeExtraMap, + nextAvailableFontCharCode + }; +} +function getRanges(glyphs, toUnicodeExtraMap, numGlyphs) { + const codes = []; + for (const charCode in glyphs) { + if (glyphs[charCode] >= numGlyphs) { + continue; + } + codes.push({ + fontCharCode: charCode | 0, + glyphId: glyphs[charCode] + }); + } + if (toUnicodeExtraMap) { + for (const [unicode, glyphId] of toUnicodeExtraMap) { + if (glyphId >= numGlyphs) { + continue; + } + codes.push({ + fontCharCode: unicode, + glyphId + }); + } + } + if (codes.length === 0) { + codes.push({ + fontCharCode: 0, + glyphId: 0 + }); + } + codes.sort((a, b2) => a.fontCharCode - b2.fontCharCode); + const ranges = []; + const length = codes.length; + for (let n = 0; n < length; ) { + const start = codes[n].fontCharCode; + const codeIndices = [codes[n].glyphId]; + ++n; + let end = start; + while (n < length && end + 1 === codes[n].fontCharCode) { + codeIndices.push(codes[n].glyphId); + ++end; + ++n; + if (end === 65535) { + break; + } + } + ranges.push([start, end, codeIndices]); + } + return ranges; +} +function createCmapTable(glyphs, toUnicodeExtraMap, numGlyphs) { + const ranges = getRanges(glyphs, toUnicodeExtraMap, numGlyphs); + const numTables = ranges.at(-1)[1] > 65535 ? 2 : 1; + let cmap = "\0\0" + string16(numTables) + "\0\0" + string322(4 + numTables * 8); + let i, ii, j, jj; + for (i = ranges.length - 1; i >= 0; --i) { + if (ranges[i][0] <= 65535) { + break; + } + } + const bmpLength = i + 1; + if (ranges[i][0] < 65535 && ranges[i][1] === 65535) { + ranges[i][1] = 65534; + } + const trailingRangesCount = ranges[i][1] < 65535 ? 1 : 0; + const segCount = bmpLength + trailingRangesCount; + const searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2); + let startCount = ""; + let endCount = ""; + let idDeltas = ""; + let idRangeOffsets = ""; + let glyphsIds = ""; + let bias = 0; + let range2, start, end, codes; + for (i = 0, ii = bmpLength; i < ii; i++) { + range2 = ranges[i]; + start = range2[0]; + end = range2[1]; + startCount += string16(start); + endCount += string16(end); + codes = range2[2]; + let contiguous = true; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + contiguous = false; + break; + } + } + if (!contiguous) { + const offset = (segCount - i) * 2 + bias * 2; + bias += end - start + 1; + idDeltas += string16(0); + idRangeOffsets += string16(offset); + for (j = 0, jj = codes.length; j < jj; ++j) { + glyphsIds += string16(codes[j]); + } + } else { + const startCode = codes[0]; + idDeltas += string16(startCode - start & 65535); + idRangeOffsets += string16(0); + } + } + if (trailingRangesCount > 0) { + endCount += "\xFF\xFF"; + startCount += "\xFF\xFF"; + idDeltas += "\0"; + idRangeOffsets += "\0\0"; + } + const format314 = "\0\0" + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + "\0\0" + startCount + idDeltas + idRangeOffsets + glyphsIds; + let format31012 = ""; + let header31012 = ""; + if (numTables > 1) { + cmap += "\0\0\n" + string322(4 + numTables * 8 + 4 + format314.length); + format31012 = ""; + for (i = 0, ii = ranges.length; i < ii; i++) { + range2 = ranges[i]; + start = range2[0]; + codes = range2[2]; + let code = codes[0]; + for (j = 1, jj = codes.length; j < jj; ++j) { + if (codes[j] !== codes[j - 1] + 1) { + end = range2[0] + j - 1; + format31012 += string322(start) + string322(end) + string322(code); + start = end + 1; + code = codes[j]; + } + } + format31012 += string322(start) + string322(range2[1]) + string322(code); + } + header31012 = "\0\f\0\0" + string322(format31012.length + 16) + "\0\0\0\0" + string322(format31012.length / 12); + } + return cmap + "\0" + string16(format314.length + 4) + format314 + header31012 + format31012; +} +function validateOS2Table(os2, file2) { + file2.pos = (file2.start || 0) + os2.offset; + const version4 = file2.getUint16(); + file2.skip(60); + const selection = file2.getUint16(); + if (version4 < 4 && selection & 768) { + return false; + } + const firstChar = file2.getUint16(); + const lastChar = file2.getUint16(); + if (firstChar > lastChar) { + return false; + } + file2.skip(6); + const usWinAscent = file2.getUint16(); + if (usWinAscent === 0) { + return false; + } + os2.data[8] = os2.data[9] = 0; + return true; +} +function createOS2Table(properties, charstrings, override) { + override ||= { + unitsPerEm: 0, + yMax: 0, + yMin: 0, + ascent: 0, + descent: 0 + }; + let ulUnicodeRange1 = 0; + let ulUnicodeRange2 = 0; + let ulUnicodeRange3 = 0; + let ulUnicodeRange4 = 0; + let firstCharIndex = null; + let lastCharIndex = 0; + let position = -1; + if (charstrings) { + for (let code in charstrings) { + code |= 0; + if (firstCharIndex > code || !firstCharIndex) { + firstCharIndex = code; + } + if (lastCharIndex < code) { + lastCharIndex = code; + } + position = getUnicodeRangeFor(code, position); + if (position < 32) { + ulUnicodeRange1 |= 1 << position; + } else if (position < 64) { + ulUnicodeRange2 |= 1 << position - 32; + } else if (position < 96) { + ulUnicodeRange3 |= 1 << position - 64; + } else if (position < 123) { + ulUnicodeRange4 |= 1 << position - 96; + } else { + throw new FormatError3("Unicode ranges Bits > 123 are reserved for internal usage"); + } + } + if (lastCharIndex > 65535) { + lastCharIndex = 65535; + } + } else { + firstCharIndex = 0; + lastCharIndex = 255; + } + const bbox = properties.bbox || [0, 0, 0, 0]; + const unitsPerEm = override.unitsPerEm || (properties.fontMatrix ? 1 / Math.max(...properties.fontMatrix.slice(0, 4).map(Math.abs)) : 1e3); + const scale = properties.ascentScaled ? 1 : unitsPerEm / PDF_GLYPH_SPACE_UNITS; + const typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3])); + let typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1])); + if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) { + typoDescent = -typoDescent; + } + const winAscent = override.yMax || typoAscent; + const winDescent = -override.yMin || -typoDescent; + return "\0$\xF4\0\0\0\x8A\xBB\0\0\0\x8C\x8A\xBB\0\0\xDF\x001\0\0\0\0" + String.fromCharCode(properties.fixedPitch ? 9 : 0) + "\0\0\0\0\0\0" + string322(ulUnicodeRange1) + string322(ulUnicodeRange2) + string322(ulUnicodeRange3) + string322(ulUnicodeRange4) + "*21*" + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + "\0d" + string16(winAscent) + string16(winDescent) + "\0\0\0\0\0\0\0\0" + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + "\0"; +} +function createPostTable(properties) { + const angle = Math.floor(properties.italicAngle * 2 ** 16); + return "\0\0\0" + string322(angle) + "\0\0\0\0" + string322(properties.fixedPitch ? 1 : 0) + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +} +function createPostscriptName(name) { + return name.replaceAll(/[^\x21-\x7E]|[[\](){}<>/%]/g, "").slice(0, 63); +} +function createNameTable(name, proto) { + if (!proto) { + proto = [[], []]; + } + const strings = [proto[0][0] || "Original licence", proto[0][1] || name, proto[0][2] || "Unknown", proto[0][3] || "uniqueID", proto[0][4] || name, proto[0][5] || "Version 0.11", proto[0][6] || createPostscriptName(name), proto[0][7] || "Unknown", proto[0][8] || "Unknown", proto[0][9] || "Unknown"]; + const stringsUnicode = []; + let i, ii, j, jj, str; + for (i = 0, ii = strings.length; i < ii; i++) { + str = proto[1][i] || strings[i]; + const strBufUnicode = []; + for (j = 0, jj = str.length; j < jj; j++) { + strBufUnicode.push(string16(str.charCodeAt(j))); + } + stringsUnicode.push(strBufUnicode.join("")); + } + const names = [strings, stringsUnicode]; + const platforms = ["\0", "\0"]; + const encodings = ["\0\0", "\0"]; + const languages = ["\0\0", " "]; + const namesRecordCount = strings.length * platforms.length; + let nameTable = "\0\0" + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6); + let strOffset = 0; + for (i = 0, ii = platforms.length; i < ii; i++) { + const strs = names[i]; + for (j = 0, jj = strs.length; j < jj; j++) { + str = strs[j]; + const nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset); + nameTable += nameRecord; + strOffset += str.length; + } + } + nameTable += strings.join("") + stringsUnicode.join(""); + return nameTable; +} +function buildB(count) { + const lut = []; + for (let i = 0; i <= count; i++) { + const t = i / count, t_ = 1 - t; + lut.push(new Float32Array([t_ ** 3, 3 * t * t_ ** 2, 3 * t ** 2 * t_, t ** 3])); + } + return lut; +} +function getB(count) { + return bCache[count] ||= buildB(count); +} +function clearPatternCaches() { + bCache = /* @__PURE__ */ Object.create(null); +} +function getTilingPatternIR(operatorList, dict, color) { + const matrix = lookupMatrix(dict.getArray("Matrix"), IDENTITY_MATRIX); + const bbox = lookupNormalRect(dict.getArray("BBox"), null); + if (!bbox || bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) { + throw new FormatError3(`Invalid getTilingPatternIR /BBox array.`); + } + const xstep = dict.get("XStep"); + if (typeof xstep !== "number") { + throw new FormatError3(`Invalid getTilingPatternIR /XStep value.`); + } + const ystep = dict.get("YStep"); + if (typeof ystep !== "number") { + throw new FormatError3(`Invalid getTilingPatternIR /YStep value.`); + } + const paintType = dict.get("PaintType"); + if (!Number.isInteger(paintType)) { + throw new FormatError3(`Invalid getTilingPatternIR /PaintType value.`); + } + const tilingType = dict.get("TilingType"); + if (!Number.isInteger(tilingType)) { + throw new FormatError3(`Invalid getTilingPatternIR /TilingType value.`); + } + return ["TilingPattern", color, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType]; +} +function getXfaFontName(name) { + const fontName = normalizeFontName(name); + const fontMap = getXFAFontMap(); + return fontMap[fontName]; +} +function getXfaFontWidths(name) { + const info3 = getXfaFontName(name); + if (!info3) { + return null; + } + const { + baseWidths, + baseMapping, + factors + } = info3; + const rescaledBaseWidths = !factors ? baseWidths : baseWidths.map((w, i) => w * factors[i]); + let currentCode = -2; + let currentArray; + const newWidths = []; + for (const [unicode, glyphIndex] of baseMapping.map((charUnicode, index2) => [charUnicode, index2]).sort(([unicode1], [unicode2]) => unicode1 - unicode2)) { + if (unicode === -1) { + continue; + } + if (unicode === currentCode + 1) { + currentArray.push(rescaledBaseWidths[glyphIndex]); + currentCode += 1; + } else { + currentCode = unicode; + currentArray = [rescaledBaseWidths[glyphIndex]]; + newWidths.push(unicode, currentArray); + } + } + return newWidths; +} +function getXfaFontDict(name) { + const widths = getXfaFontWidths(name); + const dict = new Dict(null); + dict.set("BaseFont", Name2.get(name)); + dict.set("Type", Name2.get("Font")); + dict.set("Subtype", Name2.get("CIDFontType2")); + dict.set("Encoding", Name2.get("Identity-H")); + dict.set("CIDToGIDMap", Name2.get("Identity")); + dict.set("W", widths); + dict.set("FirstChar", widths[0]); + dict.set("LastChar", widths.at(-2) + widths.at(-1).length - 1); + const descriptor = new Dict(null); + dict.set("FontDescriptor", descriptor); + const systemInfo = new Dict(null); + systemInfo.set("Ordering", "Identity"); + systemInfo.set("Registry", "Adobe"); + systemInfo.set("Supplement", 0); + dict.set("CIDSystemInfo", systemInfo); + return dict; +} +function toNumberArray(arr) { + if (!Array.isArray(arr)) { + return null; + } + if (!isNumberArray(arr, null)) { + return arr.map((x) => +x); + } + return arr; +} +function isPDFFunction(v) { + let fnDict; + if (v instanceof Dict) { + fnDict = v; + } else if (v instanceof BaseStream) { + fnDict = v.dict; + } else { + return false; + } + return fnDict.has("FunctionType"); +} +function buildAddOperation(num1, num2) { + if (num2.type === "literal" && num2.number === 0) { + return num1; + } + if (num1.type === "literal" && num1.number === 0) { + return num2; + } + if (num2.type === "literal" && num1.type === "literal") { + return new AstLiteral(num1.number + num2.number); + } + return new AstBinaryOperation("+", num1, num2, num1.min + num2.min, num1.max + num2.max); +} +function buildMulOperation(num1, num2) { + if (num2.type === "literal") { + if (num2.number === 0) { + return new AstLiteral(0); + } else if (num2.number === 1) { + return num1; + } else if (num1.type === "literal") { + return new AstLiteral(num1.number * num2.number); + } + } + if (num1.type === "literal") { + if (num1.number === 0) { + return new AstLiteral(0); + } else if (num1.number === 1) { + return num2; + } + } + const min2 = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + const max2 = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max); + return new AstBinaryOperation("*", num1, num2, min2, max2); +} +function buildSubOperation(num1, num2) { + if (num2.type === "literal") { + if (num2.number === 0) { + return num1; + } else if (num1.type === "literal") { + return new AstLiteral(num1.number - num2.number); + } + } + if (num2.type === "binary" && num2.op === "-" && num1.type === "literal" && num1.number === 1 && num2.arg1.type === "literal" && num2.arg1.number === 1) { + return num2.arg2; + } + return new AstBinaryOperation("-", num1, num2, num1.min - num2.max, num1.max - num2.min); +} +function buildMinOperation(num1, max2) { + if (num1.min >= max2) { + return new AstLiteral(max2); + } else if (num1.max <= max2) { + return num1; + } + return new AstMin(num1, max2); +} +function isOdd(i) { + return (i & 1) !== 0; +} +function isEven(i) { + return (i & 1) === 0; +} +function findUnequal(arr, start, value) { + let j, jj; + for (j = start, jj = arr.length; j < jj; ++j) { + if (arr[j] !== value) { + return j; + } + } + return j; +} +function reverseValues(arr, start, end) { + for (let i = start, j = end - 1; i < j; ++i, --j) { + const temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } +} +function createBidiText(str, isLTR, vertical = false) { + let dir = "ltr"; + if (vertical) { + dir = "ttb"; + } else if (!isLTR) { + dir = "rtl"; + } + return { + str, + dir + }; +} +function bidi(str, startLevel = -1, vertical = false) { + let isLTR = true; + const strLength = str.length; + if (strLength === 0 || vertical) { + return createBidiText(str, isLTR, vertical); + } + chars.length = strLength; + types2.length = strLength; + let numBidi = 0; + let i, ii; + for (i = 0; i < strLength; ++i) { + chars[i] = str.charAt(i); + const charCode = str.charCodeAt(i); + let charType = "L"; + if (charCode <= 255) { + charType = baseTypes[charCode]; + } else if (1424 <= charCode && charCode <= 1524) { + charType = "R"; + } else if (1536 <= charCode && charCode <= 1791) { + charType = arabicTypes[charCode & 255]; + if (!charType) { + warn2("Bidi: invalid Unicode character " + charCode.toString(16)); + } + } else if (1792 <= charCode && charCode <= 2220 || 64336 <= charCode && charCode <= 65023 || 65136 <= charCode && charCode <= 65279) { + charType = "AL"; + } + if (charType === "R" || charType === "AL" || charType === "AN") { + numBidi++; + } + types2[i] = charType; + } + if (numBidi === 0) { + isLTR = true; + return createBidiText(str, isLTR); + } + if (startLevel === -1) { + if (numBidi / strLength < 0.3 && strLength > 4) { + isLTR = true; + startLevel = 0; + } else { + isLTR = false; + startLevel = 1; + } + } + const levels = []; + for (i = 0; i < strLength; ++i) { + levels[i] = startLevel; + } + const e = isOdd(startLevel) ? "R" : "L"; + const sor = e; + const eor = sor; + let lastType = sor; + for (i = 0; i < strLength; ++i) { + if (types2[i] === "NSM") { + types2[i] = lastType; + } else { + lastType = types2[i]; + } + } + lastType = sor; + let t; + for (i = 0; i < strLength; ++i) { + t = types2[i]; + if (t === "EN") { + types2[i] = lastType === "AL" ? "AN" : "EN"; + } else if (t === "R" || t === "L" || t === "AL") { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + t = types2[i]; + if (t === "AL") { + types2[i] = "R"; + } + } + for (i = 1; i < strLength - 1; ++i) { + if (types2[i] === "ES" && types2[i - 1] === "EN" && types2[i + 1] === "EN") { + types2[i] = "EN"; + } + if (types2[i] === "CS" && (types2[i - 1] === "EN" || types2[i - 1] === "AN") && types2[i + 1] === types2[i - 1]) { + types2[i] = types2[i - 1]; + } + } + for (i = 0; i < strLength; ++i) { + if (types2[i] === "EN") { + for (let j = i - 1; j >= 0; --j) { + if (types2[j] !== "ET") { + break; + } + types2[j] = "EN"; + } + for (let j = i + 1; j < strLength; ++j) { + if (types2[j] !== "ET") { + break; + } + types2[j] = "EN"; + } + } + } + for (i = 0; i < strLength; ++i) { + t = types2[i]; + if (t === "WS" || t === "ES" || t === "ET" || t === "CS") { + types2[i] = "ON"; + } + } + lastType = sor; + for (i = 0; i < strLength; ++i) { + t = types2[i]; + if (t === "EN") { + types2[i] = lastType === "L" ? "L" : "EN"; + } else if (t === "R" || t === "L") { + lastType = t; + } + } + for (i = 0; i < strLength; ++i) { + if (types2[i] === "ON") { + const end = findUnequal(types2, i + 1, "ON"); + let before2 = sor; + if (i > 0) { + before2 = types2[i - 1]; + } + let after2 = eor; + if (end + 1 < strLength) { + after2 = types2[end + 1]; + } + if (before2 !== "L") { + before2 = "R"; + } + if (after2 !== "L") { + after2 = "R"; + } + if (before2 === after2) { + types2.fill(before2, i, end); + } + i = end - 1; + } + } + for (i = 0; i < strLength; ++i) { + if (types2[i] === "ON") { + types2[i] = e; + } + } + for (i = 0; i < strLength; ++i) { + t = types2[i]; + if (isEven(levels[i])) { + if (t === "R") { + levels[i] += 1; + } else if (t === "AN" || t === "EN") { + levels[i] += 2; + } + } else if (t === "L" || t === "AN" || t === "EN") { + levels[i] += 1; + } + } + let highestLevel = -1; + let lowestOddLevel = 99; + let level; + for (i = 0, ii = levels.length; i < ii; ++i) { + level = levels[i]; + if (highestLevel < level) { + highestLevel = level; + } + if (lowestOddLevel > level && isOdd(level)) { + lowestOddLevel = level; + } + } + for (level = highestLevel; level >= lowestOddLevel; --level) { + let start = -1; + for (i = 0, ii = levels.length; i < ii; ++i) { + if (levels[i] < level) { + if (start >= 0) { + reverseValues(chars, start, i); + start = -1; + } + } else if (start < 0) { + start = i; + } + } + if (start >= 0) { + reverseValues(chars, start, levels.length); + } + } + for (i = 0, ii = chars.length; i < ii; ++i) { + const ch2 = chars[i]; + if (ch2 === "<" || ch2 === ">") { + chars[i] = ""; + } + } + return createBidiText(chars.join(""), isLTR); +} +function getStyleToAppend(style) { + switch (style) { + case BOLD: + return "Bold"; + case ITALIC: + return "Italic"; + case BOLDITALIC: + return "Bold Italic"; + default: + if (style?.weight === "bold") { + return "Bold"; + } + if (style?.style === "italic") { + return "Italic"; + } + } + return ""; +} +function getFamilyName(str) { + const keywords = /* @__PURE__ */ new Set(["thin", "extralight", "ultralight", "demilight", "semilight", "light", "book", "regular", "normal", "medium", "demibold", "semibold", "bold", "extrabold", "ultrabold", "black", "heavy", "extrablack", "ultrablack", "roman", "italic", "oblique", "ultracondensed", "extracondensed", "condensed", "semicondensed", "normal", "semiexpanded", "expanded", "extraexpanded", "ultraexpanded", "bolditalic"]); + return str.split(/[- ,+]+/g).filter((tok) => !keywords.has(tok.toLowerCase())).join(" "); +} +function generateFont({ + alias, + local, + path: path2, + fallback, + style, + ultimate +}, src, localFontPath, useFallback = true, usePath = true, append = "") { + const result2 = { + style: null, + ultimate: null + }; + if (local) { + const extra = append ? ` ${append}` : ""; + for (const name of local) { + src.push(`local(${name}${extra})`); + } + } + if (alias) { + const substitution = substitutionMap.get(alias); + const aliasAppend = append || getStyleToAppend(style); + Object.assign(result2, generateFont(substitution, src, localFontPath, useFallback && !fallback, usePath && !path2, aliasAppend)); + } + if (style) { + result2.style = style; + } + if (ultimate) { + result2.ultimate = ultimate; + } + if (useFallback && fallback) { + const fallbackInfo = substitutionMap.get(fallback); + const { + ultimate: fallbackUltimate + } = generateFont(fallbackInfo, src, localFontPath, useFallback, usePath && !path2, append); + result2.ultimate ||= fallbackUltimate; + } + if (usePath && path2 && localFontPath) { + src.push(`url(${localFontPath}${path2})`); + } + return result2; +} +function getFontSubstitution(systemFontCache, idFactory, localFontPath, baseFontName, standardFontName, type) { + if (baseFontName.startsWith("InvalidPDFjsFont_")) { + return null; + } + if ((type === "TrueType" || type === "Type1") && /^[A-Z]{6}\+/.test(baseFontName)) { + baseFontName = baseFontName.slice(7); + } + baseFontName = normalizeFontName(baseFontName); + const key = baseFontName; + let substitutionInfo = systemFontCache.get(key); + if (substitutionInfo) { + return substitutionInfo; + } + let substitution = substitutionMap.get(baseFontName); + if (!substitution) { + for (const [alias, subst] of fontAliases) { + if (baseFontName.startsWith(alias)) { + baseFontName = `${subst}${baseFontName.substring(alias.length)}`; + substitution = substitutionMap.get(baseFontName); + break; + } + } + } + let mustAddBaseFont = false; + if (!substitution) { + substitution = substitutionMap.get(standardFontName); + mustAddBaseFont = true; + } + const loadedName = `${idFactory.getDocId()}_s${idFactory.createFontId()}`; + if (!substitution) { + if (!validateFontName(baseFontName)) { + warn2(`Cannot substitute the font because of its name: ${baseFontName}`); + systemFontCache.set(key, null); + return null; + } + const bold = /bold/gi.test(baseFontName); + const italic = /oblique|italic/gi.test(baseFontName); + const style2 = bold && italic && BOLDITALIC || bold && BOLD || italic && ITALIC || NORMAL; + substitutionInfo = { + css: `"${getFamilyName(baseFontName)}",${loadedName}`, + guessFallback: true, + loadedName, + baseFontName, + src: `local(${baseFontName})`, + style: style2 + }; + systemFontCache.set(key, substitutionInfo); + return substitutionInfo; + } + const src = []; + if (mustAddBaseFont && validateFontName(baseFontName)) { + src.push(`local(${baseFontName})`); + } + const { + style, + ultimate + } = generateFont(substitution, src, localFontPath); + const guessFallback = ultimate === null; + const fallback = guessFallback ? "" : `,${ultimate}`; + substitutionInfo = { + css: `"${getFamilyName(baseFontName)}",${loadedName}${fallback}`, + guessFallback, + loadedName, + baseFontName, + src: src.join(","), + style + }; + systemFontCache.set(key, substitutionInfo); + return substitutionInfo; +} +function resizeImageMask(src, bpc, w1, h1, w2, h2) { + const length = w2 * h2; + let dest; + if (bpc <= 8) { + dest = new Uint8Array(length); + } else if (bpc <= 16) { + dest = new Uint16Array(length); + } else { + dest = new Uint32Array(length); + } + const xRatio = w1 / w2; + const yRatio = h1 / h2; + let i, j, py, newIndex = 0, oldIndex; + const xScaled = new Uint16Array(w2); + const w1Scanline = w1; + for (i = 0; i < w2; i++) { + xScaled[i] = Math.floor(i * xRatio); + } + for (i = 0; i < h2; i++) { + py = Math.floor(i * yRatio) * w1Scanline; + for (j = 0; j < w2; j++) { + oldIndex = py + xScaled[j]; + dest[newIndex++] = src[oldIndex]; + } + } + return dest; +} +function normalizeBlendMode(value, parsingArray = false) { + if (Array.isArray(value)) { + for (const val of value) { + const maybeBM = normalizeBlendMode(val, true); + if (maybeBM) { + return maybeBM; + } + } + warn2(`Unsupported blend mode Array: ${value}`); + return "source-over"; + } + if (!(value instanceof Name2)) { + if (parsingArray) { + return null; + } + return "source-over"; + } + switch (value.name) { + case "Normal": + case "Compatible": + return "source-over"; + case "Multiply": + return "multiply"; + case "Screen": + return "screen"; + case "Overlay": + return "overlay"; + case "Darken": + return "darken"; + case "Lighten": + return "lighten"; + case "ColorDodge": + return "color-dodge"; + case "ColorBurn": + return "color-burn"; + case "HardLight": + return "hard-light"; + case "SoftLight": + return "soft-light"; + case "Difference": + return "difference"; + case "Exclusion": + return "exclusion"; + case "Hue": + return "hue"; + case "Saturation": + return "saturation"; + case "Color": + return "color"; + case "Luminosity": + return "luminosity"; + } + if (parsingArray) { + return null; + } + warn2(`Unsupported blend mode: ${value.name}`); + return "source-over"; +} +function addCachedImageOps(opList, { + objId, + fn, + args, + optionalContent, + hasMask +}) { + if (objId) { + opList.addDependency(objId); + } + opList.addImageOps(fn, args, optionalContent, hasMask); + if (fn === OPS2.paintImageMaskXObject && args[0]?.count > 0) { + args[0].count++; + } +} +function parseDefaultAppearance(str) { + return new DefaultAppearanceEvaluator(str).parse(); +} +function parseAppearanceStream(stream, evaluatorOptions, xref, globalColorSpaceCache) { + return new AppearanceStreamEvaluator(stream, evaluatorOptions, xref, globalColorSpaceCache).parse(); +} +function getPdfColor(color, isFill) { + if (color[0] === color[1] && color[1] === color[2]) { + const gray = color[0] / 255; + return `${numberToString(gray)} ${isFill ? "g" : "G"}`; + } + return Array.from(color, (c) => numberToString(c / 255)).join(" ") + ` ${isFill ? "rg" : "RG"}`; +} +function createDefaultAppearance({ + fontSize, + fontName, + fontColor +}) { + return `/${escapePDFName(fontName)} ${fontSize} Tf ${getPdfColor(fontColor, true)}`; +} +function clearGlobalCaches() { + clearPatternCaches(); + clearPrimitiveCaches(); + clearUnicodeCaches(); + JpxImage.cleanup(); +} +function pickPlatformItem(dict) { + if (!(dict instanceof Dict)) { + return null; + } + if (dict.has("UF")) { + return dict.get("UF"); + } else if (dict.has("F")) { + return dict.get("F"); + } else if (dict.has("Unix")) { + return dict.get("Unix"); + } else if (dict.has("Mac")) { + return dict.get("Mac"); + } else if (dict.has("DOS")) { + return dict.get("DOS"); + } + return null; +} +function stripPath(str) { + return str.substring(str.lastIndexOf("/") + 1); +} +function isWhitespace(s, index2) { + const ch2 = s[index2]; + return ch2 === " " || ch2 === "\n" || ch2 === "\r" || ch2 === " "; +} +function isWhitespaceString(s) { + for (let i = 0, ii = s.length; i < ii; i++) { + if (!isWhitespace(s, i)) { + return false; + } + } + return true; +} +function fetchDest(dest) { + if (dest instanceof Dict) { + dest = dest.get("D"); + } + return isValidExplicitDest2(dest) ? dest : null; +} +function fetchRemoteDest(action) { + let dest = action.get("D"); + if (dest) { + if (dest instanceof Name2) { + dest = dest.name; + } + if (typeof dest === "string") { + return stringToPDFString(dest, true); + } else if (isValidExplicitDest2(dest)) { + return JSON.stringify(dest); + } + } + return null; +} +function mayHaveChildren(value) { + return value instanceof Ref || value instanceof Dict || value instanceof BaseStream || Array.isArray(value); +} +function addChildren(node2, nodesToVisit) { + if (node2 instanceof Dict) { + node2 = node2.getRawValues(); + } else if (node2 instanceof BaseStream) { + node2 = node2.dict.getRawValues(); + } else if (!Array.isArray(node2)) { + return; + } + for (const rawValue of node2) { + if (mayHaveChildren(rawValue)) { + nodesToVisit.push(rawValue); + } + } +} +function stripQuotes(str) { + if (str.startsWith("'") || str.startsWith('"')) { + return str.slice(1, -1); + } + return str; +} +function getInteger({ + data, + defaultValue, + validate: validate2 +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + const n = parseInt(data, 10); + if (!isNaN(n) && validate2(n)) { + return n; + } + return defaultValue; +} +function getFloat({ + data, + defaultValue, + validate: validate2 +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + const n = parseFloat(data); + if (!isNaN(n) && validate2(n)) { + return n; + } + return defaultValue; +} +function getKeyword({ + data, + defaultValue, + validate: validate2 +}) { + if (!data) { + return defaultValue; + } + data = data.trim(); + if (validate2(data)) { + return data; + } + return defaultValue; +} +function getStringOption(data, options) { + return getKeyword({ + data, + defaultValue: options[0], + validate: (k) => options.includes(k) + }); +} +function getMeasurement(str, def = "0") { + def ||= "0"; + if (!str) { + return getMeasurement(def); + } + const match = str.trim().match(measurementPattern); + if (!match) { + return getMeasurement(def); + } + const [, valueStr, unit] = match; + const value = parseFloat(valueStr); + if (isNaN(value)) { + return getMeasurement(def); + } + if (value === 0) { + return 0; + } + const conv = dimConverters[unit]; + if (conv) { + return conv(value); + } + return value; +} +function getRatio(data) { + if (!data) { + return { + num: 1, + den: 1 + }; + } + const ratio = data.split(":", 2).map((x) => parseFloat(x.trim())).filter((x) => !isNaN(x)); + if (ratio.length === 1) { + ratio.push(1); + } + if (ratio.length === 0) { + return { + num: 1, + den: 1 + }; + } + const [num, den] = ratio; + return { + num, + den + }; +} +function getRelevant(data) { + if (!data) { + return []; + } + return data.trim().split(/\s+/).map((e) => ({ + excluded: e[0] === "-", + viewname: e.substring(1) + })); +} +function getColor(data, def = [0, 0, 0]) { + let [r, g, b2] = def; + if (!data) { + return { + r, + g, + b: b2 + }; + } + const color = data.split(",", 3).map((c) => MathClamp2(parseInt(c.trim(), 10), 0, 255)).map((c) => isNaN(c) ? 0 : c); + if (color.length < 3) { + return { + r, + g, + b: b2 + }; + } + [r, g, b2] = color; + return { + r, + g, + b: b2 + }; +} +function getBBox(data) { + const def = -1; + if (!data) { + return { + x: def, + y: def, + width: def, + height: def + }; + } + const bbox = data.split(",", 4).map((m) => getMeasurement(m.trim(), "-1")); + if (bbox.length < 4 || bbox[2] < 0 || bbox[3] < 0) { + return { + x: def, + y: def, + width: def, + height: def + }; + } + const [x, y, width, height] = bbox; + return { + x, + y, + width, + height + }; +} +function selectFont(xfaFont, typeface) { + if (xfaFont.posture === "italic") { + if (xfaFont.weight === "bold") { + return typeface.bolditalic; + } + return typeface.italic; + } else if (xfaFont.weight === "bold") { + return typeface.bold; + } + return typeface.regular; +} +function fonts_getMetrics(xfaFont, real2 = false) { + let pdfFont = null; + if (xfaFont) { + const name = stripQuotes(xfaFont.typeface); + const typeface = xfaFont[$globalData].fontFinder.find(name); + pdfFont = selectFont(xfaFont, typeface); + } + if (!pdfFont) { + return { + lineHeight: 12, + lineGap: 2, + lineNoGap: 10 + }; + } + const size3 = xfaFont.size || 10; + const lineHeight = pdfFont.lineHeight ? Math.max(real2 ? 0 : 1.2, pdfFont.lineHeight) : 1.2; + const lineGap = pdfFont.lineGap === void 0 ? 0.2 : pdfFont.lineGap; + return { + lineHeight: lineHeight * size3, + lineGap: lineGap * size3, + lineNoGap: Math.max(1, lineHeight - lineGap) * size3 + }; +} +function parseIndex(index2) { + index2 = index2.trim(); + if (index2 === "*") { + return Infinity; + } + return parseInt(index2, 10) || 0; +} +function parseExpression(expr, dotDotAllowed, noExpr = true) { + let match = expr.match(namePattern); + if (!match) { + return null; + } + let [name] = match; + const parsed = [{ + name, + cacheName: "." + name, + index: 0, + js: null, + formCalc: null, + operator: operators.dot + }]; + let pos = name.length; + while (pos < expr.length) { + const spos = pos; + const char2 = expr.charAt(pos++); + if (char2 === "[") { + match = expr.slice(pos).match(indexPattern); + if (!match) { + warn2("XFA - Invalid index in SOM expression"); + return null; + } + parsed.at(-1).index = parseIndex(match[0]); + pos += match[0].length + 1; + continue; + } + let operator; + switch (expr.charAt(pos)) { + case ".": + if (!dotDotAllowed) { + return null; + } + pos++; + operator = operators.dotDot; + break; + case "#": + pos++; + operator = operators.dotHash; + break; + case "[": + if (noExpr) { + warn2("XFA - SOM expression contains a FormCalc subexpression which is not supported for now."); + return null; + } + operator = operators.dotBracket; + break; + case "(": + if (noExpr) { + warn2("XFA - SOM expression contains a JavaScript subexpression which is not supported for now."); + return null; + } + operator = operators.dotParen; + break; + default: + operator = operators.dot; + break; + } + match = expr.slice(pos).match(namePattern); + if (!match) { + break; + } + [name] = match; + pos += name.length; + parsed.push({ + name, + cacheName: expr.slice(spos, pos), + operator, + index: 0, + js: null, + formCalc: null + }); + } + return parsed; +} +function searchNode(root2, container, expr, dotDotAllowed = true, useCache = true) { + const parsed = parseExpression(expr, dotDotAllowed); + if (!parsed) { + return null; + } + const fn = shortcuts.get(parsed[0].name); + let i = 0; + let isQualified; + if (fn) { + isQualified = true; + root2 = [fn(root2, container)]; + i = 1; + } else { + isQualified = container === null; + root2 = [container || root2]; + } + for (let ii = parsed.length; i < ii; i++) { + const { + name, + cacheName, + operator, + index: index2 + } = parsed[i]; + const nodes = []; + for (const node2 of root2) { + if (!node2.isXFAObject) { + continue; + } + let children, cached2; + if (useCache) { + cached2 = somCache.get(node2); + if (!cached2) { + cached2 = /* @__PURE__ */ new Map(); + somCache.set(node2, cached2); + } + children = cached2.get(cacheName); + } + if (!children) { + switch (operator) { + case operators.dot: + children = node2[$getChildrenByName](name, false); + break; + case operators.dotDot: + children = node2[$getChildrenByName](name, true); + break; + case operators.dotHash: + children = node2[$getChildrenByClass](name); + children = children.isXFAObjectArray ? children.children : [children]; + break; + default: + break; + } + if (useCache) { + cached2.set(cacheName, children); + } + } + if (children.length > 0) { + nodes.push(children); + } + } + if (nodes.length === 0 && !isQualified && i === 0) { + const parent = container[$getParent](); + container = parent; + if (!container) { + return null; + } + i = -1; + root2 = [container]; + continue; + } + root2 = isFinite(index2) ? nodes.filter((node2) => index2 < node2.length).map((node2) => node2[index2]) : nodes.flat(); + } + if (root2.length === 0) { + return null; + } + return root2; +} +function createDataNode(root2, container, expr) { + const parsed = parseExpression(expr); + if (!parsed) { + return null; + } + if (parsed.some((x) => x.operator === operators.dotDot)) { + return null; + } + const fn = shortcuts.get(parsed[0].name); + let i = 0; + if (fn) { + root2 = fn(root2, container); + i = 1; + } else { + root2 = container || root2; + } + for (let ii = parsed.length; i < ii; i++) { + const { + name, + operator, + index: index2 + } = parsed[i]; + if (!isFinite(index2)) { + parsed[i].index = 0; + return root2.createNodes(parsed.slice(i)); + } + let children; + switch (operator) { + case operators.dot: + children = root2[$getChildrenByName](name, false); + break; + case operators.dotDot: + children = root2[$getChildrenByName](name, true); + break; + case operators.dotHash: + children = root2[$getChildrenByClass](name); + children = children.isXFAObjectArray ? children.children : [children]; + break; + default: + break; + } + if (children.length === 0) { + return root2.createNodes(parsed.slice(i)); + } + if (index2 < children.length) { + const child = children[index2]; + if (!child.isXFAObject) { + warn2(`XFA - Cannot create a node.`); + return null; + } + root2 = child; + } else { + parsed[i].index = index2 - children.length; + return root2.createNodes(parsed.slice(i)); + } + } + return null; +} +function measureToString(m) { + if (typeof m === "string") { + return "0px"; + } + return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`; +} +function setMinMaxDimensions(node2, style) { + const parent = node2[$getSubformParent](); + if (parent.layout === "position") { + if (node2.minW > 0) { + style.minWidth = measureToString(node2.minW); + } + if (node2.maxW > 0) { + style.maxWidth = measureToString(node2.maxW); + } + if (node2.minH > 0) { + style.minHeight = measureToString(node2.minH); + } + if (node2.maxH > 0) { + style.maxHeight = measureToString(node2.maxH); + } + } +} +function layoutText(text2, xfaFont, margin, lineHeight, fontFinder, width) { + const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder); + if (typeof text2 === "string") { + measure.addString(text2); + } else { + text2[$pushGlyphs](measure); + } + return measure.compute(width); +} +function layoutNode(node2, availableSpace) { + let height = null; + let width = null; + let isBroken = false; + if ((!node2.w || !node2.h) && node2.value) { + let marginH = 0; + let marginV = 0; + if (node2.margin) { + marginH = node2.margin.leftInset + node2.margin.rightInset; + marginV = node2.margin.topInset + node2.margin.bottomInset; + } + let lineHeight = null; + let margin = null; + if (node2.para) { + margin = /* @__PURE__ */ Object.create(null); + lineHeight = node2.para.lineHeight === "" ? null : node2.para.lineHeight; + margin.top = node2.para.spaceAbove === "" ? 0 : node2.para.spaceAbove; + margin.bottom = node2.para.spaceBelow === "" ? 0 : node2.para.spaceBelow; + margin.left = node2.para.marginLeft === "" ? 0 : node2.para.marginLeft; + margin.right = node2.para.marginRight === "" ? 0 : node2.para.marginRight; + } + let font = node2.font; + if (!font) { + const root2 = node2[$getTemplateRoot](); + let parent = node2[$getParent](); + while (parent && parent !== root2) { + if (parent.font) { + font = parent.font; + break; + } + parent = parent[$getParent](); + } + } + const maxWidth = (node2.w || availableSpace.width) - marginH; + const fontFinder = node2[$globalData].fontFinder; + if (node2.value.exData && node2.value.exData[$content] && node2.value.exData.contentType === "text/html") { + const res = layoutText(node2.value.exData[$content], font, margin, lineHeight, fontFinder, maxWidth); + width = res.width; + height = res.height; + isBroken = res.isBroken; + } else { + const text2 = node2.value[$text](); + if (text2) { + const res = layoutText(text2, font, margin, lineHeight, fontFinder, maxWidth); + width = res.width; + height = res.height; + isBroken = res.isBroken; + } + } + if (width !== null && !node2.w) { + width += marginH; + } + if (height !== null && !node2.h) { + height += marginV; + } + } + return { + w: width, + h: height, + isBroken + }; +} +function computeBbox(node2, html, availableSpace) { + let bbox; + if (node2.w !== "" && node2.h !== "") { + bbox = [node2.x, node2.y, node2.w, node2.h]; + } else { + if (!availableSpace) { + return null; + } + let width = node2.w; + if (width === "") { + if (node2.maxW === 0) { + const parent = node2[$getSubformParent](); + width = parent.layout === "position" && parent.w !== "" ? 0 : node2.minW; + } else { + width = Math.min(node2.maxW, availableSpace.width); + } + html.attributes.style.width = measureToString(width); + } + let height = node2.h; + if (height === "") { + if (node2.maxH === 0) { + const parent = node2[$getSubformParent](); + height = parent.layout === "position" && parent.h !== "" ? 0 : node2.minH; + } else { + height = Math.min(node2.maxH, availableSpace.height); + } + html.attributes.style.height = measureToString(height); + } + bbox = [node2.x, node2.y, width, height]; + } + return bbox; +} +function fixDimensions(node2) { + const parent = node2[$getSubformParent](); + if (parent.layout?.includes("row")) { + const extra = parent[$extra]; + const colSpan = node2.colSpan; + let width; + if (colSpan === -1) { + width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn)); + } else { + width = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan)); + } + if (!isNaN(width)) { + node2.w = width; + } + } + if (parent.layout && parent.layout !== "position") { + node2.x = node2.y = 0; + } + if (node2.layout === "table") { + if (node2.w === "" && Array.isArray(node2.columnWidths)) { + node2.w = Math.sumPrecise(node2.columnWidths); + } + } +} +function layoutClass(node2) { + switch (node2.layout) { + case "position": + return "xfaPosition"; + case "lr-tb": + return "xfaLrTb"; + case "rl-row": + return "xfaRlRow"; + case "rl-tb": + return "xfaRlTb"; + case "row": + return "xfaRow"; + case "table": + return "xfaTable"; + case "tb": + return "xfaTb"; + default: + return "xfaPosition"; + } +} +function toStyle(node2, ...names) { + const style = /* @__PURE__ */ Object.create(null); + for (const name of names) { + const value = node2[name]; + if (value === null) { + continue; + } + if (converters.hasOwnProperty(name)) { + converters[name](node2, style); + continue; + } + if (value instanceof XFAObject) { + const newStyle = value[$toStyle](); + if (newStyle) { + Object.assign(style, newStyle); + } else { + warn2(`(DEBUG) - XFA - style for ${name} not implemented yet`); + } + } + } + return style; +} +function createWrapper(node2, html) { + const { + attributes + } = html; + const { + style + } = attributes; + const wrapper = { + name: "div", + attributes: { + class: ["xfaWrapper"], + style: /* @__PURE__ */ Object.create(null) + }, + children: [] + }; + attributes.class.push("xfaWrapped"); + if (node2.border) { + const { + widths, + insets + } = node2.border[$extra]; + let width, height; + let top = insets[0]; + let left = insets[3]; + const insetsH = insets[0] + insets[2]; + const insetsW = insets[1] + insets[3]; + switch (node2.border.hand) { + case "even": + top -= widths[0] / 2; + left -= widths[3] / 2; + width = `calc(100% + ${(widths[1] + widths[3]) / 2 - insetsW}px)`; + height = `calc(100% + ${(widths[0] + widths[2]) / 2 - insetsH}px)`; + break; + case "left": + top -= widths[0]; + left -= widths[3]; + width = `calc(100% + ${widths[1] + widths[3] - insetsW}px)`; + height = `calc(100% + ${widths[0] + widths[2] - insetsH}px)`; + break; + case "right": + width = insetsW ? `calc(100% - ${insetsW}px)` : "100%"; + height = insetsH ? `calc(100% - ${insetsH}px)` : "100%"; + break; + } + const classNames = ["xfaBorder"]; + if (isPrintOnly(node2.border)) { + classNames.push("xfaPrintOnly"); + } + const border = { + name: "div", + attributes: { + class: classNames, + style: { + top: `${top}px`, + left: `${left}px`, + width, + height + } + }, + children: [] + }; + for (const key of ["border", "borderWidth", "borderColor", "borderRadius", "borderStyle"]) { + if (style[key] !== void 0) { + border.attributes.style[key] = style[key]; + delete style[key]; + } + } + wrapper.children.push(border, html); + } else { + wrapper.children.push(html); + } + for (const key of ["background", "backgroundClip", "top", "left", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "transform", "transformOrigin", "visibility"]) { + if (style[key] !== void 0) { + wrapper.attributes.style[key] = style[key]; + delete style[key]; + } + } + wrapper.attributes.style.position = style.position === "absolute" ? "absolute" : "relative"; + delete style.position; + if (style.alignSelf) { + wrapper.attributes.style.alignSelf = style.alignSelf; + delete style.alignSelf; + } + return wrapper; +} +function fixTextIndent(styles) { + const indent = getMeasurement(styles.textIndent, "0px"); + if (indent >= 0) { + return; + } + const align = styles.textAlign === "right" ? "right" : "left"; + const name = "padding" + (align === "left" ? "Left" : "Right"); + const padding = getMeasurement(styles[name], "0px"); + styles[name] = `${padding - indent}px`; +} +function setAccess(node2, classNames) { + switch (node2.access) { + case "nonInteractive": + classNames.push("xfaNonInteractive"); + break; + case "readOnly": + classNames.push("xfaReadOnly"); + break; + case "protected": + classNames.push("xfaDisabled"); + break; + } +} +function isPrintOnly(node2) { + return node2.relevant.length > 0 && !node2.relevant[0].excluded && node2.relevant[0].viewname === "print"; +} +function getCurrentPara(node2) { + const stack = node2[$getTemplateRoot]()[$extra].paraStack; + return stack.length ? stack.at(-1) : null; +} +function setPara(node2, nodeStyle, value) { + if (value.attributes.class?.includes("xfaRich")) { + if (nodeStyle) { + if (node2.h === "") { + nodeStyle.height = "auto"; + } + if (node2.w === "") { + nodeStyle.width = "auto"; + } + } + const para = getCurrentPara(node2); + if (para) { + const valueStyle = value.attributes.style; + valueStyle.display = "flex"; + valueStyle.flexDirection = "column"; + switch (para.vAlign) { + case "top": + valueStyle.justifyContent = "start"; + break; + case "bottom": + valueStyle.justifyContent = "end"; + break; + case "middle": + valueStyle.justifyContent = "center"; + break; + } + const paraStyle = para[$toStyle](); + for (const [key, val] of Object.entries(paraStyle)) { + if (!(key in valueStyle)) { + valueStyle[key] = val; + } + } + } + } +} +function setFontFamily(xfaFont, node2, fontFinder, style) { + if (!fontFinder) { + delete style.fontFamily; + return; + } + const name = stripQuotes(xfaFont.typeface); + style.fontFamily = `"${name}"`; + const typeface = fontFinder.find(name); + if (typeface) { + const { + fontFamily + } = typeface.regular.cssFontInfo; + if (fontFamily !== name) { + style.fontFamily = `"${fontFamily}"`; + } + const para = getCurrentPara(node2); + if (para && para.lineHeight !== "") { + return; + } + if (style.lineHeight) { + return; + } + const pdfFont = selectFont(xfaFont, typeface); + if (pdfFont) { + style.lineHeight = Math.max(1.2, pdfFont.lineHeight); + } + } +} +function fixURL(str) { + const absoluteUrl = createValidAbsoluteUrl2(str, null, { + addDefaultProtocol: true, + tryConvertEncoding: true + }); + return absoluteUrl ? absoluteUrl.href : null; +} +function createLine(node2, children) { + return { + name: "div", + attributes: { + class: [node2.layout === "lr-tb" ? "xfaLr" : "xfaRl"] + }, + children + }; +} +function flushHTML(node2) { + if (!node2[$extra]) { + return null; + } + const attributes = node2[$extra].attributes; + const html = { + name: "div", + attributes, + children: node2[$extra].children + }; + if (node2[$extra].failingNode) { + const htmlFromFailing = node2[$extra].failingNode[$flushHTML](); + if (htmlFromFailing) { + if (node2.layout.endsWith("-tb")) { + html.children.push(createLine(node2, [htmlFromFailing])); + } else { + html.children.push(htmlFromFailing); + } + } + } + if (html.children.length === 0) { + return null; + } + return html; +} +function addHTML(node2, html, bbox) { + const extra = node2[$extra]; + const availableSpace = extra.availableSpace; + const [x, y, w, h] = bbox; + switch (node2.layout) { + case "position": { + extra.width = Math.max(extra.width, x + w); + extra.height = Math.max(extra.height, y + h); + extra.children.push(html); + break; + } + case "lr-tb": + case "rl-tb": + if (!extra.line || extra.attempt === 1) { + extra.line = createLine(node2, []); + extra.children.push(extra.line); + extra.numberInLine = 0; + } + extra.numberInLine += 1; + extra.line.children.push(html); + if (extra.attempt === 0) { + extra.currentWidth += w; + extra.height = Math.max(extra.height, extra.prevHeight + h); + } else { + extra.currentWidth = w; + extra.prevHeight = extra.height; + extra.height += h; + extra.attempt = 0; + } + extra.width = Math.max(extra.width, extra.currentWidth); + break; + case "rl-row": + case "row": { + extra.children.push(html); + extra.width += w; + extra.height = Math.max(extra.height, h); + const height = measureToString(extra.height); + for (const child of extra.children) { + child.attributes.style.height = height; + } + break; + } + case "table": { + extra.width = MathClamp2(w, extra.width, availableSpace.width); + extra.height += h; + extra.children.push(html); + break; + } + case "tb": { + extra.width = MathClamp2(w, extra.width, availableSpace.width); + extra.height += h; + extra.children.push(html); + break; + } + } +} +function getAvailableSpace(node2) { + const availableSpace = node2[$extra].availableSpace; + const marginV = node2.margin ? node2.margin.topInset + node2.margin.bottomInset : 0; + const marginH = node2.margin ? node2.margin.leftInset + node2.margin.rightInset : 0; + switch (node2.layout) { + case "lr-tb": + case "rl-tb": + if (node2[$extra].attempt === 0) { + return { + width: availableSpace.width - marginH - node2[$extra].currentWidth, + height: availableSpace.height - marginV - node2[$extra].prevHeight + }; + } + return { + width: availableSpace.width - marginH, + height: availableSpace.height - marginV - node2[$extra].height + }; + case "rl-row": + case "row": + const width = Math.sumPrecise(node2[$extra].columnWidths.slice(node2[$extra].currentColumn)); + return { + width, + height: availableSpace.height - marginH + }; + case "table": + case "tb": + return { + width: availableSpace.width - marginH, + height: availableSpace.height - marginV - node2[$extra].height + }; + case "position": + default: + return availableSpace; + } +} +function getTransformedBBox(node2) { + let w = node2.w === "" ? NaN : node2.w; + let h = node2.h === "" ? NaN : node2.h; + let [centerX, centerY] = [0, 0]; + switch (node2.anchorType || "") { + case "bottomCenter": + [centerX, centerY] = [w / 2, h]; + break; + case "bottomLeft": + [centerX, centerY] = [0, h]; + break; + case "bottomRight": + [centerX, centerY] = [w, h]; + break; + case "middleCenter": + [centerX, centerY] = [w / 2, h / 2]; + break; + case "middleLeft": + [centerX, centerY] = [0, h / 2]; + break; + case "middleRight": + [centerX, centerY] = [w, h / 2]; + break; + case "topCenter": + [centerX, centerY] = [w / 2, 0]; + break; + case "topRight": + [centerX, centerY] = [w, 0]; + break; + } + let x, y; + switch (node2.rotate || 0) { + case 0: + [x, y] = [-centerX, -centerY]; + break; + case 90: + [x, y] = [-centerY, centerX]; + [w, h] = [h, -w]; + break; + case 180: + [x, y] = [centerX, centerY]; + [w, h] = [-w, -h]; + break; + case 270: + [x, y] = [centerY, -centerX]; + [w, h] = [-h, w]; + break; + } + return [node2.x + x + Math.min(0, w), node2.y + y + Math.min(0, h), Math.abs(w), Math.abs(h)]; +} +function checkDimensions(node2, space) { + if (node2[$getTemplateRoot]()[$extra].firstUnsplittable === null) { + return true; + } + if (node2.w === 0 || node2.h === 0) { + return true; + } + const ERROR = 2; + const parent = node2[$getSubformParent](); + const attempt = parent[$extra]?.attempt || 0; + const [, y, w, h] = getTransformedBBox(node2); + switch (parent.layout) { + case "lr-tb": + case "rl-tb": + if (attempt === 0) { + if (!node2[$getTemplateRoot]()[$extra].noLayoutFailure) { + if (node2.h !== "" && Math.round(h - space.height) > ERROR) { + return false; + } + if (node2.w !== "") { + if (Math.round(w - space.width) <= ERROR) { + return true; + } + if (parent[$extra].numberInLine === 0) { + return space.height > ERROR; + } + return false; + } + return space.width > ERROR; + } + if (node2.w !== "") { + return Math.round(w - space.width) <= ERROR; + } + return space.width > ERROR; + } + if (node2[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node2.h !== "" && Math.round(h - space.height) > ERROR) { + return false; + } + if (node2.w === "" || Math.round(w - space.width) <= ERROR) { + return space.height > ERROR; + } + if (parent[$isThereMoreWidth]()) { + return false; + } + return space.height > ERROR; + case "table": + case "tb": + if (node2[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node2.h !== "" && !node2[$isSplittable]()) { + return Math.round(h - space.height) <= ERROR; + } + if (node2.w === "" || Math.round(w - space.width) <= ERROR) { + return space.height > ERROR; + } + if (parent[$isThereMoreWidth]()) { + return false; + } + return space.height > ERROR; + case "position": + if (node2[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node2.h === "" || Math.round(h + y - space.height) <= ERROR) { + return true; + } + const area = node2[$getTemplateRoot]()[$extra].currentContentArea; + return h + y > area.h; + case "rl-row": + case "row": + if (node2[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + if (node2.h !== "") { + return Math.round(h - space.height) <= ERROR; + } + return true; + default: + return true; + } +} +function getBorderDims(node2) { + if (!node2 || !node2.border) { + return { + w: 0, + h: 0 + }; + } + const borderExtra = node2.border[$getExtra](); + if (!borderExtra) { + return { + w: 0, + h: 0 + }; + } + return { + w: borderExtra.widths[0] + borderExtra.widths[2] + borderExtra.insets[0] + borderExtra.insets[2], + h: borderExtra.widths[1] + borderExtra.widths[3] + borderExtra.insets[1] + borderExtra.insets[3] + }; +} +function hasMargin(node2) { + return node2.margin && (node2.margin.topInset || node2.margin.rightInset || node2.margin.bottomInset || node2.margin.leftInset); +} +function _setValue(templateNode, value) { + if (!templateNode.value) { + const nodeValue = new Value({}); + templateNode[$appendChild](nodeValue); + templateNode.value = nodeValue; + } + templateNode.value[$setValue](value); +} +function* getContainedChildren(node2) { + for (const child of node2[$getChildren]()) { + if (child instanceof SubformSet) { + yield* child[$getContainedChildren](); + continue; + } + yield child; + } +} +function isRequired(node2) { + return node2.validate?.nullTest === "error"; +} +function setTabIndex(node2) { + while (node2) { + if (!node2.traversal) { + node2[$tabIndex] = node2[$getParent]()[$tabIndex]; + return; + } + if (node2[$tabIndex]) { + return; + } + let next = null; + for (const child of node2.traversal[$getChildren]()) { + if (child.operation === "next") { + next = child; + break; + } + } + if (!next || !next.ref) { + node2[$tabIndex] = node2[$getParent]()[$tabIndex]; + return; + } + const root2 = node2[$getTemplateRoot](); + node2[$tabIndex] = ++root2[$tabIndex]; + const ref = root2[$searchNode](next.ref, node2); + if (!ref) { + return; + } + node2 = ref[0]; + } +} +function applyAssist(obj2, attributes) { + const assist = obj2.assist; + if (assist) { + const assistTitle = assist[$toHTML](); + if (assistTitle) { + attributes.title = assistTitle; + } + const role = assist.role; + const match = role.match(HEADING_PATTERN); + if (match) { + const ariaRole = "heading"; + const ariaLevel = match[1]; + attributes.role = ariaRole; + attributes["aria-level"] = ariaLevel; + } + } + if (obj2.layout === "table") { + attributes.role = "table"; + } else if (obj2.layout === "row") { + attributes.role = "row"; + } else { + const parent = obj2[$getParent](); + if (parent.layout === "row") { + attributes.role = parent.assist?.role === "TH" ? "columnheader" : "cell"; + } + } +} +function ariaLabel(obj2) { + if (!obj2.assist) { + return null; + } + const assist = obj2.assist; + if (assist.speak && assist.speak[$content] !== "") { + return assist.speak[$content]; + } + if (assist.toolTip) { + return assist.toolTip[$content]; + } + return null; +} +function valueToHtml(value) { + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: /* @__PURE__ */ Object.create(null) + }, + children: [{ + name: "span", + attributes: { + style: /* @__PURE__ */ Object.create(null) + }, + value + }] + }); +} +function setFirstUnsplittable(node2) { + const root2 = node2[$getTemplateRoot](); + if (root2[$extra].firstUnsplittable === null) { + root2[$extra].firstUnsplittable = node2; + root2[$extra].noLayoutFailure = true; + } +} +function unsetFirstUnsplittable(node2) { + const root2 = node2[$getTemplateRoot](); + if (root2[$extra].firstUnsplittable === node2) { + root2[$extra].noLayoutFailure = false; + } +} +function handleBreak(node2) { + if (node2[$extra]) { + return false; + } + node2[$extra] = /* @__PURE__ */ Object.create(null); + if (node2.targetType === "auto") { + return false; + } + const root2 = node2[$getTemplateRoot](); + let target = null; + if (node2.target) { + target = root2[$searchNode](node2.target, node2[$getParent]()); + if (!target) { + return false; + } + target = target[0]; + } + const { + currentPageArea, + currentContentArea + } = root2[$extra]; + if (node2.targetType === "pageArea") { + if (!(target instanceof PageArea)) { + target = null; + } + if (node2.startNew) { + node2[$extra].target = target || currentPageArea; + return true; + } else if (target && target !== currentPageArea) { + node2[$extra].target = target; + return true; + } + return false; + } + if (!(target instanceof ContentArea)) { + target = null; + } + const pageArea = target && target[$getParent](); + let index2; + let nextPageArea = pageArea; + if (node2.startNew) { + if (target) { + const contentAreas = pageArea.contentArea.children; + const indexForCurrent = contentAreas.indexOf(currentContentArea); + const indexForTarget = contentAreas.indexOf(target); + if (indexForCurrent !== -1 && indexForCurrent < indexForTarget) { + nextPageArea = null; + } + index2 = indexForTarget - 1; + } else { + index2 = currentPageArea.contentArea.children.indexOf(currentContentArea); + } + } else if (target && target !== currentContentArea) { + const contentAreas = pageArea.contentArea.children; + index2 = contentAreas.indexOf(target) - 1; + nextPageArea = pageArea === currentPageArea ? null : pageArea; + } else { + return false; + } + node2[$extra].target = nextPageArea; + node2[$extra].index = index2; + return true; +} +function handleOverflow(node2, extraNode, space) { + const root2 = node2[$getTemplateRoot](); + const saved = root2[$extra].noLayoutFailure; + const savedMethod = extraNode[$getSubformParent]; + extraNode[$getSubformParent] = () => node2; + root2[$extra].noLayoutFailure = true; + const res = extraNode[$toHTML](space); + node2[$addHTML](res.html, res.bbox); + root2[$extra].noLayoutFailure = saved; + extraNode[$getSubformParent] = savedMethod; +} +function createText(content) { + const node2 = new Text({}); + node2[$content] = content; + return node2; +} +function mapStyle(styleStr, node2, richText) { + const style = /* @__PURE__ */ Object.create(null); + if (!styleStr) { + return style; + } + const original = /* @__PURE__ */ Object.create(null); + for (const [key, value] of styleStr.split(";").map((s) => s.split(":", 2))) { + const mapping = StyleMapping.get(key); + if (mapping === "") { + continue; + } + let newValue = value; + if (mapping) { + newValue = typeof mapping === "string" ? mapping : mapping(value, original); + } + if (key.endsWith("scale")) { + style.transform = style.transform ? `${style[key]} ${newValue}` : newValue; + } else { + style[key.replaceAll(/-([a-zA-Z])/g, (_3, x) => x.toUpperCase())] = newValue; + } + } + if (style.fontFamily) { + setFontFamily({ + typeface: style.fontFamily, + weight: style.fontWeight || "normal", + posture: style.fontStyle || "normal", + size: original.fontSize || 0 + }, node2, node2[$globalData].fontFinder, style); + } + if (richText && style.verticalAlign && style.verticalAlign !== "0px" && style.fontSize) { + const SUB_SUPER_SCRIPT_FACTOR = 0.583; + const VERTICAL_FACTOR = 0.333; + const fontSize = getMeasurement(style.fontSize); + style.fontSize = measureToString(fontSize * SUB_SUPER_SCRIPT_FACTOR); + style.verticalAlign = measureToString(Math.sign(getMeasurement(style.verticalAlign)) * fontSize * VERTICAL_FACTOR); + } + if (richText && style.fontSize) { + style.fontSize = `calc(${style.fontSize} * var(--total-scale-factor))`; + } + fixTextIndent(style); + return style; +} +function checkStyle(node2) { + if (!node2.style) { + return ""; + } + return node2.style.split(";").filter((s) => !!s.trim()).map((s) => s.split(":", 2).map((t) => t.trim())).filter(([key, value]) => { + if (key === "font-family") { + node2[$globalData].usedTypefaces.add(value); + } + return VALID_STYLES.has(key); + }).map((kv) => kv.join(":")).join(";"); +} +function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) { + if (!Array.isArray(color)) { + return defaultColor; + } + const rgbColor = defaultColor || new Uint8ClampedArray(3); + switch (color.length) { + case 0: + return null; + case 1: + ColorSpaceUtils.gray.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + case 3: + ColorSpaceUtils.rgb.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + case 4: + ColorSpaceUtils.cmyk.getRgbItem(color, 0, rgbColor, 0); + return rgbColor; + default: + return defaultColor; + } +} +function getPdfColorArray(color, defaultValue = null) { + return color && Array.from(color, (c) => c / 255) || defaultValue; +} +function getQuadPoints(dict, rect) { + const quadPoints = dict.getArray("QuadPoints"); + if (!isNumberArray(quadPoints, null) || quadPoints.length === 0 || quadPoints.length % 8 > 0) { + return null; + } + const newQuadPoints = new Float32Array(quadPoints.length); + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + const [x1, y1, x2, y2, x3, y3, x4, y4] = quadPoints.slice(i, i + 8); + const minX = Math.min(x1, x2, x3, x4); + const maxX = Math.max(x1, x2, x3, x4); + const minY = Math.min(y1, y2, y3, y4); + const maxY = Math.max(y1, y2, y3, y4); + if (rect !== null && (minX < rect[0] || maxX > rect[2] || minY < rect[1] || maxY > rect[3])) { + return null; + } + newQuadPoints.set([minX, maxY, maxX, maxY, minX, minY, maxX, minY], i); + } + return newQuadPoints; +} +function getTransformMatrix(rect, bbox, matrix) { + const minMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + Util2.axialAlignedBoundingBox(bbox, matrix, minMax); + const [minX, minY, maxX, maxY] = minMax; + if (minX === maxX || minY === maxY) { + return [1, 0, 0, 1, rect[0], rect[1]]; + } + const xRatio = (rect[2] - rect[0]) / (maxX - minX); + const yRatio = (rect[3] - rect[1]) / (maxY - minY); + return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio]; +} +function calculateMD5(data, offset, length) { + let h0 = 1732584193, h1 = -271733879, h2 = -1732584194, h3 = 271733878; + const paddedLength = length + 72 & ~63; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 128; + const n = paddedLength - 8; + if (i < n) { + i = n; + } + padded[i++] = length << 3 & 255; + padded[i++] = length >> 5 & 255; + padded[i++] = length >> 13 & 255; + padded[i++] = length >> 21 & 255; + padded[i++] = length >>> 29 & 255; + i += 3; + const w = new Int32Array(16); + const { + k, + r + } = PARAMS; + for (i = 0; i < paddedLength; ) { + for (j = 0; j < 16; ++j, i += 4) { + w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24; + } + let a = h0, b2 = h1, c = h2, d = h3, f, g; + for (j = 0; j < 64; ++j) { + if (j < 16) { + f = b2 & c | ~b2 & d; + g = j; + } else if (j < 32) { + f = d & b2 | ~d & c; + g = 5 * j + 1 & 15; + } else if (j < 48) { + f = b2 ^ c ^ d; + g = 3 * j + 5 & 15; + } else { + f = c ^ (b2 | ~d); + g = 7 * j & 15; + } + const tmp = d, rotateArg = a + f + k[j] + w[g] | 0, rotate = r[j]; + d = c; + c = b2; + b2 = b2 + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0; + a = tmp; + } + h0 = h0 + a | 0; + h1 = h1 + b2 | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + } + return new Uint8Array([h0 & 255, h0 >> 8 & 255, h0 >> 16 & 255, h0 >>> 24 & 255, h1 & 255, h1 >> 8 & 255, h1 >> 16 & 255, h1 >>> 24 & 255, h2 & 255, h2 >> 8 & 255, h2 >> 16 & 255, h2 >>> 24 & 255, h3 & 255, h3 >> 8 & 255, h3 >> 16 & 255, h3 >>> 24 & 255]); +} +function decodeString(str) { + try { + return stringToUTF8String2(str); + } catch (ex) { + warn2(`UTF-8 decoding failed: "${ex}".`); + return str; + } +} +function ch(result2, x, y, z2, tmp) { + result2.assign(x); + result2.and(y); + tmp.assign(x); + tmp.not(); + tmp.and(z2); + result2.xor(tmp); +} +function maj(result2, x, y, z2, tmp) { + result2.assign(x); + result2.and(y); + tmp.assign(x); + tmp.and(z2); + result2.xor(tmp); + tmp.assign(y); + tmp.and(z2); + result2.xor(tmp); +} +function sigma(result2, x, tmp) { + result2.assign(x); + result2.rotateRight(28); + tmp.assign(x); + tmp.rotateRight(34); + result2.xor(tmp); + tmp.assign(x); + tmp.rotateRight(39); + result2.xor(tmp); +} +function sigmaPrime(result2, x, tmp) { + result2.assign(x); + result2.rotateRight(14); + tmp.assign(x); + tmp.rotateRight(18); + result2.xor(tmp); + tmp.assign(x); + tmp.rotateRight(41); + result2.xor(tmp); +} +function littleSigma(result2, x, tmp) { + result2.assign(x); + result2.rotateRight(1); + tmp.assign(x); + tmp.rotateRight(8); + result2.xor(tmp); + tmp.assign(x); + tmp.shiftRight(7); + result2.xor(tmp); +} +function littleSigmaPrime(result2, x, tmp) { + result2.assign(x); + result2.rotateRight(19); + tmp.assign(x); + tmp.rotateRight(61); + result2.xor(tmp); + tmp.assign(x); + tmp.shiftRight(6); + result2.xor(tmp); +} +function calculateSHA512(data, offset, length, mode384 = false) { + let h0, h1, h2, h3, h4, h5, h6, h7; + if (!mode384) { + h0 = new Word64(1779033703, 4089235720); + h1 = new Word64(3144134277, 2227873595); + h2 = new Word64(1013904242, 4271175723); + h3 = new Word64(2773480762, 1595750129); + h4 = new Word64(1359893119, 2917565137); + h5 = new Word64(2600822924, 725511199); + h6 = new Word64(528734635, 4215389547); + h7 = new Word64(1541459225, 327033209); + } else { + h0 = new Word64(3418070365, 3238371032); + h1 = new Word64(1654270250, 914150663); + h2 = new Word64(2438529370, 812702999); + h3 = new Word64(355462360, 4144912697); + h4 = new Word64(1731405415, 4290775857); + h5 = new Word64(2394180231, 1750603025); + h6 = new Word64(3675008525, 1694076839); + h7 = new Word64(1203062813, 3204075428); + } + const paddedLength = Math.ceil((length + 17) / 128) * 128; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 128; + const n = paddedLength - 16; + if (i < n) { + i = n; + } + i += 11; + padded[i++] = length >>> 29 & 255; + padded[i++] = length >> 21 & 255; + padded[i++] = length >> 13 & 255; + padded[i++] = length >> 5 & 255; + padded[i++] = length << 3 & 255; + const w = new Array(80); + for (i = 0; i < 80; i++) { + w[i] = new Word64(0, 0); + } + const { + k + } = calculate_sha_other_PARAMS; + let a = new Word64(0, 0), b2 = new Word64(0, 0), c = new Word64(0, 0); + let d = new Word64(0, 0), e = new Word64(0, 0), f = new Word64(0, 0); + let g = new Word64(0, 0), h = new Word64(0, 0); + const t1 = new Word64(0, 0), t2 = new Word64(0, 0); + const tmp1 = new Word64(0, 0), tmp2 = new Word64(0, 0); + let tmp3; + for (i = 0; i < paddedLength; ) { + for (j = 0; j < 16; ++j) { + w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7]; + i += 8; + } + for (j = 16; j < 80; ++j) { + tmp3 = w[j]; + littleSigmaPrime(tmp3, w[j - 2], tmp2); + tmp3.add(w[j - 7]); + littleSigma(tmp1, w[j - 15], tmp2); + tmp3.add(tmp1); + tmp3.add(w[j - 16]); + } + a.assign(h0); + b2.assign(h1); + c.assign(h2); + d.assign(h3); + e.assign(h4); + f.assign(h5); + g.assign(h6); + h.assign(h7); + for (j = 0; j < 80; ++j) { + t1.assign(h); + sigmaPrime(tmp1, e, tmp2); + t1.add(tmp1); + ch(tmp1, e, f, g, tmp2); + t1.add(tmp1); + t1.add(k[j]); + t1.add(w[j]); + sigma(t2, a, tmp2); + maj(tmp1, a, b2, c, tmp2); + t2.add(tmp1); + tmp3 = h; + h = g; + g = f; + f = e; + d.add(t1); + e = d; + d = c; + c = b2; + b2 = a; + tmp3.assign(t1); + tmp3.add(t2); + a = tmp3; + } + h0.add(a); + h1.add(b2); + h2.add(c); + h3.add(d); + h4.add(e); + h5.add(f); + h6.add(g); + h7.add(h); + } + let result2; + if (!mode384) { + result2 = new Uint8Array(64); + h0.copyTo(result2, 0); + h1.copyTo(result2, 8); + h2.copyTo(result2, 16); + h3.copyTo(result2, 24); + h4.copyTo(result2, 32); + h5.copyTo(result2, 40); + h6.copyTo(result2, 48); + h7.copyTo(result2, 56); + } else { + result2 = new Uint8Array(48); + h0.copyTo(result2, 0); + h1.copyTo(result2, 8); + h2.copyTo(result2, 16); + h3.copyTo(result2, 24); + h4.copyTo(result2, 32); + h5.copyTo(result2, 40); + } + return result2; +} +function calculateSHA384(data, offset, length) { + return calculateSHA512(data, offset, length, true); +} +function rotr(x, n) { + return x >>> n | x << 32 - n; +} +function calculate_sha256_ch(x, y, z2) { + return x & y ^ ~x & z2; +} +function calculate_sha256_maj(x, y, z2) { + return x & y ^ x & z2 ^ y & z2; +} +function calculate_sha256_sigma(x) { + return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); +} +function calculate_sha256_sigmaPrime(x) { + return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); +} +function calculate_sha256_littleSigma(x) { + return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3; +} +function calculate_sha256_littleSigmaPrime(x) { + return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10; +} +function calculateSHA256(data, offset, length) { + let h0 = 1779033703, h1 = 3144134277, h2 = 1013904242, h3 = 2773480762, h4 = 1359893119, h5 = 2600822924, h6 = 528734635, h7 = 1541459225; + const paddedLength = Math.ceil((length + 9) / 64) * 64; + const padded = new Uint8Array(paddedLength); + let i, j; + for (i = 0; i < length; ++i) { + padded[i] = data[offset++]; + } + padded[i++] = 128; + const n = paddedLength - 8; + if (i < n) { + i = n; + } + i += 3; + padded[i++] = length >>> 29 & 255; + padded[i++] = length >> 21 & 255; + padded[i++] = length >> 13 & 255; + padded[i++] = length >> 5 & 255; + padded[i++] = length << 3 & 255; + const w = new Uint32Array(64); + const { + k + } = calculate_sha256_PARAMS; + for (i = 0; i < paddedLength; ) { + for (j = 0; j < 16; ++j) { + w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3]; + i += 4; + } + for (j = 16; j < 64; ++j) { + w[j] = calculate_sha256_littleSigmaPrime(w[j - 2]) + w[j - 7] + calculate_sha256_littleSigma(w[j - 15]) + w[j - 16] | 0; + } + let a = h0, b2 = h1, c = h2, d = h3, e = h4, f = h5, g = h6, h = h7, t1, t2; + for (j = 0; j < 64; ++j) { + t1 = h + calculate_sha256_sigmaPrime(e) + calculate_sha256_ch(e, f, g) + k[j] + w[j]; + t2 = calculate_sha256_sigma(a) + calculate_sha256_maj(a, b2, c); + h = g; + g = f; + f = e; + e = d + t1 | 0; + d = c; + c = b2; + b2 = a; + a = t1 + t2 | 0; + } + h0 = h0 + a | 0; + h1 = h1 + b2 | 0; + h2 = h2 + c | 0; + h3 = h3 + d | 0; + h4 = h4 + e | 0; + h5 = h5 + f | 0; + h6 = h6 + g | 0; + h7 = h7 + h | 0; + } + return new Uint8Array([h0 >> 24 & 255, h0 >> 16 & 255, h0 >> 8 & 255, h0 & 255, h1 >> 24 & 255, h1 >> 16 & 255, h1 >> 8 & 255, h1 & 255, h2 >> 24 & 255, h2 >> 16 & 255, h2 >> 8 & 255, h2 & 255, h3 >> 24 & 255, h3 >> 16 & 255, h3 >> 8 & 255, h3 & 255, h4 >> 24 & 255, h4 >> 16 & 255, h4 >> 8 & 255, h4 & 255, h5 >> 24 & 255, h5 >> 16 & 255, h5 >> 8 & 255, h5 & 255, h6 >> 24 & 255, h6 >> 16 & 255, h6 >> 8 & 255, h6 & 255, h7 >> 24 & 255, h7 >> 16 & 255, h7 >> 8 & 255, h7 & 255]); +} +function find2(stream, signature, limit = 1024, backwards = false) { + const signatureLength = signature.length; + const scanBytes = stream.peekBytes(limit); + const scanLength = scanBytes.length - signatureLength; + if (scanLength <= 0) { + return false; + } + if (backwards) { + const signatureEnd = signatureLength - 1; + let pos = scanBytes.length - 1; + while (pos >= signatureEnd) { + let j = 0; + while (j < signatureLength && scanBytes[pos - j] === signature[signatureEnd - j]) { + j++; + } + if (j >= signatureLength) { + stream.pos += pos - signatureEnd; + return true; + } + pos--; + } + } else { + let pos = 0; + while (pos <= scanLength) { + let j = 0; + while (j < signatureLength && scanBytes[pos + j] === signature[j]) { + j++; + } + if (j >= signatureLength) { + stream.pos += pos; + return true; + } + pos++; + } + } + return false; +} +function parseDocBaseUrl(url2) { + if (url2) { + const absoluteUrl = createValidAbsoluteUrl2(url2); + if (absoluteUrl) { + return absoluteUrl.href; + } + warn2(`Invalid absolute docBaseUrl: "${url2}".`); + } + return null; +} +function onFn2() { +} +function wrapReason2(ex) { + if (ex instanceof AbortException3 || ex instanceof InvalidPDFException3 || ex instanceof PasswordException3 || ex instanceof ResponseException3 || ex instanceof UnknownErrorException3) { + return ex; + } + if (!(ex instanceof Error || typeof ex === "object" && ex !== null)) { + unreachable2('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); + } + switch (ex.name) { + case "AbortException": + return new AbortException3(ex.message); + case "InvalidPDFException": + return new InvalidPDFException3(ex.message); + case "PasswordException": + return new PasswordException3(ex.message, ex.code); + case "ResponseException": + return new ResponseException3(ex.message, ex.status, ex.missing); + case "UnknownErrorException": + return new UnknownErrorException3(ex.message, ex.details); + } + return new UnknownErrorException3(ex.message, ex.toString()); +} +async function writeObject(ref, obj2, buffer2, { + encrypt = null +}) { + const transform2 = encrypt?.createCipherTransform(ref.num, ref.gen); + buffer2.push(`${ref.num} ${ref.gen} obj +`); + if (obj2 instanceof Dict) { + await writeDict(obj2, buffer2, transform2); + } else if (obj2 instanceof BaseStream) { + await writeStream(obj2, buffer2, transform2); + } else if (Array.isArray(obj2) || ArrayBuffer.isView(obj2)) { + await writeArray(obj2, buffer2, transform2); + } + buffer2.push("\nendobj\n"); +} +async function writeDict(dict, buffer2, transform2) { + buffer2.push("<<"); + for (const key of dict.getKeys()) { + buffer2.push(` /${escapePDFName(key)} `); + await writeValue(dict.getRaw(key), buffer2, transform2); + } + buffer2.push(">>"); +} +async function writeStream(stream, buffer2, transform2) { + let bytes = stream.getBytes(); + const { + dict + } = stream; + const [filter2, params] = await Promise.all([dict.getAsync("Filter"), dict.getAsync("DecodeParms")]); + const filterZero = Array.isArray(filter2) ? await dict.xref.fetchIfRefAsync(filter2[0]) : filter2; + const isFilterZeroFlateDecode = isName(filterZero, "FlateDecode"); + const MIN_LENGTH_FOR_COMPRESSING = 256; + if (bytes.length >= MIN_LENGTH_FOR_COMPRESSING || isFilterZeroFlateDecode) { + try { + const cs = new CompressionStream("deflate"); + const writer = cs.writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => { + }); + const buf = await new Response(cs.readable).arrayBuffer(); + bytes = new Uint8Array(buf); + let newFilter, newParams; + if (!filter2) { + newFilter = Name2.get("FlateDecode"); + } else if (!isFilterZeroFlateDecode) { + newFilter = Array.isArray(filter2) ? [Name2.get("FlateDecode"), ...filter2] : [Name2.get("FlateDecode"), filter2]; + if (params) { + newParams = Array.isArray(params) ? [null, ...params] : [null, params]; + } + } + if (newFilter) { + dict.set("Filter", newFilter); + } + if (newParams) { + dict.set("DecodeParms", newParams); + } + } catch (ex) { + info2(`writeStream - cannot compress data: "${ex}".`); + } + } + let string4 = bytesToString2(bytes); + if (transform2) { + string4 = transform2.encryptString(string4); + } + dict.set("Length", string4.length); + await writeDict(dict, buffer2, transform2); + buffer2.push(" stream\n", string4, "\nendstream"); +} +async function writeArray(array2, buffer2, transform2) { + buffer2.push("["); + let first2 = true; + for (const val of array2) { + if (!first2) { + buffer2.push(" "); + } else { + first2 = false; + } + await writeValue(val, buffer2, transform2); + } + buffer2.push("]"); +} +async function writeValue(value, buffer2, transform2) { + if (value instanceof Name2) { + buffer2.push(`/${escapePDFName(value.name)}`); + } else if (value instanceof Ref) { + buffer2.push(`${value.num} ${value.gen} R`); + } else if (Array.isArray(value) || ArrayBuffer.isView(value)) { + await writeArray(value, buffer2, transform2); + } else if (typeof value === "string") { + if (transform2) { + value = transform2.encryptString(value); + } + buffer2.push(`(${escapeString(value)})`); + } else if (typeof value === "number") { + buffer2.push(numberToString(value)); + } else if (typeof value === "boolean") { + buffer2.push(value.toString()); + } else if (value instanceof Dict) { + await writeDict(value, buffer2, transform2); + } else if (value instanceof BaseStream) { + await writeStream(value, buffer2, transform2); + } else if (value === null) { + buffer2.push("null"); + } else { + warn2(`Unhandled value in writer: ${typeof value}, please file a bug.`); + } +} +function writeInt(number4, size3, offset, buffer2) { + for (let i = size3 + offset - 1; i > offset - 1; i--) { + buffer2[i] = number4 & 255; + number4 >>= 8; + } + return offset + size3; +} +function writeString(string4, offset, buffer2) { + const ii = string4.length; + for (let i = 0; i < ii; i++) { + buffer2[offset + i] = string4.charCodeAt(i) & 255; + } + return offset + ii; +} +function computeMD5(filesize, xrefInfo) { + const time4 = Math.floor(Date.now() / 1e3); + const filename = xrefInfo.filename || ""; + const md5Buffer = [time4.toString(), filename, filesize.toString(), ...xrefInfo.infoMap.values()]; + const md5BufferLen = Math.sumPrecise(md5Buffer.map((str) => str.length)); + const array2 = new Uint8Array(md5BufferLen); + let offset = 0; + for (const str of md5Buffer) { + offset = writeString(str, offset, array2); + } + return bytesToString2(calculateMD5(array2, 0, array2.length)); +} +function writeXFADataForAcroform(str, changes) { + const xml = new SimpleXMLParser({ + hasAttributes: true + }).parseFromString(str); + for (const { + xfa + } of changes) { + if (!xfa) { + continue; + } + const { + path: path2, + value + } = xfa; + if (!path2) { + continue; + } + const nodePath = parseXFAPath(path2); + let node2 = xml.documentElement.searchNode(nodePath, 0); + if (!node2 && nodePath.length > 1) { + node2 = xml.documentElement.searchNode([nodePath.at(-1)], 0); + } + if (node2) { + node2.childNodes = Array.isArray(value) ? value.map((val) => new SimpleDOMNode("value", val)) : [new SimpleDOMNode("#text", value)]; + } else { + warn2(`Node not found for path: ${path2}`); + } + } + const buffer2 = []; + xml.documentElement.dump(buffer2); + return buffer2.join(""); +} +async function updateAcroform({ + xref, + acroForm, + acroFormRef, + hasXfa, + hasXfaDatasetsEntry, + xfaDatasetsRef, + needAppearances, + changes +}) { + if (hasXfa && !hasXfaDatasetsEntry && !xfaDatasetsRef) { + warn2("XFA - Cannot save it"); + } + if (!needAppearances && (!hasXfa || !xfaDatasetsRef || hasXfaDatasetsEntry)) { + return; + } + const dict = acroForm.clone(); + if (hasXfa && !hasXfaDatasetsEntry) { + const newXfa = acroForm.get("XFA").slice(); + newXfa.splice(2, 0, "datasets"); + newXfa.splice(3, 0, xfaDatasetsRef); + dict.set("XFA", newXfa); + } + if (needAppearances) { + dict.set("NeedAppearances", true); + } + changes.put(acroFormRef, { + data: dict + }); +} +function updateXFA({ + xfaData, + xfaDatasetsRef, + changes, + xref +}) { + if (xfaData === null) { + const datasets = xref.fetchIfRef(xfaDatasetsRef); + xfaData = writeXFADataForAcroform(datasets.getString(), changes); + } + const xfaDataStream = new StringStream(xfaData); + xfaDataStream.dict = new Dict(xref); + xfaDataStream.dict.setIfName("Type", "EmbeddedFile"); + changes.put(xfaDatasetsRef, { + data: xfaDataStream + }); +} +async function getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer2) { + buffer2.push("xref\n"); + const indexes = getIndexes(newRefs); + let indexesPosition = 0; + for (const { + ref, + data + } of newRefs) { + if (ref.num === indexes[indexesPosition]) { + buffer2.push(`${indexes[indexesPosition]} ${indexes[indexesPosition + 1]} +`); + indexesPosition += 2; + } + if (data !== null) { + buffer2.push(`${baseOffset.toString().padStart(10, "0")} ${Math.min(ref.gen, 65535).toString().padStart(5, "0")} n\r +`); + baseOffset += data.length; + } else { + buffer2.push(`0000000000 ${Math.min(ref.gen + 1, 65535).toString().padStart(5, "0")} f\r +`); + } + } + computeIDs(baseOffset, xrefInfo, newXref); + buffer2.push("trailer\n"); + await writeDict(newXref, buffer2); + buffer2.push("\nstartxref\n", baseOffset.toString(), "\n%%EOF\n"); +} +function getIndexes(newRefs) { + const indexes = []; + for (const { + ref + } of newRefs) { + if (ref.num === indexes.at(-2) + indexes.at(-1)) { + indexes[indexes.length - 1] += 1; + } else { + indexes.push(ref.num, 1); + } + } + return indexes; +} +async function getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer2) { + const xrefTableData = []; + let maxOffset = 0; + let maxGen = 0; + for (const { + ref, + data: data2 + } of newRefs) { + let gen; + maxOffset = Math.max(maxOffset, baseOffset); + if (data2 !== null) { + gen = Math.min(ref.gen, 65535); + xrefTableData.push([1, baseOffset, gen]); + baseOffset += data2.length; + } else { + gen = Math.min(ref.gen + 1, 65535); + xrefTableData.push([0, 0, gen]); + } + maxGen = Math.max(maxGen, gen); + } + newXref.set("Index", getIndexes(newRefs)); + const offsetSize = getSizeInBytes(maxOffset); + const maxGenSize = getSizeInBytes(maxGen); + const sizes = [1, offsetSize, maxGenSize]; + newXref.set("W", sizes); + computeIDs(baseOffset, xrefInfo, newXref); + const structSize = Math.sumPrecise(sizes); + const data = new Uint8Array(structSize * xrefTableData.length); + const stream = new Stream3(data); + stream.dict = newXref; + let offset = 0; + for (const [type, objOffset, gen] of xrefTableData) { + offset = writeInt(type, sizes[0], offset, data); + offset = writeInt(objOffset, sizes[1], offset, data); + offset = writeInt(gen, sizes[2], offset, data); + } + await writeObject(xrefInfo.newRef, stream, buffer2, {}); + buffer2.push("startxref\n", baseOffset.toString(), "\n%%EOF\n"); +} +function computeIDs(baseOffset, xrefInfo, newXref) { + if (Array.isArray(xrefInfo.fileIds) && xrefInfo.fileIds.length > 0) { + const md52 = computeMD5(baseOffset, xrefInfo); + newXref.set("ID", [xrefInfo.fileIds[0], md52]); + } +} +function getTrailerDict(xrefInfo, changes, useXrefStream) { + const newXref = new Dict(null); + newXref.set("Prev", xrefInfo.startXRef); + const refForXrefTable = xrefInfo.newRef; + if (useXrefStream) { + changes.put(refForXrefTable, { + data: "" + }); + newXref.set("Size", refForXrefTable.num + 1); + newXref.setIfName("Type", "XRef"); + } else { + newXref.set("Size", refForXrefTable.num); + } + if (xrefInfo.rootRef !== null) { + newXref.set("Root", xrefInfo.rootRef); + } + if (xrefInfo.infoRef !== null) { + newXref.set("Info", xrefInfo.infoRef); + } + if (xrefInfo.encryptRef !== null) { + newXref.set("Encrypt", xrefInfo.encryptRef); + } + return newXref; +} +async function writeChanges(changes, xref, buffer2 = []) { + const newRefs = []; + for (const [ref, { + data + }] of changes.items()) { + if (data === null || typeof data === "string") { + newRefs.push({ + ref, + data + }); + continue; + } + await writeObject(ref, data, buffer2, xref); + newRefs.push({ + ref, + data: buffer2.join("") + }); + buffer2.length = 0; + } + return newRefs.sort((a, b2) => a.ref.num - b2.ref.num); +} +async function incrementalUpdate({ + originalData, + xrefInfo, + changes, + xref = null, + hasXfa = false, + xfaDatasetsRef = null, + hasXfaDatasetsEntry = false, + needAppearances, + acroFormRef = null, + acroForm = null, + xfaData = null, + useXrefStream = false +}) { + await updateAcroform({ + xref, + acroForm, + acroFormRef, + hasXfa, + hasXfaDatasetsEntry, + xfaDatasetsRef, + needAppearances, + changes + }); + if (hasXfa) { + updateXFA({ + xfaData, + xfaDatasetsRef, + changes, + xref + }); + } + const newXref = getTrailerDict(xrefInfo, changes, useXrefStream); + const buffer2 = []; + const newRefs = await writeChanges(changes, xref, buffer2); + let baseOffset = originalData.length; + const lastByte = originalData.at(-1); + if (lastByte !== 10 && lastByte !== 13) { + buffer2.push("\n"); + baseOffset += 1; + } + for (const { + data + } of newRefs) { + if (data !== null) { + buffer2.push(data); + } + } + await (useXrefStream ? getXRefStreamTable(xrefInfo, baseOffset, newRefs, newXref, buffer2) : getXRefTable(xrefInfo, baseOffset, newRefs, newXref, buffer2)); + const totalLength = originalData.length + Math.sumPrecise(buffer2.map((str) => str.length)); + const array2 = new Uint8Array(totalLength); + array2.set(originalData); + let offset = originalData.length; + for (const str of buffer2) { + offset = writeString(str, offset, array2); + } + return array2; +} +var __webpack_modules__2, __webpack_module_cache__2, es_array_push2, es_array_buffer_detached2, es_array_buffer_transfer2, es_array_buffer_transfer_to_fixed_length2, es_iterator_constructor2, es_iterator_filter2, es_iterator_map2, es_iterator_some2, es_promise_with_resolvers2, es_set_difference_v22, es_set_intersection_v22, es_set_is_disjoint_from_v22, es_set_is_subset_of_v22, es_set_is_superset_of_v22, es_set_symmetric_difference_v22, es_set_union_v22, es_typed_array_with2, esnext_uint8_array_set_from_base642, esnext_uint8_array_set_from_hex2, esnext_uint8_array_to_base642, esnext_uint8_array_to_hex2, web_self, es_iterator_reduce2, es_promise_try2, esnext_math_sum_precise2, esnext_uint8_array_from_base642, web_dom_exception_stack2, web_url_parse2, isNodeJS2, FONT_IDENTITY_MATRIX2, LINE_FACTOR2, LINE_DESCENT_FACTOR2, BASELINE_FACTOR2, RenderingIntentFlag2, AnnotationEditorPrefix2, AnnotationEditorType2, PermissionFlag2, TextRenderingMode2, ImageKind2, AnnotationType2, AnnotationReplyType, AnnotationFlag, AnnotationFieldFlag, AnnotationBorderStyleType2, AnnotationActionEventType, DocumentActionEventType, PageActionEventType, VerbosityLevel2, OPS2, DrawOPS3, PasswordResponses2, verbosity2, BaseException2, PasswordException3, UnknownErrorException3, InvalidPDFException3, ResponseException3, FormatError3, AbortException3, FeatureTest2, hexNumbers2, Util2, PDFStringTranslateTable, NormalizeRegex2, NormalizationMap2, AnnotationPrefix2, es_iterator_every2, CIRCULAR_REF, EOF, CmdCache, NameCache, RefCache, Name2, Cmd, nonSerializable, Dict, Ref, RefSet, RefSetCache, BaseStream, PDF_VERSION_REGEXP, MAX_INT_32, MIN_INT_32, IDENTITY_MATRIX, RESOURCES_KEYS_OPERATOR_LIST, RESOURCES_KEYS_TEXT_CONTENT, MissingDataException, ParserEOFException, XRefEntryException, XRefParseException, ROMAN_NUMBER_MAP, XMLEntities, web_url_search_params_delete2, web_url_search_params_has2, web_url_search_params_size2, QCMS, wasm, cachedTextDecoder, cachedUint8ArrayMemory0, WASM_VECTOR_LEN, DataType, Intent, ColorSpace, AlternateCS, PatternCS, IndexedCS, DeviceGrayCS, DeviceRgbCS, DeviceRgbaCS, DeviceCmykCS, CalGrayCS, CalRGBCS, LabCS, IccColorSpace, CmykICCBasedCS, Stream3, StringStream, NullStream, ChunkedStream, ChunkedStreamManager, MIN_IMAGE_DIM, MAX_IMAGE_DIM, MAX_ERROR, ImageResizer, emptyBuffer, DecodeStream, StreamsSequenceStream, ColorSpaceUtils, JpegError, DNLMarkerError, EOIMarkerError, dctZigZag, dctCos1, dctSin1, dctCos3, dctSin3, dctCos6, dctSin6, dctSqrt2, dctSqrt1d2, JpegImage, JpegStream, openjpeg, JpxError, JpxImage, InitialState, NullOptimizer, QueueOptimizer, OperatorList, es_iterator_find2, es_regexp_flags, es_iterator_for_each2, MAX_NUM_SIZE, MAX_ENCODED_NUM_SIZE, BinaryCMapStream, BinaryCMapReader, Ascii85Stream, AsciiHexStream, ccittEOL, ccittEOF, twoDimPass, twoDimHoriz, twoDimVert0, twoDimVertR1, twoDimVertL1, twoDimVertR2, twoDimVertL2, twoDimVertR3, twoDimVertL3, twoDimTable, whiteTable1, whiteTable2, blackTable1, blackTable2, blackTable3, CCITTFaxDecoder, CCITTFaxStream, codeLenCodeMap, lengthDecode, distDecode, fixedLitCodeTab, fixedDistCodeTab, FlateStream, QeTable, ArithmeticDecoder, Jbig2Error, ContextCache, DecodingContext, SegmentTypes, CodingTemplates, RefinementTemplates, ReusedContexts, RefinementReusedContexts, RegionSegmentInformationFieldLength, SimpleSegmentVisitor, HuffmanLine, HuffmanTreeNode, HuffmanTable, standardTablesCache, Reader, Jbig2Image, Jbig2Stream, JpxStream, LZWStream, PredictorStream, RunLengthStream, MAX_LENGTH_TO_CACHE, Parser, specialChars, Lexer, Linearization, BUILT_IN_CMAPS, MAX_MAP_RANGE, CMap, IdentityCMap, CMapFactory, ExpertEncoding, MacExpertEncoding, MacRomanEncoding, StandardEncoding, WinAnsiEncoding, SymbolSetEncoding, ZapfDingbatsEncoding, getGlyphsUnicode, getDingbatsGlyphsUnicode, getSpecialPUASymbols, UnicodeRanges, SpecialCharRegExp, CategoryCache, SEAC_ANALYSIS_ENABLED, FontFlags, MacStandardGlyphOrdering, getVerticalPresentationForm, MAX_SIZE_TO_COMPILE, es_iterator_to_array, ISOAdobeCharset, ExpertCharset, ExpertSubsetCharset, MAX_SUBR_NESTING, CFFStandardStrings, NUM_STANDARD_CFF_STRINGS, CharstringValidationData, CharstringValidationData12, CFFParser, CFF, CFFHeader, CFFStrings, CFFIndex, CFFDict, CFFTopDictLayout, CFFTopDict, CFFPrivateDictLayout, CFFPrivateDict, CFFCharsetPredefinedTypes, CFFCharset, CFFEncoding, CFFFDSelect, CFFOffsetTracker, CFFCompiler, getStdFontMap, getFontNameToFileMap, getNonStdFontMap, getSerifFonts, getSymbolsFonts, getGlyphMapForStandardFonts, getSupplementalGlyphMapForArialBlack, getSupplementalGlyphMapForCalibri, ToUnicodeMap, IdentityToUnicodeMap, CFFFont, NOOP, Commands, CompiledFont, TrueTypeCompiled, Type2Compiled, FontRendererFactory, getMetrics, getFontBasicMetrics, ON_CURVE_POINT, X_SHORT_VECTOR, Y_SHORT_VECTOR, REPEAT_FLAG, X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR, Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR, OVERLAP_SIMPLE, ARG_1_AND_2_ARE_WORDS, ARGS_ARE_XY_VALUES, WE_HAVE_A_SCALE, MORE_COMPONENTS, WE_HAVE_AN_X_AND_Y_SCALE, WE_HAVE_A_TWO_BY_TWO, WE_HAVE_INSTRUCTIONS, GlyfTable, Glyph, GlyphHeader, Contour, SimpleGlyph, CompositeGlyph, OTF_HEADER_SIZE, OTF_TABLE_ENTRY_SIZE, OpenTypeFileBuilder, HINTING_ENABLED, COMMAND_MAP, Type1CharString, EEXEC_ENCRYPT_KEY, CHAR_STRS_ENCRYPT_KEY, Type1Parser, Type1Font, PRIVATE_USE_AREAS, PDF_GLYPH_SPACE_UNITS, EXPORT_DATA_PROPERTIES, EXPORT_DATA_EXTRA_PROPERTIES, fonts_Glyph, Font, ErrorFont, ShadingType, Pattern, BaseShading, RadialAxialShading, MeshStreamReader, bCache, MeshShading, DummyShading, CalibriBoldFactors, CalibriBoldMetrics, CalibriBoldItalicFactors, CalibriBoldItalicMetrics, CalibriItalicFactors, CalibriItalicMetrics, CalibriRegularFactors, CalibriRegularMetrics, HelveticaBoldFactors, HelveticaBoldMetrics, HelveticaBoldItalicFactors, HelveticaBoldItalicMetrics, HelveticaItalicFactors, HelveticaItalicMetrics, HelveticaRegularFactors, HelveticaRegularMetrics, LiberationSansBoldWidths, LiberationSansBoldMapping, LiberationSansBoldItalicWidths, LiberationSansBoldItalicMapping, LiberationSansItalicWidths, LiberationSansItalicMapping, LiberationSansRegularWidths, LiberationSansRegularMapping, MyriadProBoldFactors, MyriadProBoldMetrics, MyriadProBoldItalicFactors, MyriadProBoldItalicMetrics, MyriadProItalicFactors, MyriadProItalicMetrics, MyriadProRegularFactors, MyriadProRegularMetrics, SegoeuiBoldFactors, SegoeuiBoldMetrics, SegoeuiBoldItalicFactors, SegoeuiBoldItalicMetrics, SegoeuiItalicFactors, SegoeuiItalicMetrics, SegoeuiRegularFactors, SegoeuiRegularMetrics, getXFAFontMap, PostScriptParser, PostScriptTokenTypes, PostScriptToken, PostScriptLexer, BaseLocalCache, LocalImageCache, LocalColorSpaceCache, LocalFunctionCache, LocalGStateCache, LocalTilingPatternCache, RegionalImageCache, GlobalColorSpaceCache, GlobalImageCache, PDFFunctionFactory, PDFFunction, PostScriptStack, PostScriptEvaluator, AstNode, AstArgument, AstLiteral, AstBinaryOperation, AstMin, AstVariable, AstVariableDefinition, ExpressionBuilderVisitor, PostScriptCompiler, baseTypes, arabicTypes, chars, types2, CssFontInfo2, SystemFontInfo2, FontInfo2, NORMAL, BOLD, ITALIC, BOLDITALIC, substitutionMap, fontAliases, SEED2, MASK_HIGH2, MASK_LOW2, MurmurHash3_642, PDFImage, DefaultPartialEvaluatorOptions, PatternType, TEXT_CHUNK_BATCH_SIZE, deferred, TimeSlotManager, PartialEvaluator, TranslatedFont, StateManager, TextState, EvalState, EvaluatorPreprocessor, DefaultAppearanceEvaluator, AppearanceStreamEvaluator, FakeUnicodeFont, DateFormats, TimeFormats, NameOrNumberTree, NameTree, NumberTree, FileSpec, XMLParserErrorCode, XMLParserBase, SimpleDOMNode, SimpleXMLParser, MetadataParser, MAX_DEPTH, StructElementType, StructTreeRoot, StructElementNode, StructElement, StructTreePage, isRef2, isValidExplicitDest2, Catalog, ObjectLoader, $acceptWhitespace, $addHTML, $appendChild, $childrenToHTML, $clean, $cleanPage, $cleanup, $clone, $consumed, $content, $data, $dump, $extra, $finalize, $flushHTML, $getAttributeIt, $getAttributes, $getAvailableSpace, $getChildrenByClass, $getChildrenByName, $getChildrenByNameIt, $getDataValue, $getExtra, $getRealChildrenByNameIt, $getChildren, $getContainedChildren, $getNextPage, $getSubformParent, $getParent, $getTemplateRoot, $globalData, $hasSettableValue, $ids, $indexOf, $insertAt, $isCDATAXml, $isBindable, $isDataValue, $isDescendent, $isNsAgnostic, $isSplittable, $isThereMoreWidth, $isTransparent, $isUsable, $lastAttribute, $namespaceId, $nodeName, $nsAttributes, $onChild, $onChildCheck, $onText, $pushGlyphs, $popPara, $pushPara, $removeChild, $root, $resolvePrototypes, $searchNode, $setId, $setSetAttributes, $setValue, $tabIndex, $text, $toPages, $toHTML, $toString, $toStyle, $uid, es_iterator_flat_map2, $buildXFAObject, NamespaceIds, dimConverters, measurementPattern, HTMLResult, FontFinder, WIDTH_FACTOR, text_FontInfo, FontSelector, TextMeasure, namePattern, indexPattern, operators, shortcuts, somCache, _applyPrototype, _attributes, _attributeNames, _children, _cloneAttribute, _dataValue, _defaultValue, _filteredChildrenGenerator, _getPrototype, _getUnsetAttributes, _hasChildren, _max, _options, _parent, _resolvePrototypesHelper, _setAttributes, _validator, uid2, NS_DATASETS, XFAObject, XFAObjectArray, XFAAttribute, XmlObject, ContentObject, OptionObject, StringObject, IntegerObject, Option01, Option10, converters, TEMPLATE_NS_ID, SVG_NS2, MAX_ATTEMPTS_FOR_LRTB_LAYOUT, MAX_EMPTY_PAGES, DEFAULT_TAB_INDEX, HEADING_PATTERN, MIMES, IMAGES_HEADERS, AppearanceFilter, Arc, Area, Assist, Barcode, Bind, BindItems, Bookend, BooleanElement, Border, Break, BreakAfter, BreakBefore, Button, Calculate, Caption, Certificate, Certificates, CheckButton, ChoiceList, Color, Comb, Connect, ContentArea, Corner, DateElement, DateTime, DateTimeEdit, Decimal, DefaultUi, Desc, DigestMethod, DigestMethods, Draw, Edge, Encoding, Encodings, Encrypt, EncryptData, Encryption, EncryptionMethod, EncryptionMethods, Event2, ExData, ExObject, ExclGroup, Execute, Extras, Field, Fill, Filter, Float, template_Font, Format, Handler, Hyphenation, Image2, ImageEdit, Integer, Issuers, Items, Keep, KeyUsage, Line2, Linear, LockDocument, Manifest, Margin, Mdp, Medium, Message, NumericEdit, Occur, Oid, Oids, Overflow, PageArea, PageSet, Para, PasswordEdit, template_Pattern, Picture, Proto, Radial, Reason, Reasons, Rectangle2, RefElement, Script, SetProperty, SignData, Signature, Signing, Solid, Speak, Stipple, Subform, SubformSet, SubjectDN, SubjectDNs, Submit, Template, Text, TextEdit, Time2, TimeStamp, ToolTip, Traversal, Traverse, Ui, Validate, Value, Variables, TemplateNamespace, bind_NS_DATASETS, Binder, DataHandler, CONFIG_NS_ID, Acrobat, Acrobat7, ADBE_JSConsole, ADBE_JSDebugger, AddSilentPrint, AddViewerPreferences, AdjustData, AdobeExtensionLevel, Agent, AlwaysEmbed, Amd, config_Area, Attributes, AutoSave, Base, BatchOutput, BehaviorOverride, Cache2, Change, Common, Compress, CompressLogicalStructure, CompressObjectStream, Compression, Config, Conformance, ContentCopy, Copies, Creator, CurrentPage, Data, Debug, DefaultTypeface, Destination, DocumentAssembly, Driver, DuplexOption, DynamicRender, Embed, config_Encrypt, config_Encryption, EncryptionLevel, Enforce, Equate, EquateRange, Exclude, ExcludeNS, FlipLabel, config_FontInfo, FormFieldFilling, GroupParent, IfEmpty, IncludeXDPContent, IncrementalLoad, IncrementalMerge, Interactive, Jog, LabelPrinter, Layout, Level, Linearized, Locale, LocaleSet, Log, MapElement, MediumInfo, config_Message, Messaging, Mode, ModifyAnnots, MsgId, NameAttr, NeverEmbed, NumberOfCopies, OpenAction, Output, OutputBin, OutputXSL, Overprint, Packets, PageOffset, PageRange, Pagination, PaginationOverride, Part, Pcl, Pdf, Pdfa, Permissions, PickTrayByPDFSize, config_Picture, PlaintextMetadata, Presence, Present, Print, PrintHighQuality, PrintScaling, PrinterName, Producer, Ps, Range2, Record, Relevant, Rename, RenderPolicy, RunScripts, config_Script, ScriptModel, Severity, SilentPrint, Staple, StartNode, StartPage, SubmitFormat, SubmitUrl, SubsetBelow, SuppressBanner, Tagged, config_Template, Threshold, To, TemplateCache, Trace, Transform, Type, Uri, config_Validate, ValidateApprovalSignatures, ValidationMessaging, Version, VersionControl, ViewerPreferences, WebClient, Whitespace, Window, Xdc, Xdp, Xsl, Zpl, ConfigNamespace, CONNECTION_SET_NS_ID, ConnectionSet, EffectiveInputPolicy, EffectiveOutputPolicy, Operation, RootElement, SoapAction, SoapAddress, connection_set_Uri, WsdlAddress, WsdlConnection, XmlConnection, XsdConnection, ConnectionSetNamespace, DATASETS_NS_ID, datasets_Data, Datasets, DatasetsNamespace, LOCALE_SET_NS_ID, CalendarSymbols, CurrencySymbol, CurrencySymbols, DatePattern, DatePatterns, DateTimeSymbols, Day, DayNames, Era, EraNames, locale_set_Locale, locale_set_LocaleSet, Meridiem, MeridiemNames, Month, MonthNames, NumberPattern, NumberPatterns, NumberSymbol, NumberSymbols, TimePattern, TimePatterns, TypeFace, TypeFaces, LocaleSetNamespace, SIGNATURE_NS_ID, signature_Signature, SignatureNamespace, STYLESHEET_NS_ID, Stylesheet, StylesheetNamespace, XDP_NS_ID, xdp_Xdp, XdpNamespace, XHTML_NS_ID, $richText, VALID_STYLES, StyleMapping, spacesRegExp, crlfRegExp, crlfForRichTextRegExp, NoWhites, XhtmlObject, A, B, Body, Br, Html, I, Li, Ol, P, Span, Sub, Sup, Ul, XhtmlNamespace, NamespaceSetUp, UnknownNamespace, Root, Empty, Builder2, XFAParser, XFAFactory, AnnotationFactory, Annotation, AnnotationBorderStyle, MarkupAnnotation, WidgetAnnotation, TextWidgetAnnotation, ButtonWidgetAnnotation, ChoiceWidgetAnnotation, SignatureWidgetAnnotation, TextAnnotation, LinkAnnotation, PopupAnnotation, FreeTextAnnotation, LineAnnotation, SquareAnnotation, CircleAnnotation, PolylineAnnotation, PolygonAnnotation, CaretAnnotation, InkAnnotation, HighlightAnnotation, UnderlineAnnotation, SquigglyAnnotation, StrikeOutAnnotation, StampAnnotation, FileAttachmentAnnotation, PARAMS, DatasetXMLParser, DatasetReader, SingleIntersector, Intersector, Word64, calculate_sha_other_PARAMS, calculate_sha256_PARAMS, chunkSize, DecryptStream, ARCFourCipher, NullCipher, AESBaseCipher, AES128Cipher, AES256Cipher, PDFBase, PDF17, PDF20, CipherTransform, CipherTransformFactory, XRef, LETTER_SIZE_MEDIABOX, Page, PDF_HEADER_SIGNATURE, STARTXREF_SIGNATURE, ENDOBJ_SIGNATURE, PDFDocument, BasePdfManager, LocalPdfManager, NetworkPdfManager, CallbackKind2, StreamKind2, MessageHandler2, PDFWorkerStream, PDFWorkerStreamReader, PDFWorkerStreamRangeReader, WorkerTask, WorkerMessageHandler; +var init_pdf_worker = __esm({ + "node_modules/.pnpm/pdfjs-dist@5.4.296/node_modules/pdfjs-dist/legacy/build/pdf.worker.mjs"() { + __webpack_modules__2 = { + /***/ + 34: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + module2.exports = function(it) { + return typeof it == "object" ? it !== null : isCallable(it); + }; + } + ), + /***/ + 81: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var tryToString = __webpack_require__3(6823); + var getIteratorMethod = __webpack_require__3(851); + var $TypeError = TypeError; + module2.exports = function(argument, usingIterator) { + var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator; + if (aCallable(iteratorMethod)) return anObject(call(iteratorMethod, argument)); + throw new $TypeError(tryToString(argument) + " is not iterable"); + }; + } + ), + /***/ + 116: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var findWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("find", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: findWithoutClosingOnEarlyError }, { + find: function find3(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (findWithoutClosingOnEarlyError) return call(findWithoutClosingOnEarlyError, this, predicate); + var record2 = getIteratorDirect(this); + var counter = 0; + return iterate(record2, function(value, stop) { + if (predicate(value, counter++)) return stop(value); + }, { IS_RECORD: true, INTERRUPTED: true }).result; + } + }); + } + ), + /***/ + 283: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); + var hasOwn = __webpack_require__3(9297); + var DESCRIPTORS = __webpack_require__3(3724); + var CONFIGURABLE_FUNCTION_NAME = __webpack_require__3(350).CONFIGURABLE; + var inspectSource = __webpack_require__3(3706); + var InternalStateModule = __webpack_require__3(1181); + var enforceInternalState = InternalStateModule.enforce; + var getInternalState = InternalStateModule.get; + var $String = String; + var defineProperty = Object.defineProperty; + var stringSlice = uncurryThis("".slice); + var replace = uncurryThis("".replace); + var join2 = uncurryThis([].join); + var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() { + return defineProperty(function() { + }, "length", { value: 8 }).length !== 8; + }); + var TEMPLATE = String(String).split("String"); + var makeBuiltIn = module2.exports = function(value, name, options) { + if (stringSlice($String(name), 0, 7) === "Symbol(") { + name = "[" + replace($String(name), /^Symbol\(([^)]*)\).*$/, "$1") + "]"; + } + if (options && options.getter) name = "get " + name; + if (options && options.setter) name = "set " + name; + if (!hasOwn(value, "name") || CONFIGURABLE_FUNCTION_NAME && value.name !== name) { + if (DESCRIPTORS) defineProperty(value, "name", { value: name, configurable: true }); + else value.name = name; + } + if (CONFIGURABLE_LENGTH && options && hasOwn(options, "arity") && value.length !== options.arity) { + defineProperty(value, "length", { value: options.arity }); + } + try { + if (options && hasOwn(options, "constructor") && options.constructor) { + if (DESCRIPTORS) defineProperty(value, "prototype", { writable: false }); + } else if (value.prototype) value.prototype = void 0; + } catch (error62) { + } + var state = enforceInternalState(value); + if (!hasOwn(state, "source")) { + state.source = join2(TEMPLATE, typeof name == "string" ? name : ""); + } + return value; + }; + Function.prototype.toString = makeBuiltIn(function toString2() { + return isCallable(this) && getInternalState(this).source || inspectSource(this); + }, "toString"); + } + ), + /***/ + 350: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var hasOwn = __webpack_require__3(9297); + var FunctionPrototype = Function.prototype; + var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor; + var EXISTS = hasOwn(FunctionPrototype, "name"); + var PROPER = EXISTS && function something() { + }.name === "something"; + var CONFIGURABLE = EXISTS && (!DESCRIPTORS || DESCRIPTORS && getDescriptor(FunctionPrototype, "name").configurable); + module2.exports = { + EXISTS, + PROPER, + CONFIGURABLE + }; + } + ), + /***/ + 397: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + module2.exports = getBuiltIn("document", "documentElement"); + } + ), + /***/ + 421: ( + /***/ + (module2) => { + module2.exports = {}; + } + ), + /***/ + 456: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var numberToString2 = uncurryThis(1.1.toString); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !function() { + try { + var target = new Uint8Array2([255, 255, 255, 255, 255, 255, 255, 255]); + return target.toHex() === "ffffffffffffffff"; + } catch (error62) { + return false; + } + }(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + toHex: function toHex() { + anUint8Array(this); + notDetached(this.buffer); + var result2 = ""; + for (var i = 0, length = this.length; i < length; i++) { + var hex3 = numberToString2(this[i], 16); + result2 += hex3.length === 1 ? "0" + hex3 : hex3; + } + return result2; + } + }); + } + ), + /***/ + 507: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + module2.exports = function(record2, fn, ITERATOR_INSTEAD_OF_RECORD) { + var iterator = ITERATOR_INSTEAD_OF_RECORD ? record2 : record2.iterator; + var next = record2.next; + var step, result2; + while (!(step = call(next, iterator)).done) { + result2 = fn(step.value); + if (result2 !== void 0) return result2; + } + }; + } + ), + /***/ + 531: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var getIteratorFlattenable = __webpack_require__3(8646); + var createIteratorProxy = __webpack_require__3(9462); + var iteratorClose = __webpack_require__3(9539); + var IS_PURE = __webpack_require__3(6395); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("flatMap", function() { + }); + var flatMapWithoutClosingOnEarlyError = !IS_PURE && !FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("flatMap", TypeError); + var FORCED = IS_PURE || FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR || flatMapWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var mapper = this.mapper; + var result2, inner; + while (true) { + if (inner = this.inner) try { + result2 = anObject(call(inner.next, inner.iterator)); + if (!result2.done) return result2.value; + this.inner = null; + } catch (error62) { + iteratorClose(iterator, "throw", error62); + } + result2 = anObject(call(this.next, iterator)); + if (this.done = !!result2.done) return; + try { + this.inner = getIteratorFlattenable(mapper(result2.value, this.counter++), false); + } catch (error62) { + iteratorClose(iterator, "throw", error62); + } + } + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + flatMap: function flatMap(mapper) { + anObject(this); + try { + aCallable(mapper); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (flatMapWithoutClosingOnEarlyError) return call(flatMapWithoutClosingOnEarlyError, this, mapper); + return new IteratorProxy(getIteratorDirect(this), { + mapper, + inner: null + }); + } + }); + } + ), + /***/ + 616: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + module2.exports = !fails(function() { + var test = function() { + }.bind(); + return typeof test != "function" || test.hasOwnProperty("prototype"); + }); + } + ), + /***/ + 655: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); + var $String = String; + module2.exports = function(argument) { + if (classof(argument) === "Symbol") throw new TypeError("Cannot convert a Symbol value to a string"); + return $String(argument); + }; + } + ), + /***/ + 679: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isPrototypeOf = __webpack_require__3(1625); + var $TypeError = TypeError; + module2.exports = function(it, Prototype) { + if (isPrototypeOf(Prototype, it)) return it; + throw new $TypeError("Incorrect invocation"); + }; + } + ), + /***/ + 684: ( + /***/ + (module2) => { + module2.exports = function(methodName, argument) { + var method = typeof Iterator == "function" && Iterator.prototype[methodName]; + if (method) try { + method.call({ next: null }, argument).next(); + } catch (error62) { + return true; + } + }; + } + ), + /***/ + 741: ( + /***/ + (module2) => { + var ceil2 = Math.ceil; + var floor2 = Math.floor; + module2.exports = Math.trunc || function trunc(x) { + var n = +x; + return (n > 0 ? floor2 : ceil2)(n); + }; + } + ), + /***/ + 757: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + var isCallable = __webpack_require__3(4901); + var isPrototypeOf = __webpack_require__3(1625); + var USE_SYMBOL_AS_UID = __webpack_require__3(7040); + var $Object = Object; + module2.exports = USE_SYMBOL_AS_UID ? function(it) { + return typeof it == "symbol"; + } : function(it) { + var $Symbol = getBuiltIn("Symbol"); + return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it)); + }; + } + ), + /***/ + 851: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); + var getMethod = __webpack_require__3(5966); + var isNullOrUndefined = __webpack_require__3(4117); + var Iterators = __webpack_require__3(6269); + var wellKnownSymbol = __webpack_require__3(8227); + var ITERATOR = wellKnownSymbol("iterator"); + module2.exports = function(it) { + if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR) || getMethod(it, "@@iterator") || Iterators[classof(it)]; + }; + } + ), + /***/ + 944: ( + /***/ + (module2) => { + var $TypeError = TypeError; + module2.exports = function(options) { + var alphabet = options && options.alphabet; + if (alphabet === void 0 || alphabet === "base64" || alphabet === "base64url") return alphabet || "base64"; + throw new $TypeError("Incorrect `alphabet` option"); + }; + } + ), + /***/ + 1072: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var internalObjectKeys = __webpack_require__3(1828); + var enumBugKeys = __webpack_require__3(8727); + module2.exports = Object.keys || function keys2(O) { + return internalObjectKeys(O, enumBugKeys); + }; + } + ), + /***/ + 1103: ( + /***/ + (module2) => { + module2.exports = function(exec) { + try { + return { error: false, value: exec() }; + } catch (error62) { + return { error: true, value: error62 }; + } + }; + } + ), + /***/ + 1108: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); + module2.exports = function(it) { + var klass = classof(it); + return klass === "BigInt64Array" || klass === "BigUint64Array"; + }; + } + ), + /***/ + 1148: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var everyWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("every", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: everyWithoutClosingOnEarlyError }, { + every: function every2(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (everyWithoutClosingOnEarlyError) return call(everyWithoutClosingOnEarlyError, this, predicate); + var record2 = getIteratorDirect(this); + var counter = 0; + return !iterate(record2, function(value, stop) { + if (!predicate(value, counter++)) return stop(); + }, { IS_RECORD: true, INTERRUPTED: true }).stopped; + } + }); + } + ), + /***/ + 1181: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_WEAK_MAP = __webpack_require__3(8622); + var globalThis2 = __webpack_require__3(4576); + var isObject5 = __webpack_require__3(34); + var createNonEnumerableProperty = __webpack_require__3(6699); + var hasOwn = __webpack_require__3(9297); + var shared = __webpack_require__3(7629); + var sharedKey = __webpack_require__3(6119); + var hiddenKeys = __webpack_require__3(421); + var OBJECT_ALREADY_INITIALIZED = "Object already initialized"; + var TypeError2 = globalThis2.TypeError; + var WeakMap2 = globalThis2.WeakMap; + var set2, get2, has3; + var enforce = function(it) { + return has3(it) ? get2(it) : set2(it, {}); + }; + var getterFor = function(TYPE) { + return function(it) { + var state; + if (!isObject5(it) || (state = get2(it)).type !== TYPE) { + throw new TypeError2("Incompatible receiver, " + TYPE + " required"); + } + return state; + }; + }; + if (NATIVE_WEAK_MAP || shared.state) { + var store = shared.state || (shared.state = new WeakMap2()); + store.get = store.get; + store.has = store.has; + store.set = store.set; + set2 = function(it, metadata) { + if (store.has(it)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + store.set(it, metadata); + return metadata; + }; + get2 = function(it) { + return store.get(it) || {}; + }; + has3 = function(it) { + return store.has(it); + }; + } else { + var STATE2 = sharedKey("state"); + hiddenKeys[STATE2] = true; + set2 = function(it, metadata) { + if (hasOwn(it, STATE2)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + createNonEnumerableProperty(it, STATE2, metadata); + return metadata; + }; + get2 = function(it) { + return hasOwn(it, STATE2) ? it[STATE2] : {}; + }; + has3 = function(it) { + return hasOwn(it, STATE2); + }; + } + module2.exports = { + set: set2, + get: get2, + has: has3, + enforce, + getterFor + }; + } + ), + /***/ + 1291: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var trunc = __webpack_require__3(741); + module2.exports = function(argument) { + var number4 = +argument; + return number4 !== number4 || number4 === 0 ? 0 : trunc(number4); + }; + } + ), + /***/ + 1385: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var iteratorClose = __webpack_require__3(9539); + module2.exports = function(iters, kind, value) { + for (var i = iters.length - 1; i >= 0; i--) { + if (iters[i] === void 0) continue; + try { + value = iteratorClose(iters[i].iterator, kind, value); + } catch (error62) { + kind = "throw"; + value = error62; + } + } + if (kind === "throw") throw value; + return value; + }; + } + ), + /***/ + 1548: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var fails = __webpack_require__3(9039); + var V8 = __webpack_require__3(9519); + var ENVIRONMENT = __webpack_require__3(4215); + var structuredClone2 = globalThis2.structuredClone; + module2.exports = !!structuredClone2 && !fails(function() { + if (ENVIRONMENT === "DENO" && V8 > 92 || ENVIRONMENT === "NODE" && V8 > 94 || ENVIRONMENT === "BROWSER" && V8 > 97) return false; + var buffer2 = new ArrayBuffer(8); + var clone3 = structuredClone2(buffer2, { transfer: [buffer2] }); + return buffer2.byteLength !== 0 || clone3.byteLength !== 8; + }); + } + ), + /***/ + 1549: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(6632); + } + ), + /***/ + 1625: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + module2.exports = uncurryThis({}.isPrototypeOf); + } + ), + /***/ + 1689: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var apply = __webpack_require__3(8745); + var slice2 = __webpack_require__3(7680); + var newPromiseCapabilityModule = __webpack_require__3(6043); + var aCallable = __webpack_require__3(9306); + var perform = __webpack_require__3(1103); + var Promise2 = globalThis2.Promise; + var ACCEPT_ARGUMENTS = false; + var FORCED = !Promise2 || !Promise2["try"] || perform(function() { + Promise2["try"](function(argument) { + ACCEPT_ARGUMENTS = argument === 8; + }, 8); + }).error || !ACCEPT_ARGUMENTS; + $({ target: "Promise", stat: true, forced: FORCED }, { + "try": function(callbackfn) { + var args = arguments.length > 1 ? slice2(arguments, 1) : []; + var promiseCapability = newPromiseCapabilityModule.f(this); + var result2 = perform(function() { + return apply(aCallable(callbackfn), void 0, args); + }); + (result2.error ? promiseCapability.reject : promiseCapability.resolve)(result2.value); + return promiseCapability.promise; + } + }); + } + ), + /***/ + 1698: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var union3 = __webpack_require__3(4204); + var setMethodGetKeysBeforeCloning = __webpack_require__3(9835); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var FORCED = !setMethodAcceptSetLike("union") || !setMethodGetKeysBeforeCloning("union"); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + union: union3 + }); + } + ), + /***/ + 1701: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var createIteratorProxy = __webpack_require__3(9462); + var callWithSafeIterationClosing = __webpack_require__3(6319); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var IS_PURE = __webpack_require__3(6395); + var MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("map", function() { + }); + var mapWithoutClosingOnEarlyError = !IS_PURE && !MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("map", TypeError); + var FORCED = IS_PURE || MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR || mapWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var result2 = anObject(call(this.next, iterator)); + var done = this.done = !!result2.done; + if (!done) return callWithSafeIterationClosing(iterator, this.mapper, [result2.value, this.counter++], true); + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + map: function map3(mapper) { + anObject(this); + try { + aCallable(mapper); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (mapWithoutClosingOnEarlyError) return call(mapWithoutClosingOnEarlyError, this, mapper); + return new IteratorProxy(getIteratorDirect(this), { + mapper + }); + } + }); + } + ), + /***/ + 1767: ( + /***/ + (module2) => { + module2.exports = function(obj2) { + return { + iterator: obj2, + next: obj2.next, + done: false + }; + }; + } + ), + /***/ + 1806: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var anObject = __webpack_require__3(8551); + var iterate = __webpack_require__3(2652); + var getIteratorDirect = __webpack_require__3(1767); + var push2 = [].push; + $({ target: "Iterator", proto: true, real: true }, { + toArray: function toArray2() { + var result2 = []; + iterate(getIteratorDirect(anObject(this)), push2, { that: result2, IS_RECORD: true }); + return result2; + } + }); + } + ), + /***/ + 1828: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var hasOwn = __webpack_require__3(9297); + var toIndexedObject = __webpack_require__3(5397); + var indexOf = __webpack_require__3(9617).indexOf; + var hiddenKeys = __webpack_require__3(421); + var push2 = uncurryThis([].push); + module2.exports = function(object3, names) { + var O = toIndexedObject(object3); + var i = 0; + var result2 = []; + var key; + for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push2(result2, key); + while (names.length > i) if (hasOwn(O, key = names[i++])) { + ~indexOf(result2, key) || push2(result2, key); + } + return result2; + }; + } + ), + /***/ + 2106: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var makeBuiltIn = __webpack_require__3(283); + var defineProperty = __webpack_require__3(4913); + module2.exports = function(target, name, descriptor) { + if (descriptor.get) makeBuiltIn(descriptor.get, name, { getter: true }); + if (descriptor.set) makeBuiltIn(descriptor.set, name, { setter: true }); + return defineProperty.f(target, name, descriptor); + }; + } + ), + /***/ + 2140: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var wellKnownSymbol = __webpack_require__3(8227); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var test = {}; + test[TO_STRING_TAG] = "z"; + module2.exports = String(test) === "[object z]"; + } + ), + /***/ + 2195: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var toString2 = uncurryThis({}.toString); + var stringSlice = uncurryThis("".slice); + module2.exports = function(it) { + return stringSlice(toString2(it), 8, -1); + }; + } + ), + /***/ + 2211: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + module2.exports = !fails(function() { + function F() { + } + F.prototype.constructor = null; + return Object.getPrototypeOf(new F()) !== F.prototype; + }); + } + ), + /***/ + 2303: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var Uint8Array2 = globalThis2.Uint8Array; + var SyntaxError2 = globalThis2.SyntaxError; + var parseInt2 = globalThis2.parseInt; + var min2 = Math.min; + var NOT_HEX = /[^\da-f]/i; + var exec = uncurryThis(NOT_HEX.exec); + var stringSlice = uncurryThis("".slice); + module2.exports = function(string4, into) { + var stringLength = string4.length; + if (stringLength % 2 !== 0) throw new SyntaxError2("String should be an even number of characters"); + var maxLength = into ? min2(into.length, stringLength / 2) : stringLength / 2; + var bytes = into || new Uint8Array2(maxLength); + var read = 0; + var written = 0; + while (written < maxLength) { + var hexits = stringSlice(string4, read, read += 2); + if (exec(NOT_HEX, hexits)) throw new SyntaxError2("String should only contain hex characters"); + bytes[written++] = parseInt2(hexits, 16); + } + return { bytes, read }; + }; + } + ), + /***/ + 2360: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var anObject = __webpack_require__3(8551); + var definePropertiesModule = __webpack_require__3(6801); + var enumBugKeys = __webpack_require__3(8727); + var hiddenKeys = __webpack_require__3(421); + var html = __webpack_require__3(397); + var documentCreateElement = __webpack_require__3(4055); + var sharedKey = __webpack_require__3(6119); + var GT = ">"; + var LT = "<"; + var PROTOTYPE = "prototype"; + var SCRIPT = "script"; + var IE_PROTO = sharedKey("IE_PROTO"); + var EmptyConstructor = function() { + }; + var scriptTag = function(content) { + return LT + SCRIPT + GT + content + LT + "/" + SCRIPT + GT; + }; + var NullProtoObjectViaActiveX = function(activeXDocument2) { + activeXDocument2.write(scriptTag("")); + activeXDocument2.close(); + var temp = activeXDocument2.parentWindow.Object; + activeXDocument2 = null; + return temp; + }; + var NullProtoObjectViaIFrame = function() { + var iframe = documentCreateElement("iframe"); + var JS = "java" + SCRIPT + ":"; + var iframeDocument; + iframe.style.display = "none"; + html.appendChild(iframe); + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag("document.F=Object")); + iframeDocument.close(); + return iframeDocument.F; + }; + var activeXDocument; + var NullProtoObject = function() { + try { + activeXDocument = new ActiveXObject("htmlfile"); + } catch (error62) { + } + NullProtoObject = typeof document != "undefined" ? document.domain && activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame() : NullProtoObjectViaActiveX(activeXDocument); + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]]; + return NullProtoObject(); + }; + hiddenKeys[IE_PROTO] = true; + module2.exports = Object.create || function create2(O, Properties) { + var result2; + if (O !== null) { + EmptyConstructor[PROTOTYPE] = anObject(O); + result2 = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE] = null; + result2[IE_PROTO] = O; + } else result2 = NullProtoObject(); + return Properties === void 0 ? result2 : definePropertiesModule.f(result2, Properties); + }; + } + ), + /***/ + 2475: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isSupersetOf = __webpack_require__3(8527); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var INCORRECT = !setMethodAcceptSetLike("isSupersetOf", function(result2) { + return !result2; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isSupersetOf + }); + } + ), + /***/ + 2489: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var createIteratorProxy = __webpack_require__3(9462); + var callWithSafeIterationClosing = __webpack_require__3(6319); + var IS_PURE = __webpack_require__3(6395); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("filter", function() { + }); + var filterWithoutClosingOnEarlyError = !IS_PURE && !FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("filter", TypeError); + var FORCED = IS_PURE || FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR || filterWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var predicate = this.predicate; + var next = this.next; + var result2, done, value; + while (true) { + result2 = anObject(call(next, iterator)); + done = this.done = !!result2.done; + if (done) return; + value = result2.value; + if (callWithSafeIterationClosing(iterator, predicate, [value, this.counter++], true)) return value; + } + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + filter: function filter2(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (filterWithoutClosingOnEarlyError) return call(filterWithoutClosingOnEarlyError, this, predicate); + return new IteratorProxy(getIteratorDirect(this), { + predicate + }); + } + }); + } + ), + /***/ + 2529: ( + /***/ + (module2) => { + module2.exports = function(value, done) { + return { value, done }; + }; + } + ), + /***/ + 2603: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toString2 = __webpack_require__3(655); + module2.exports = function(argument, $default) { + return argument === void 0 ? arguments.length < 2 ? "" : $default : toString2(argument); + }; + } + ), + /***/ + 2652: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var bind = __webpack_require__3(6080); + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var tryToString = __webpack_require__3(6823); + var isArrayIteratorMethod = __webpack_require__3(4209); + var lengthOfArrayLike = __webpack_require__3(6198); + var isPrototypeOf = __webpack_require__3(1625); + var getIterator = __webpack_require__3(81); + var getIteratorMethod = __webpack_require__3(851); + var iteratorClose = __webpack_require__3(9539); + var $TypeError = TypeError; + var Result2 = function(stopped, result2) { + this.stopped = stopped; + this.result = result2; + }; + var ResultPrototype = Result2.prototype; + module2.exports = function(iterable, unboundFunction, options) { + var that = options && options.that; + var AS_ENTRIES = !!(options && options.AS_ENTRIES); + var IS_RECORD = !!(options && options.IS_RECORD); + var IS_ITERATOR = !!(options && options.IS_ITERATOR); + var INTERRUPTED = !!(options && options.INTERRUPTED); + var fn = bind(unboundFunction, that); + var iterator, iterFn, index2, length, result2, next, step; + var stop = function(condition) { + if (iterator) iteratorClose(iterator, "normal"); + return new Result2(true, condition); + }; + var callFn = function(value) { + if (AS_ENTRIES) { + anObject(value); + return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]); + } + return INTERRUPTED ? fn(value, stop) : fn(value); + }; + if (IS_RECORD) { + iterator = iterable.iterator; + } else if (IS_ITERATOR) { + iterator = iterable; + } else { + iterFn = getIteratorMethod(iterable); + if (!iterFn) throw new $TypeError(tryToString(iterable) + " is not iterable"); + if (isArrayIteratorMethod(iterFn)) { + for (index2 = 0, length = lengthOfArrayLike(iterable); length > index2; index2++) { + result2 = callFn(iterable[index2]); + if (result2 && isPrototypeOf(ResultPrototype, result2)) return result2; + } + return new Result2(false); + } + iterator = getIterator(iterable, iterFn); + } + next = IS_RECORD ? iterable.next : iterator.next; + while (!(step = call(next, iterator)).done) { + try { + result2 = callFn(step.value); + } catch (error62) { + iteratorClose(iterator, "throw", error62); + } + if (typeof result2 == "object" && result2 && isPrototypeOf(ResultPrototype, result2)) return result2; + } + return new Result2(false); + }; + } + ), + /***/ + 2777: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var isObject5 = __webpack_require__3(34); + var isSymbol = __webpack_require__3(757); + var getMethod = __webpack_require__3(5966); + var ordinaryToPrimitive = __webpack_require__3(4270); + var wellKnownSymbol = __webpack_require__3(8227); + var $TypeError = TypeError; + var TO_PRIMITIVE = wellKnownSymbol("toPrimitive"); + module2.exports = function(input2, pref) { + if (!isObject5(input2) || isSymbol(input2)) return input2; + var exoticToPrim = getMethod(input2, TO_PRIMITIVE); + var result2; + if (exoticToPrim) { + if (pref === void 0) pref = "default"; + result2 = call(exoticToPrim, input2, pref); + if (!isObject5(result2) || isSymbol(result2)) return result2; + throw new $TypeError("Can't convert object to primitive value"); + } + if (pref === void 0) pref = "number"; + return ordinaryToPrimitive(input2, pref); + }; + } + ), + /***/ + 2787: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var hasOwn = __webpack_require__3(9297); + var isCallable = __webpack_require__3(4901); + var toObject = __webpack_require__3(8981); + var sharedKey = __webpack_require__3(6119); + var CORRECT_PROTOTYPE_GETTER = __webpack_require__3(2211); + var IE_PROTO = sharedKey("IE_PROTO"); + var $Object = Object; + var ObjectPrototype = $Object.prototype; + module2.exports = CORRECT_PROTOTYPE_GETTER ? $Object.getPrototypeOf : function(O) { + var object3 = toObject(O); + if (hasOwn(object3, IE_PROTO)) return object3[IE_PROTO]; + var constructor = object3.constructor; + if (isCallable(constructor) && object3 instanceof constructor) { + return constructor.prototype; + } + return object3 instanceof $Object ? ObjectPrototype : null; + }; + } + ), + /***/ + 2796: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); + var replacement = /#|\.prototype\./; + var isForced = function(feature, detection) { + var value = data[normalize(feature)]; + return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection; + }; + var normalize = isForced.normalize = function(string4) { + return String(string4).replace(replacement, ".").toLowerCase(); + }; + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = "N"; + var POLYFILL = isForced.POLYFILL = "P"; + module2.exports = isForced; + } + ), + /***/ + 2804: ( + /***/ + (module2) => { + var commonAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var base64Alphabet = commonAlphabet + "+/"; + var base64UrlAlphabet = commonAlphabet + "-_"; + var inverse = function(characters) { + var result2 = {}; + var index2 = 0; + for (; index2 < 64; index2++) result2[characters.charAt(index2)] = index2; + return result2; + }; + module2.exports = { + i2c: base64Alphabet, + c2i: inverse(base64Alphabet), + i2cUrl: base64UrlAlphabet, + c2iUrl: inverse(base64UrlAlphabet) + }; + } + ), + /***/ + 2812: ( + /***/ + (module2) => { + var $TypeError = TypeError; + module2.exports = function(passed, required2) { + if (passed < required2) throw new $TypeError("Not enough arguments"); + return passed; + }; + } + ), + /***/ + 2839: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var navigator2 = globalThis2.navigator; + var userAgent = navigator2 && navigator2.userAgent; + module2.exports = userAgent ? String(userAgent) : ""; + } + ), + /***/ + 2967: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThisAccessor = __webpack_require__3(6706); + var isObject5 = __webpack_require__3(34); + var requireObjectCoercible = __webpack_require__3(7750); + var aPossiblePrototype = __webpack_require__3(3506); + module2.exports = Object.setPrototypeOf || ("__proto__" in {} ? function() { + var CORRECT_SETTER = false; + var test = {}; + var setter; + try { + setter = uncurryThisAccessor(Object.prototype, "__proto__", "set"); + setter(test, []); + CORRECT_SETTER = test instanceof Array; + } catch (error62) { + } + return function setPrototypeOf(O, proto) { + requireObjectCoercible(O); + aPossiblePrototype(proto); + if (!isObject5(O)) return O; + if (CORRECT_SETTER) setter(O, proto); + else O.__proto__ = proto; + return O; + }; + }() : void 0); + } + ), + /***/ + 3068: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var uncurryThis = __webpack_require__3(9504); + var iterate = __webpack_require__3(2652); + var $RangeError = RangeError; + var $TypeError = TypeError; + var $Infinity = Infinity; + var $NaN = NaN; + var abs = Math.abs; + var pow = Math.pow; + var push2 = uncurryThis([].push); + var POW_2_1023 = pow(2, 1023); + var MAX_SAFE_INTEGER = pow(2, 53) - 1; + var MAX_DOUBLE = Number.MAX_VALUE; + var MAX_ULP = pow(2, 971); + var NOT_A_NUMBER = {}; + var MINUS_INFINITY = {}; + var PLUS_INFINITY = {}; + var MINUS_ZERO = {}; + var FINITE = {}; + var twosum = function(x, y) { + var hi = x + y; + var lo = y - (hi - x); + return { hi, lo }; + }; + $({ target: "Math", stat: true }, { + // eslint-disable-next-line max-statements -- ok + sumPrecise: function sumPrecise(items) { + var numbers = []; + var count = 0; + var state = MINUS_ZERO; + iterate(items, function(n2) { + if (++count >= MAX_SAFE_INTEGER) throw new $RangeError("Maximum allowed index exceeded"); + if (typeof n2 != "number") throw new $TypeError("Value is not a number"); + if (state !== NOT_A_NUMBER) { + if (n2 !== n2) state = NOT_A_NUMBER; + else if (n2 === $Infinity) state = state === MINUS_INFINITY ? NOT_A_NUMBER : PLUS_INFINITY; + else if (n2 === -$Infinity) state = state === PLUS_INFINITY ? NOT_A_NUMBER : MINUS_INFINITY; + else if ((n2 !== 0 || 1 / n2 === $Infinity) && (state === MINUS_ZERO || state === FINITE)) { + state = FINITE; + push2(numbers, n2); + } + } + }); + switch (state) { + case NOT_A_NUMBER: + return $NaN; + case MINUS_INFINITY: + return -$Infinity; + case PLUS_INFINITY: + return $Infinity; + case MINUS_ZERO: + return -0; + } + var partials = []; + var overflow = 0; + var x, y, sum, hi, lo, tmp; + for (var i = 0; i < numbers.length; i++) { + x = numbers[i]; + var actuallyUsedPartials = 0; + for (var j = 0; j < partials.length; j++) { + y = partials[j]; + if (abs(x) < abs(y)) { + tmp = x; + x = y; + y = tmp; + } + sum = twosum(x, y); + hi = sum.hi; + lo = sum.lo; + if (abs(hi) === $Infinity) { + var sign = hi === $Infinity ? 1 : -1; + overflow += sign; + x = x - sign * POW_2_1023 - sign * POW_2_1023; + if (abs(x) < abs(y)) { + tmp = x; + x = y; + y = tmp; + } + sum = twosum(x, y); + hi = sum.hi; + lo = sum.lo; + } + if (lo !== 0) partials[actuallyUsedPartials++] = lo; + x = hi; + } + partials.length = actuallyUsedPartials; + if (x !== 0) push2(partials, x); + } + var n = partials.length - 1; + hi = 0; + lo = 0; + if (overflow !== 0) { + var next = n >= 0 ? partials[n] : 0; + n--; + if (abs(overflow) > 1 || overflow > 0 && next > 0 || overflow < 0 && next < 0) { + return overflow > 0 ? $Infinity : -$Infinity; + } + sum = twosum(overflow * POW_2_1023, next / 2); + hi = sum.hi; + lo = sum.lo; + lo *= 2; + if (abs(2 * hi) === $Infinity) { + if (hi > 0) { + return hi === POW_2_1023 && lo === -(MAX_ULP / 2) && n >= 0 && partials[n] < 0 ? MAX_DOUBLE : $Infinity; + } + return hi === -POW_2_1023 && lo === MAX_ULP / 2 && n >= 0 && partials[n] > 0 ? -MAX_DOUBLE : -$Infinity; + } + if (lo !== 0) { + partials[++n] = lo; + lo = 0; + } + hi *= 2; + } + while (n >= 0) { + sum = twosum(hi, partials[n--]); + hi = sum.hi; + lo = sum.lo; + if (lo !== 0) break; + } + if (n >= 0 && (lo < 0 && partials[n] < 0 || lo > 0 && partials[n] > 0)) { + y = lo * 2; + x = hi + y; + if (y === x - hi) hi = x; + } + return hi; + } + }); + } + ), + /***/ + 3167: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var setPrototypeOf = __webpack_require__3(2967); + module2.exports = function($this, dummy, Wrapper) { + var NewTarget, NewTargetPrototype; + if ( + // it can work only with native `setPrototypeOf` + setPrototypeOf && // we haven't completely correct pre-ES6 way for getting `new.target`, so use this + isCallable(NewTarget = dummy.constructor) && NewTarget !== Wrapper && isObject5(NewTargetPrototype = NewTarget.prototype) && NewTargetPrototype !== Wrapper.prototype + ) setPrototypeOf($this, NewTargetPrototype); + return $this; + }; + } + ), + /***/ + 3238: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var NATIVE_ARRAY_BUFFER = __webpack_require__3(7811); + var arrayBufferByteLength = __webpack_require__3(7394); + var DataView2 = globalThis2.DataView; + module2.exports = function(O) { + if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false; + try { + new DataView2(O); + return false; + } catch (error62) { + return true; + } + }; + } + ), + /***/ + 3392: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var id = 0; + var postfix = Math.random(); + var toString2 = uncurryThis(1.1.toString); + module2.exports = function(key) { + return "Symbol(" + (key === void 0 ? "" : key) + ")_" + toString2(++id + postfix, 36); + }; + } + ), + /***/ + 3440: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var clone3 = __webpack_require__3(9286); + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); + var has3 = SetHelpers.has; + var remove = SetHelpers.remove; + module2.exports = function difference(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + var result2 = clone3(O); + if (size3(O) <= otherRec.size) iterateSet(O, function(e) { + if (otherRec.includes(e)) remove(result2, e); + }); + else iterateSimple(otherRec.getIterator(), function(e) { + if (has3(result2, e)) remove(result2, e); + }); + return result2; + }; + } + ), + /***/ + 3463: ( + /***/ + (module2) => { + var $TypeError = TypeError; + module2.exports = function(argument) { + if (typeof argument == "string") return argument; + throw new $TypeError("Argument is not a string"); + }; + } + ), + /***/ + 3506: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isPossiblePrototype = __webpack_require__3(3925); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isPossiblePrototype(argument)) return argument; + throw new $TypeError("Can't set " + $String(argument) + " as a prototype"); + }; + } + ), + /***/ + 3579: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var someWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("some", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: someWithoutClosingOnEarlyError }, { + some: function some2(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (someWithoutClosingOnEarlyError) return call(someWithoutClosingOnEarlyError, this, predicate); + var record2 = getIteratorDirect(this); + var counter = 0; + return iterate(record2, function(value, stop) { + if (predicate(value, counter++)) return stop(); + }, { IS_RECORD: true, INTERRUPTED: true }).stopped; + } + }); + } + ), + /***/ + 3611: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var defineBuiltInAccessor = __webpack_require__3(2106); + var DESCRIPTORS = __webpack_require__3(3724); + var $TypeError = TypeError; + var defineProperty = Object.defineProperty; + var INCORRECT_VALUE = globalThis2.self !== globalThis2; + try { + if (DESCRIPTORS) { + var descriptor = Object.getOwnPropertyDescriptor(globalThis2, "self"); + if (INCORRECT_VALUE || !descriptor || !descriptor.get || !descriptor.enumerable) { + defineBuiltInAccessor(globalThis2, "self", { + get: function self2() { + return globalThis2; + }, + set: function self2(value) { + if (this !== globalThis2) throw new $TypeError("Illegal invocation"); + defineProperty(globalThis2, "self", { + value, + writable: true, + configurable: true, + enumerable: true + }); + }, + configurable: true, + enumerable: true + }); + } + } else $({ global: true, simple: true, forced: INCORRECT_VALUE }, { + self: globalThis2 + }); + } catch (error62) { + } + } + ), + /***/ + 3650: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var clone3 = __webpack_require__3(9286); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); + var add = SetHelpers.add; + var has3 = SetHelpers.has; + var remove = SetHelpers.remove; + module2.exports = function symmetricDifference(other) { + var O = aSet(this); + var keysIter = getSetRecord(other).getIterator(); + var result2 = clone3(O); + iterateSimple(keysIter, function(e) { + if (has3(O, e)) remove(result2, e); + else add(result2, e); + }); + return result2; + }; + } + ), + /***/ + 3706: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var isCallable = __webpack_require__3(4901); + var store = __webpack_require__3(7629); + var functionToString = uncurryThis(Function.toString); + if (!isCallable(store.inspectSource)) { + store.inspectSource = function(it) { + return functionToString(it); + }; + } + module2.exports = store.inspectSource; + } + ), + /***/ + 3717: ( + /***/ + (__unused_webpack_module, exports2) => { + exports2.f = Object.getOwnPropertySymbols; + } + ), + /***/ + 3724: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + module2.exports = !fails(function() { + return Object.defineProperty({}, 1, { get: function() { + return 7; + } })[1] !== 7; + }); + } + ), + /***/ + 3789: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var call = __webpack_require__3(9565); + var toIntegerOrInfinity = __webpack_require__3(1291); + var getIteratorDirect = __webpack_require__3(1767); + var INVALID_SIZE = "Invalid size"; + var $RangeError = RangeError; + var $TypeError = TypeError; + var max2 = Math.max; + var SetRecord = function(set2, intSize) { + this.set = set2; + this.size = max2(intSize, 0); + this.has = aCallable(set2.has); + this.keys = aCallable(set2.keys); + }; + SetRecord.prototype = { + getIterator: function() { + return getIteratorDirect(anObject(call(this.keys, this.set))); + }, + includes: function(it) { + return call(this.has, this.set, it); + } + }; + module2.exports = function(obj2) { + anObject(obj2); + var numSize = +obj2.size; + if (numSize !== numSize) throw new $TypeError(INVALID_SIZE); + var intSize = toIntegerOrInfinity(numSize); + if (intSize < 0) throw new $RangeError(INVALID_SIZE); + return new SetRecord(obj2, intSize); + }; + } + ), + /***/ + 3838: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var size3 = __webpack_require__3(5170); + var iterate = __webpack_require__3(8469); + var getSetRecord = __webpack_require__3(3789); + module2.exports = function isSubsetOf(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size3(O) > otherRec.size) return false; + return iterate(O, function(e) { + if (!otherRec.includes(e)) return false; + }, true) !== false; + }; + } + ), + /***/ + 3853: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isDisjointFrom = __webpack_require__3(4449); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var INCORRECT = !setMethodAcceptSetLike("isDisjointFrom", function(result2) { + return !result2; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isDisjointFrom + }); + } + ), + /***/ + 3925: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); + module2.exports = function(argument) { + return isObject5(argument) || argument === null; + }; + } + ), + /***/ + 3972: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (argument === void 0 || isObject5(argument)) return argument; + throw new $TypeError($String(argument) + " is not an object or undefined"); + }; + } + ), + /***/ + 4055: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isObject5 = __webpack_require__3(34); + var document2 = globalThis2.document; + var EXISTS = isObject5(document2) && isObject5(document2.createElement); + module2.exports = function(it) { + return EXISTS ? document2.createElement(it) : {}; + }; + } + ), + /***/ + 4114: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var toObject = __webpack_require__3(8981); + var lengthOfArrayLike = __webpack_require__3(6198); + var setArrayLength = __webpack_require__3(4527); + var doesNotExceedSafeInteger = __webpack_require__3(6837); + var fails = __webpack_require__3(9039); + var INCORRECT_TO_LENGTH = fails(function() { + return [].push.call({ length: 4294967296 }, 1) !== 4294967297; + }); + var properErrorOnNonWritableLength = function() { + try { + Object.defineProperty([], "length", { writable: false }).push(); + } catch (error62) { + return error62 instanceof TypeError; + } + }; + var FORCED = INCORRECT_TO_LENGTH || !properErrorOnNonWritableLength(); + $({ target: "Array", proto: true, arity: 1, forced: FORCED }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + push: function push2(item) { + var O = toObject(this); + var len = lengthOfArrayLike(O); + var argCount = arguments.length; + doesNotExceedSafeInteger(len + argCount); + for (var i = 0; i < argCount; i++) { + O[len] = arguments[i]; + len++; + } + setArrayLength(O, len); + return len; + } + }); + } + ), + /***/ + 4117: ( + /***/ + (module2) => { + module2.exports = function(it) { + return it === null || it === void 0; + }; + } + ), + /***/ + 4154: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); + var $TypeError = TypeError; + module2.exports = function(argument) { + if (classof(argument) === "Uint8Array") return argument; + throw new $TypeError("Argument is not an Uint8Array"); + }; + } + ), + /***/ + 4204: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var add = __webpack_require__3(4402).add; + var clone3 = __webpack_require__3(9286); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); + module2.exports = function union3(other) { + var O = aSet(this); + var keysIter = getSetRecord(other).getIterator(); + var result2 = clone3(O); + iterateSimple(keysIter, function(it) { + add(result2, it); + }); + return result2; + }; + } + ), + /***/ + 4209: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var wellKnownSymbol = __webpack_require__3(8227); + var Iterators = __webpack_require__3(6269); + var ITERATOR = wellKnownSymbol("iterator"); + var ArrayPrototype = Array.prototype; + module2.exports = function(it) { + return it !== void 0 && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it); + }; + } + ), + /***/ + 4215: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var userAgent = __webpack_require__3(2839); + var classof = __webpack_require__3(2195); + var userAgentStartsWith = function(string4) { + return userAgent.slice(0, string4.length) === string4; + }; + module2.exports = function() { + if (userAgentStartsWith("Bun/")) return "BUN"; + if (userAgentStartsWith("Cloudflare-Workers")) return "CLOUDFLARE"; + if (userAgentStartsWith("Deno/")) return "DENO"; + if (userAgentStartsWith("Node.js/")) return "NODE"; + if (globalThis2.Bun && typeof Bun.version == "string") return "BUN"; + if (globalThis2.Deno && typeof Deno.version == "object") return "DENO"; + if (classof(globalThis2.process) === "process") return "NODE"; + if (globalThis2.window && globalThis2.document) return "BROWSER"; + return "REST"; + }(); + } + ), + /***/ + 4226: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var aString = __webpack_require__3(3463); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var $fromHex = __webpack_require__3(2303); + if (globalThis2.Uint8Array) $({ target: "Uint8Array", proto: true }, { + setFromHex: function setFromHex(string4) { + anUint8Array(this); + aString(string4); + notDetached(this.buffer); + var read = $fromHex(string4, this).read; + return { read, written: read / 2 }; + } + }); + } + ), + /***/ + 4235: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(3068); + } + ), + /***/ + 4270: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var $TypeError = TypeError; + module2.exports = function(input2, pref) { + var fn, val; + if (pref === "string" && isCallable(fn = input2.toString) && !isObject5(val = call(fn, input2))) return val; + if (isCallable(fn = input2.valueOf) && !isObject5(val = call(fn, input2))) return val; + if (pref !== "string" && isCallable(fn = input2.toString) && !isObject5(val = call(fn, input2))) return val; + throw new $TypeError("Can't convert object to primitive value"); + }; + } + ), + /***/ + 4376: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(2195); + module2.exports = Array.isArray || function isArray(argument) { + return classof(argument) === "Array"; + }; + } + ), + /***/ + 4402: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var SetPrototype = Set.prototype; + module2.exports = { + // eslint-disable-next-line es/no-set -- safe + Set, + add: uncurryThis(SetPrototype.add), + has: uncurryThis(SetPrototype.has), + remove: uncurryThis(SetPrototype["delete"]), + proto: SetPrototype + }; + } + ), + /***/ + 4449: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var has3 = __webpack_require__3(4402).has; + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); + var iteratorClose = __webpack_require__3(9539); + module2.exports = function isDisjointFrom(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size3(O) <= otherRec.size) return iterateSet(O, function(e) { + if (otherRec.includes(e)) return false; + }, true) !== false; + var iterator = otherRec.getIterator(); + return iterateSimple(iterator, function(e) { + if (has3(O, e)) return iteratorClose(iterator, "normal", false); + }) !== false; + }; + } + ), + /***/ + 4483: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var getBuiltInNodeModule = __webpack_require__3(9429); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__3(1548); + var structuredClone2 = globalThis2.structuredClone; + var $ArrayBuffer = globalThis2.ArrayBuffer; + var $MessageChannel = globalThis2.MessageChannel; + var detach = false; + var WorkerThreads, channel, buffer2, $detach; + if (PROPER_STRUCTURED_CLONE_TRANSFER) { + detach = function(transferable) { + structuredClone2(transferable, { transfer: [transferable] }); + }; + } else if ($ArrayBuffer) try { + if (!$MessageChannel) { + WorkerThreads = getBuiltInNodeModule("worker_threads"); + if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel; + } + if ($MessageChannel) { + channel = new $MessageChannel(); + buffer2 = new $ArrayBuffer(2); + $detach = function(transferable) { + channel.port1.postMessage(null, [transferable]); + }; + if (buffer2.byteLength === 2) { + $detach(buffer2); + if (buffer2.byteLength === 0) detach = $detach; + } + } + } catch (error62) { + } + module2.exports = detach; + } + ), + /***/ + 4495: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var V8_VERSION = __webpack_require__3(9519); + var fails = __webpack_require__3(9039); + var globalThis2 = __webpack_require__3(4576); + var $String = globalThis2.String; + module2.exports = !!Object.getOwnPropertySymbols && !fails(function() { + var symbol2 = Symbol("symbol detection"); + return !$String(symbol2) || !(Object(symbol2) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + !Symbol.sham && V8_VERSION && V8_VERSION < 41; + }); + } + ), + /***/ + 4527: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var isArray = __webpack_require__3(4376); + var $TypeError = TypeError; + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function() { + if (this !== void 0) return true; + try { + Object.defineProperty([], "length", { writable: false }).length = 1; + } catch (error62) { + return error62 instanceof TypeError; + } + }(); + module2.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function(O, length) { + if (isArray(O) && !getOwnPropertyDescriptor(O, "length").writable) { + throw new $TypeError("Cannot set read only .length"); + } + return O.length = length; + } : function(O, length) { + return O.length = length; + }; + } + ), + /***/ + 4549: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + module2.exports = function(METHOD_NAME, ExpectedError) { + var Iterator2 = globalThis2.Iterator; + var IteratorPrototype = Iterator2 && Iterator2.prototype; + var method = IteratorPrototype && IteratorPrototype[METHOD_NAME]; + var CLOSED = false; + if (method) try { + method.call({ + next: function() { + return { done: true }; + }, + "return": function() { + CLOSED = true; + } + }, -1); + } catch (error62) { + if (!(error62 instanceof ExpectedError)) CLOSED = false; + } + if (!CLOSED) return method; + }; + } + ), + /***/ + 4576: ( + /***/ + function(module2) { + var check3 = function(it) { + return it && it.Math === Math && it; + }; + module2.exports = // eslint-disable-next-line es/no-global-this -- safe + check3(typeof globalThis == "object" && globalThis) || check3(typeof window == "object" && window) || // eslint-disable-next-line no-restricted-globals -- safe + check3(typeof self == "object" && self) || check3(typeof global == "object" && global) || check3(typeof this == "object" && this) || // eslint-disable-next-line no-new-func -- fallback + /* @__PURE__ */ function() { + return this; + }() || Function("return this")(); + } + ), + /***/ + 4603: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); + var uncurryThis = __webpack_require__3(9504); + var toString2 = __webpack_require__3(655); + var validateArgumentsLength = __webpack_require__3(2812); + var $URLSearchParams = URLSearchParams; + var URLSearchParamsPrototype = $URLSearchParams.prototype; + var append = uncurryThis(URLSearchParamsPrototype.append); + var $delete = uncurryThis(URLSearchParamsPrototype["delete"]); + var forEach = uncurryThis(URLSearchParamsPrototype.forEach); + var push2 = uncurryThis([].push); + var params = new $URLSearchParams("a=1&a=2&b=3"); + params["delete"]("a", 1); + params["delete"]("b", void 0); + if (params + "" !== "a=2") { + defineBuiltIn(URLSearchParamsPrototype, "delete", function(name) { + var length = arguments.length; + var $value = length < 2 ? void 0 : arguments[1]; + if (length && $value === void 0) return $delete(this, name); + var entries = []; + forEach(this, function(v, k) { + push2(entries, { key: k, value: v }); + }); + validateArgumentsLength(length, 1); + var key = toString2(name); + var value = toString2($value); + var index2 = 0; + var dindex = 0; + var found = false; + var entriesLength = entries.length; + var entry; + while (index2 < entriesLength) { + entry = entries[index2++]; + if (found || entry.key === key) { + found = true; + $delete(this, entry.key); + } else dindex++; + } + while (dindex < entriesLength) { + entry = entries[dindex++]; + if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value); + } + }, { enumerable: true, unsafe: true }); + } + } + ), + /***/ + 4628: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var newPromiseCapabilityModule = __webpack_require__3(6043); + $({ target: "Promise", stat: true }, { + withResolvers: function withResolvers() { + var promiseCapability = newPromiseCapabilityModule.f(this); + return { + promise: promiseCapability.promise, + resolve: promiseCapability.resolve, + reject: promiseCapability.reject + }; + } + }); + } + ), + /***/ + 4644: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_ARRAY_BUFFER = __webpack_require__3(7811); + var DESCRIPTORS = __webpack_require__3(3724); + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var hasOwn = __webpack_require__3(9297); + var classof = __webpack_require__3(6955); + var tryToString = __webpack_require__3(6823); + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIn = __webpack_require__3(6840); + var defineBuiltInAccessor = __webpack_require__3(2106); + var isPrototypeOf = __webpack_require__3(1625); + var getPrototypeOf = __webpack_require__3(2787); + var setPrototypeOf = __webpack_require__3(2967); + var wellKnownSymbol = __webpack_require__3(8227); + var uid3 = __webpack_require__3(3392); + var InternalStateModule = __webpack_require__3(1181); + var enforceInternalState = InternalStateModule.enforce; + var getInternalState = InternalStateModule.get; + var Int8Array2 = globalThis2.Int8Array; + var Int8ArrayPrototype = Int8Array2 && Int8Array2.prototype; + var Uint8ClampedArray2 = globalThis2.Uint8ClampedArray; + var Uint8ClampedArrayPrototype = Uint8ClampedArray2 && Uint8ClampedArray2.prototype; + var TypedArray = Int8Array2 && getPrototypeOf(Int8Array2); + var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf(Int8ArrayPrototype); + var ObjectPrototype = Object.prototype; + var TypeError2 = globalThis2.TypeError; + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var TYPED_ARRAY_TAG = uid3("TYPED_ARRAY_TAG"); + var TYPED_ARRAY_CONSTRUCTOR = "TypedArrayConstructor"; + var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(globalThis2.opera) !== "Opera"; + var TYPED_ARRAY_TAG_REQUIRED = false; + var NAME, Constructor, Prototype; + var TypedArrayConstructorsList = { + Int8Array: 1, + Uint8Array: 1, + Uint8ClampedArray: 1, + Int16Array: 2, + Uint16Array: 2, + Int32Array: 4, + Uint32Array: 4, + Float32Array: 4, + Float64Array: 8 + }; + var BigIntArrayConstructorsList = { + BigInt64Array: 8, + BigUint64Array: 8 + }; + var isView = function isView2(it) { + if (!isObject5(it)) return false; + var klass = classof(it); + return klass === "DataView" || hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass); + }; + var getTypedArrayConstructor = function(it) { + var proto = getPrototypeOf(it); + if (!isObject5(proto)) return; + var state = getInternalState(proto); + return state && hasOwn(state, TYPED_ARRAY_CONSTRUCTOR) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto); + }; + var isTypedArray2 = function(it) { + if (!isObject5(it)) return false; + var klass = classof(it); + return hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass); + }; + var aTypedArray = function(it) { + if (isTypedArray2(it)) return it; + throw new TypeError2("Target is not a typed array"); + }; + var aTypedArrayConstructor = function(C) { + if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C; + throw new TypeError2(tryToString(C) + " is not a typed array constructor"); + }; + var exportTypedArrayMethod = function(KEY, property2, forced, options) { + if (!DESCRIPTORS) return; + if (forced) for (var ARRAY in TypedArrayConstructorsList) { + var TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try { + delete TypedArrayConstructor.prototype[KEY]; + } catch (error62) { + try { + TypedArrayConstructor.prototype[KEY] = property2; + } catch (error210) { + } + } + } + if (!TypedArrayPrototype[KEY] || forced) { + defineBuiltIn(TypedArrayPrototype, KEY, forced ? property2 : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property2, options); + } + }; + var exportTypedArrayStaticMethod = function(KEY, property2, forced) { + var ARRAY, TypedArrayConstructor; + if (!DESCRIPTORS) return; + if (setPrototypeOf) { + if (forced) for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try { + delete TypedArrayConstructor[KEY]; + } catch (error62) { + } + } + if (!TypedArray[KEY] || forced) { + try { + return defineBuiltIn(TypedArray, KEY, forced ? property2 : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property2); + } catch (error62) { + } + } else return; + } + for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) { + defineBuiltIn(TypedArrayConstructor, KEY, property2); + } + } + }; + for (NAME in TypedArrayConstructorsList) { + Constructor = globalThis2[NAME]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + else NATIVE_ARRAY_BUFFER_VIEWS = false; + } + for (NAME in BigIntArrayConstructorsList) { + Constructor = globalThis2[NAME]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + } + if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) { + TypedArray = function TypedArray2() { + throw new TypeError2("Incorrect invocation"); + }; + if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { + if (globalThis2[NAME]) setPrototypeOf(globalThis2[NAME], TypedArray); + } + } + if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) { + TypedArrayPrototype = TypedArray.prototype; + if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { + if (globalThis2[NAME]) setPrototypeOf(globalThis2[NAME].prototype, TypedArrayPrototype); + } + } + if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) { + setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype); + } + if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) { + TYPED_ARRAY_TAG_REQUIRED = true; + defineBuiltInAccessor(TypedArrayPrototype, TO_STRING_TAG, { + configurable: true, + get: function() { + return isObject5(this) ? this[TYPED_ARRAY_TAG] : void 0; + } + }); + for (NAME in TypedArrayConstructorsList) if (globalThis2[NAME]) { + createNonEnumerableProperty(globalThis2[NAME], TYPED_ARRAY_TAG, NAME); + } + } + module2.exports = { + NATIVE_ARRAY_BUFFER_VIEWS, + TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG, + aTypedArray, + aTypedArrayConstructor, + exportTypedArrayMethod, + exportTypedArrayStaticMethod, + getTypedArrayConstructor, + isView, + isTypedArray: isTypedArray2, + TypedArray, + TypedArrayPrototype + }; + } + ), + /***/ + 4659: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var definePropertyModule = __webpack_require__3(4913); + var createPropertyDescriptor = __webpack_require__3(6980); + module2.exports = function(object3, key, value) { + if (DESCRIPTORS) definePropertyModule.f(object3, key, createPropertyDescriptor(0, value)); + else object3[key] = value; + }; + } + ), + /***/ + 4901: ( + /***/ + (module2) => { + var documentAll = typeof document == "object" && document.all; + module2.exports = typeof documentAll == "undefined" && documentAll !== void 0 ? function(argument) { + return typeof argument == "function" || argument === documentAll; + } : function(argument) { + return typeof argument == "function"; + }; + } + ), + /***/ + 4913: ( + /***/ + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var IE8_DOM_DEFINE = __webpack_require__3(5917); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__3(8686); + var anObject = __webpack_require__3(8551); + var toPropertyKey = __webpack_require__3(6969); + var $TypeError = TypeError; + var $defineProperty = Object.defineProperty; + var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var ENUMERABLE = "enumerable"; + var CONFIGURABLE = "configurable"; + var WRITABLE = "writable"; + exports2.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P2, Attributes2) { + anObject(O); + P2 = toPropertyKey(P2); + anObject(Attributes2); + if (typeof O === "function" && P2 === "prototype" && "value" in Attributes2 && WRITABLE in Attributes2 && !Attributes2[WRITABLE]) { + var current = $getOwnPropertyDescriptor(O, P2); + if (current && current[WRITABLE]) { + O[P2] = Attributes2.value; + Attributes2 = { + configurable: CONFIGURABLE in Attributes2 ? Attributes2[CONFIGURABLE] : current[CONFIGURABLE], + enumerable: ENUMERABLE in Attributes2 ? Attributes2[ENUMERABLE] : current[ENUMERABLE], + writable: false + }; + } + } + return $defineProperty(O, P2, Attributes2); + } : $defineProperty : function defineProperty(O, P2, Attributes2) { + anObject(O); + P2 = toPropertyKey(P2); + anObject(Attributes2); + if (IE8_DOM_DEFINE) try { + return $defineProperty(O, P2, Attributes2); + } catch (error62) { + } + if ("get" in Attributes2 || "set" in Attributes2) throw new $TypeError("Accessors not supported"); + if ("value" in Attributes2) O[P2] = Attributes2.value; + return O; + }; + } + ), + /***/ + 4916: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + var createSetLike = function(size3) { + return { + size: size3, + has: function() { + return false; + }, + keys: function() { + return { + next: function() { + return { done: true }; + } + }; + } + }; + }; + var createSetLikeWithInfinitySize = function(size3) { + return { + size: size3, + has: function() { + return true; + }, + keys: function() { + throw new Error("e"); + } + }; + }; + module2.exports = function(name, callback) { + var Set2 = getBuiltIn("Set"); + try { + new Set2()[name](createSetLike(0)); + try { + new Set2()[name](createSetLike(-1)); + return false; + } catch (error210) { + if (!callback) return true; + try { + new Set2()[name](createSetLikeWithInfinitySize(-Infinity)); + return false; + } catch (error62) { + var set2 = new Set2(); + set2.add(1); + set2.add(2); + return callback(set2[name](createSetLikeWithInfinitySize(Infinity))); + } + } + } catch (error62) { + return false; + } + }; + } + ), + /***/ + 4979: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var getBuiltIn = __webpack_require__3(7751); + var createPropertyDescriptor = __webpack_require__3(6980); + var defineProperty = __webpack_require__3(4913).f; + var hasOwn = __webpack_require__3(9297); + var anInstance = __webpack_require__3(679); + var inheritIfRequired = __webpack_require__3(3167); + var normalizeStringArgument = __webpack_require__3(2603); + var DOMExceptionConstants = __webpack_require__3(5002); + var clearErrorStack = __webpack_require__3(8574); + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); + var DOM_EXCEPTION = "DOMException"; + var Error2 = getBuiltIn("Error"); + var NativeDOMException = getBuiltIn(DOM_EXCEPTION); + var $DOMException = function DOMException() { + anInstance(this, DOMExceptionPrototype); + var argumentsLength = arguments.length; + var message2 = normalizeStringArgument(argumentsLength < 1 ? void 0 : arguments[0]); + var name = normalizeStringArgument(argumentsLength < 2 ? void 0 : arguments[1], "Error"); + var that = new NativeDOMException(message2, name); + var error62 = new Error2(message2); + error62.name = DOM_EXCEPTION; + defineProperty(that, "stack", createPropertyDescriptor(1, clearErrorStack(error62.stack, 1))); + inheritIfRequired(that, this, $DOMException); + return that; + }; + var DOMExceptionPrototype = $DOMException.prototype = NativeDOMException.prototype; + var ERROR_HAS_STACK = "stack" in new Error2(DOM_EXCEPTION); + var DOM_EXCEPTION_HAS_STACK = "stack" in new NativeDOMException(1, 2); + var descriptor = NativeDOMException && DESCRIPTORS && Object.getOwnPropertyDescriptor(globalThis2, DOM_EXCEPTION); + var BUGGY_DESCRIPTOR = !!descriptor && !(descriptor.writable && descriptor.configurable); + var FORCED_CONSTRUCTOR = ERROR_HAS_STACK && !BUGGY_DESCRIPTOR && !DOM_EXCEPTION_HAS_STACK; + $({ global: true, constructor: true, forced: IS_PURE || FORCED_CONSTRUCTOR }, { + // TODO: fix export logic + DOMException: FORCED_CONSTRUCTOR ? $DOMException : NativeDOMException + }); + var PolyfilledDOMException = getBuiltIn(DOM_EXCEPTION); + var PolyfilledDOMExceptionPrototype = PolyfilledDOMException.prototype; + if (PolyfilledDOMExceptionPrototype.constructor !== PolyfilledDOMException) { + if (!IS_PURE) { + defineProperty(PolyfilledDOMExceptionPrototype, "constructor", createPropertyDescriptor(1, PolyfilledDOMException)); + } + for (var key in DOMExceptionConstants) if (hasOwn(DOMExceptionConstants, key)) { + var constant2 = DOMExceptionConstants[key]; + var constantName = constant2.s; + if (!hasOwn(PolyfilledDOMException, constantName)) { + defineProperty(PolyfilledDOMException, constantName, createPropertyDescriptor(6, constant2.c)); + } + } + } + } + ), + /***/ + 5002: ( + /***/ + (module2) => { + module2.exports = { + IndexSizeError: { s: "INDEX_SIZE_ERR", c: 1, m: 1 }, + DOMStringSizeError: { s: "DOMSTRING_SIZE_ERR", c: 2, m: 0 }, + HierarchyRequestError: { s: "HIERARCHY_REQUEST_ERR", c: 3, m: 1 }, + WrongDocumentError: { s: "WRONG_DOCUMENT_ERR", c: 4, m: 1 }, + InvalidCharacterError: { s: "INVALID_CHARACTER_ERR", c: 5, m: 1 }, + NoDataAllowedError: { s: "NO_DATA_ALLOWED_ERR", c: 6, m: 0 }, + NoModificationAllowedError: { s: "NO_MODIFICATION_ALLOWED_ERR", c: 7, m: 1 }, + NotFoundError: { s: "NOT_FOUND_ERR", c: 8, m: 1 }, + NotSupportedError: { s: "NOT_SUPPORTED_ERR", c: 9, m: 1 }, + InUseAttributeError: { s: "INUSE_ATTRIBUTE_ERR", c: 10, m: 1 }, + InvalidStateError: { s: "INVALID_STATE_ERR", c: 11, m: 1 }, + SyntaxError: { s: "SYNTAX_ERR", c: 12, m: 1 }, + InvalidModificationError: { s: "INVALID_MODIFICATION_ERR", c: 13, m: 1 }, + NamespaceError: { s: "NAMESPACE_ERR", c: 14, m: 1 }, + InvalidAccessError: { s: "INVALID_ACCESS_ERR", c: 15, m: 1 }, + ValidationError: { s: "VALIDATION_ERR", c: 16, m: 0 }, + TypeMismatchError: { s: "TYPE_MISMATCH_ERR", c: 17, m: 1 }, + SecurityError: { s: "SECURITY_ERR", c: 18, m: 1 }, + NetworkError: { s: "NETWORK_ERR", c: 19, m: 1 }, + AbortError: { s: "ABORT_ERR", c: 20, m: 1 }, + URLMismatchError: { s: "URL_MISMATCH_ERR", c: 21, m: 1 }, + QuotaExceededError: { s: "QUOTA_EXCEEDED_ERR", c: 22, m: 1 }, + TimeoutError: { s: "TIMEOUT_ERR", c: 23, m: 1 }, + InvalidNodeTypeError: { s: "INVALID_NODE_TYPE_ERR", c: 24, m: 1 }, + DataCloneError: { s: "DATA_CLONE_ERR", c: 25, m: 1 } + }; + } + ), + /***/ + 5024: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var symmetricDifference = __webpack_require__3(3650); + var setMethodGetKeysBeforeCloning = __webpack_require__3(9835); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var FORCED = !setMethodAcceptSetLike("symmetricDifference") || !setMethodGetKeysBeforeCloning("symmetricDifference"); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + symmetricDifference + }); + } + ), + /***/ + 5031: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + var uncurryThis = __webpack_require__3(9504); + var getOwnPropertyNamesModule = __webpack_require__3(8480); + var getOwnPropertySymbolsModule = __webpack_require__3(3717); + var anObject = __webpack_require__3(8551); + var concat2 = uncurryThis([].concat); + module2.exports = getBuiltIn("Reflect", "ownKeys") || function ownKeys(it) { + var keys2 = getOwnPropertyNamesModule.f(anObject(it)); + var getOwnPropertySymbols = getOwnPropertySymbolsModule.f; + return getOwnPropertySymbols ? concat2(keys2, getOwnPropertySymbols(it)) : keys2; + }; + } + ), + /***/ + 5169: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isDetached = __webpack_require__3(3238); + var $TypeError = TypeError; + module2.exports = function(it) { + if (isDetached(it)) throw new $TypeError("ArrayBuffer is detached"); + return it; + }; + } + ), + /***/ + 5170: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThisAccessor = __webpack_require__3(6706); + var SetHelpers = __webpack_require__3(4402); + module2.exports = uncurryThisAccessor(SetHelpers.proto, "size", "get") || function(set2) { + return set2.size; + }; + } + ), + /***/ + 5213: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var arrayFromConstructorAndList = __webpack_require__3(5370); + var $fromBase64 = __webpack_require__3(9143); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.fromBase64 || !function() { + try { + Uint8Array2.fromBase64("a"); + return; + } catch (error62) { + } + try { + Uint8Array2.fromBase64("", null); + } catch (error62) { + return true; + } + }(); + if (Uint8Array2) $({ target: "Uint8Array", stat: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + fromBase64: function fromBase64(string4) { + var result2 = $fromBase64(string4, arguments.length > 1 ? arguments[1] : void 0, null, 9007199254740991); + return arrayFromConstructorAndList(Uint8Array2, result2.bytes); + } + }); + } + ), + /***/ + 5370: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var lengthOfArrayLike = __webpack_require__3(6198); + module2.exports = function(Constructor, list, $length) { + var index2 = 0; + var length = arguments.length > 2 ? $length : lengthOfArrayLike(list); + var result2 = new Constructor(length); + while (length > index2) result2[index2] = list[index2++]; + return result2; + }; + } + ), + /***/ + 5397: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var IndexedObject = __webpack_require__3(7055); + var requireObjectCoercible = __webpack_require__3(7750); + module2.exports = function(it) { + return IndexedObject(requireObjectCoercible(it)); + }; + } + ), + /***/ + 5610: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); + var max2 = Math.max; + var min2 = Math.min; + module2.exports = function(index2, length) { + var integer3 = toIntegerOrInfinity(index2); + return integer3 < 0 ? max2(integer3 + length, 0) : min2(integer3, length); + }; + } + ), + /***/ + 5623: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(456); + } + ), + /***/ + 5636: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var uncurryThisAccessor = __webpack_require__3(6706); + var toIndex = __webpack_require__3(7696); + var notDetached = __webpack_require__3(5169); + var arrayBufferByteLength = __webpack_require__3(7394); + var detachTransferable = __webpack_require__3(4483); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__3(1548); + var structuredClone2 = globalThis2.structuredClone; + var ArrayBuffer2 = globalThis2.ArrayBuffer; + var DataView2 = globalThis2.DataView; + var min2 = Math.min; + var ArrayBufferPrototype = ArrayBuffer2.prototype; + var DataViewPrototype = DataView2.prototype; + var slice2 = uncurryThis(ArrayBufferPrototype.slice); + var isResizable = uncurryThisAccessor(ArrayBufferPrototype, "resizable", "get"); + var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, "maxByteLength", "get"); + var getInt8 = uncurryThis(DataViewPrototype.getInt8); + var setInt8 = uncurryThis(DataViewPrototype.setInt8); + module2.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function(arrayBuffer, newLength, preserveResizability) { + var byteLength = arrayBufferByteLength(arrayBuffer); + var newByteLength = newLength === void 0 ? byteLength : toIndex(newLength); + var fixedLength = !isResizable || !isResizable(arrayBuffer); + var newBuffer; + notDetached(arrayBuffer); + if (PROPER_STRUCTURED_CLONE_TRANSFER) { + arrayBuffer = structuredClone2(arrayBuffer, { transfer: [arrayBuffer] }); + if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer; + } + if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) { + newBuffer = slice2(arrayBuffer, 0, newByteLength); + } else { + var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : void 0; + newBuffer = new ArrayBuffer2(newByteLength, options); + var a = new DataView2(arrayBuffer); + var b2 = new DataView2(newBuffer); + var copyLength = min2(newByteLength, byteLength); + for (var i = 0; i < copyLength; i++) setInt8(b2, i, getInt8(a, i)); + } + if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer); + return newBuffer; + }; + } + ), + /***/ + 5745: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var store = __webpack_require__3(7629); + module2.exports = function(key, value) { + return store[key] || (store[key] = value || {}); + }; + } + ), + /***/ + 5781: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var getBuiltIn = __webpack_require__3(7751); + var validateArgumentsLength = __webpack_require__3(2812); + var toString2 = __webpack_require__3(655); + var USE_NATIVE_URL = __webpack_require__3(7416); + var URL2 = getBuiltIn("URL"); + $({ target: "URL", stat: true, forced: !USE_NATIVE_URL }, { + parse: function parse4(url2) { + var length = validateArgumentsLength(arguments.length, 1); + var urlString = toString2(url2); + var base = length < 2 || arguments[1] === void 0 ? void 0 : toString2(arguments[1]); + try { + return new URL2(urlString, base); + } catch (error62) { + return null; + } + } + }); + } + ), + /***/ + 5854: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toPrimitive = __webpack_require__3(2777); + var $TypeError = TypeError; + module2.exports = function(argument) { + var prim = toPrimitive(argument, "number"); + if (typeof prim == "number") throw new $TypeError("Can't convert number to bigint"); + return BigInt(prim); + }; + } + ), + /***/ + 5876: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isSubsetOf = __webpack_require__3(3838); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var INCORRECT = !setMethodAcceptSetLike("isSubsetOf", function(result2) { + return result2; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isSubsetOf + }); + } + ), + /***/ + 5917: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var fails = __webpack_require__3(9039); + var createElement = __webpack_require__3(4055); + module2.exports = !DESCRIPTORS && !fails(function() { + return Object.defineProperty(createElement("div"), "a", { + get: function() { + return 7; + } + }).a !== 7; + }); + } + ), + /***/ + 5966: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); + var isNullOrUndefined = __webpack_require__3(4117); + module2.exports = function(V, P2) { + var func = V[P2]; + return isNullOrUndefined(func) ? void 0 : aCallable(func); + }; + } + ), + /***/ + 6043: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); + var $TypeError = TypeError; + var PromiseCapability = function(C) { + var resolve2, reject2; + this.promise = new C(function($$resolve, $$reject) { + if (resolve2 !== void 0 || reject2 !== void 0) throw new $TypeError("Bad Promise constructor"); + resolve2 = $$resolve; + reject2 = $$reject; + }); + this.resolve = aCallable(resolve2); + this.reject = aCallable(reject2); + }; + module2.exports.f = function(C) { + return new PromiseCapability(C); + }; + } + ), + /***/ + 6080: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(7476); + var aCallable = __webpack_require__3(9306); + var NATIVE_BIND = __webpack_require__3(616); + var bind = uncurryThis(uncurryThis.bind); + module2.exports = function(fn, that) { + aCallable(fn); + return that === void 0 ? fn : NATIVE_BIND ? bind(fn, that) : function() { + return fn.apply(that, arguments); + }; + }; + } + ), + /***/ + 6119: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var shared = __webpack_require__3(5745); + var uid3 = __webpack_require__3(3392); + var keys2 = shared("keys"); + module2.exports = function(key) { + return keys2[key] || (keys2[key] = uid3(key)); + }; + } + ), + /***/ + 6193: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var ENVIRONMENT = __webpack_require__3(4215); + module2.exports = ENVIRONMENT === "NODE"; + } + ), + /***/ + 6198: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toLength = __webpack_require__3(8014); + module2.exports = function(obj2) { + return toLength(obj2.length); + }; + } + ), + /***/ + 6269: ( + /***/ + (module2) => { + module2.exports = {}; + } + ), + /***/ + 6279: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); + module2.exports = function(target, src, options) { + for (var key in src) defineBuiltIn(target, key, src[key], options); + return target; + }; + } + ), + /***/ + 6319: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var anObject = __webpack_require__3(8551); + var iteratorClose = __webpack_require__3(9539); + module2.exports = function(iterator, fn, value, ENTRIES) { + try { + return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); + } catch (error62) { + iteratorClose(iterator, "throw", error62); + } + }; + } + ), + /***/ + 6395: ( + /***/ + (module2) => { + module2.exports = false; + } + ), + /***/ + 6518: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var getOwnPropertyDescriptor = __webpack_require__3(7347).f; + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIn = __webpack_require__3(6840); + var defineGlobalProperty = __webpack_require__3(9433); + var copyConstructorProperties = __webpack_require__3(7740); + var isForced = __webpack_require__3(2796); + module2.exports = function(options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = globalThis2; + } else if (STATIC) { + target = globalThis2[TARGET] || defineGlobalProperty(TARGET, {}); + } else { + target = globalThis2[TARGET] && globalThis2[TARGET].prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.dontCallGetSet) { + descriptor = getOwnPropertyDescriptor(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced); + if (!FORCED && targetProperty !== void 0) { + if (typeof sourceProperty == typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + if (options.sham || targetProperty && targetProperty.sham) { + createNonEnumerableProperty(sourceProperty, "sham", true); + } + defineBuiltIn(target, key, sourceProperty, options); + } + }; + } + ), + /***/ + 6573: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var defineBuiltInAccessor = __webpack_require__3(2106); + var isDetached = __webpack_require__3(3238); + var ArrayBufferPrototype = ArrayBuffer.prototype; + if (DESCRIPTORS && !("detached" in ArrayBufferPrototype)) { + defineBuiltInAccessor(ArrayBufferPrototype, "detached", { + configurable: true, + get: function detached() { + return isDetached(this); + } + }); + } + } + ), + /***/ + 6632: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var $fromBase64 = __webpack_require__3(9143); + var anUint8Array = __webpack_require__3(4154); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.setFromBase64 || !function() { + var target = new Uint8Array2([255, 255, 255, 255, 255]); + try { + target.setFromBase64("", null); + return; + } catch (error62) { + } + try { + target.setFromBase64("a"); + return; + } catch (error62) { + } + try { + target.setFromBase64("MjYyZg==="); + } catch (error62) { + return target[0] === 50 && target[1] === 54 && target[2] === 50 && target[3] === 255 && target[4] === 255; + } + }(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + setFromBase64: function setFromBase64(string4) { + anUint8Array(this); + var result2 = $fromBase64(string4, arguments.length > 1 ? arguments[1] : void 0, this, this.length); + return { read: result2.read, written: result2.written }; + } + }); + } + ), + /***/ + 6699: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var definePropertyModule = __webpack_require__3(4913); + var createPropertyDescriptor = __webpack_require__3(6980); + module2.exports = DESCRIPTORS ? function(object3, key, value) { + return definePropertyModule.f(object3, key, createPropertyDescriptor(1, value)); + } : function(object3, key, value) { + object3[key] = value; + return object3; + }; + } + ), + /***/ + 6706: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var aCallable = __webpack_require__3(9306); + module2.exports = function(object3, key, method) { + try { + return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object3, key)[method])); + } catch (error62) { + } + }; + } + ), + /***/ + 6801: ( + /***/ + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__3(8686); + var definePropertyModule = __webpack_require__3(4913); + var anObject = __webpack_require__3(8551); + var toIndexedObject = __webpack_require__3(5397); + var objectKeys = __webpack_require__3(1072); + exports2.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var props = toIndexedObject(Properties); + var keys2 = objectKeys(Properties); + var length = keys2.length; + var index2 = 0; + var key; + while (length > index2) definePropertyModule.f(O, key = keys2[index2++], props[key]); + return O; + }; + } + ), + /***/ + 6823: ( + /***/ + (module2) => { + var $String = String; + module2.exports = function(argument) { + try { + return $String(argument); + } catch (error62) { + return "Object"; + } + }; + } + ), + /***/ + 6837: ( + /***/ + (module2) => { + var $TypeError = TypeError; + var MAX_SAFE_INTEGER = 9007199254740991; + module2.exports = function(it) { + if (it > MAX_SAFE_INTEGER) throw $TypeError("Maximum allowed index exceeded"); + return it; + }; + } + ), + /***/ + 6840: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var definePropertyModule = __webpack_require__3(4913); + var makeBuiltIn = __webpack_require__3(283); + var defineGlobalProperty = __webpack_require__3(9433); + module2.exports = function(O, key, value, options) { + if (!options) options = {}; + var simple = options.enumerable; + var name = options.name !== void 0 ? options.name : key; + if (isCallable(value)) makeBuiltIn(value, name, options); + if (options.global) { + if (simple) O[key] = value; + else defineGlobalProperty(key, value); + } else { + try { + if (!options.unsafe) delete O[key]; + else if (O[key]) simple = true; + } catch (error62) { + } + if (simple) O[key] = value; + else definePropertyModule.f(O, key, { + value, + enumerable: false, + configurable: !options.nonConfigurable, + writable: !options.nonWritable + }); + } + return O; + }; + } + ), + /***/ + 6955: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var TO_STRING_TAG_SUPPORT = __webpack_require__3(2140); + var isCallable = __webpack_require__3(4901); + var classofRaw = __webpack_require__3(2195); + var wellKnownSymbol = __webpack_require__3(8227); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var $Object = Object; + var CORRECT_ARGUMENTS = classofRaw(/* @__PURE__ */ function() { + return arguments; + }()) === "Arguments"; + var tryGet = function(it, key) { + try { + return it[key]; + } catch (error62) { + } + }; + module2.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) { + var O, tag2, result2; + return it === void 0 ? "Undefined" : it === null ? "Null" : typeof (tag2 = tryGet(O = $Object(it), TO_STRING_TAG)) == "string" ? tag2 : CORRECT_ARGUMENTS ? classofRaw(O) : (result2 = classofRaw(O)) === "Object" && isCallable(O.callee) ? "Arguments" : result2; + }; + } + ), + /***/ + 6969: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toPrimitive = __webpack_require__3(2777); + var isSymbol = __webpack_require__3(757); + module2.exports = function(argument) { + var key = toPrimitive(argument, "string"); + return isSymbol(key) ? key : key + ""; + }; + } + ), + /***/ + 6980: ( + /***/ + (module2) => { + module2.exports = function(bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value + }; + }; + } + ), + /***/ + 7040: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_SYMBOL = __webpack_require__3(4495); + module2.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == "symbol"; + } + ), + /***/ + 7055: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var fails = __webpack_require__3(9039); + var classof = __webpack_require__3(2195); + var $Object = Object; + var split = uncurryThis("".split); + module2.exports = fails(function() { + return !$Object("z").propertyIsEnumerable(0); + }) ? function(it) { + return classof(it) === "String" ? split(it, "") : $Object(it); + } : $Object; + } + ), + /***/ + 7080: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var has3 = __webpack_require__3(4402).has; + module2.exports = function(it) { + has3(it); + return it; + }; + } + ), + /***/ + 7347: ( + /***/ + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var call = __webpack_require__3(9565); + var propertyIsEnumerableModule = __webpack_require__3(8773); + var createPropertyDescriptor = __webpack_require__3(6980); + var toIndexedObject = __webpack_require__3(5397); + var toPropertyKey = __webpack_require__3(6969); + var hasOwn = __webpack_require__3(9297); + var IE8_DOM_DEFINE = __webpack_require__3(5917); + var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + exports2.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P2) { + O = toIndexedObject(O); + P2 = toPropertyKey(P2); + if (IE8_DOM_DEFINE) try { + return $getOwnPropertyDescriptor(O, P2); + } catch (error62) { + } + if (hasOwn(O, P2)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P2), O[P2]); + }; + } + ), + /***/ + 7394: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThisAccessor = __webpack_require__3(6706); + var classof = __webpack_require__3(2195); + var ArrayBuffer2 = globalThis2.ArrayBuffer; + var TypeError2 = globalThis2.TypeError; + module2.exports = ArrayBuffer2 && uncurryThisAccessor(ArrayBuffer2.prototype, "byteLength", "get") || function(O) { + if (classof(O) !== "ArrayBuffer") throw new TypeError2("ArrayBuffer expected"); + return O.byteLength; + }; + } + ), + /***/ + 7416: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var wellKnownSymbol = __webpack_require__3(8227); + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); + var ITERATOR = wellKnownSymbol("iterator"); + module2.exports = !fails(function() { + var url2 = new URL("b?a=1&b=2&c=3", "https://a"); + var params = url2.searchParams; + var params2 = new URLSearchParams("a=1&a=2&b=3"); + var result2 = ""; + url2.pathname = "c%20d"; + params.forEach(function(value, key) { + params["delete"]("b"); + result2 += key + value; + }); + params2["delete"]("a", 2); + params2["delete"]("b", void 0); + return IS_PURE && (!url2.toJSON || !params2.has("a", 1) || params2.has("a", 2) || !params2.has("a", void 0) || params2.has("b")) || !params.size && (IS_PURE || !DESCRIPTORS) || !params.sort || url2.href !== "https://a/c%20d?a=1&c=3" || params.get("c") !== "3" || String(new URLSearchParams("?a=1")) !== "a=1" || !params[ITERATOR] || new URL("https://a@b").username !== "a" || new URLSearchParams(new URLSearchParams("a=b")).get("a") !== "b" || new URL("https://\u0442\u0435\u0441\u0442").host !== "xn--e1aybc" || new URL("https://a#\u0431").hash !== "#%D0%B1" || result2 !== "a1c3" || new URL("https://x", void 0).host !== "x"; + }); + } + ), + /***/ + 7476: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classofRaw = __webpack_require__3(2195); + var uncurryThis = __webpack_require__3(9504); + module2.exports = function(fn) { + if (classofRaw(fn) === "Function") return uncurryThis(fn); + }; + } + ), + /***/ + 7566: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); + var uncurryThis = __webpack_require__3(9504); + var toString2 = __webpack_require__3(655); + var validateArgumentsLength = __webpack_require__3(2812); + var $URLSearchParams = URLSearchParams; + var URLSearchParamsPrototype = $URLSearchParams.prototype; + var getAll = uncurryThis(URLSearchParamsPrototype.getAll); + var $has = uncurryThis(URLSearchParamsPrototype.has); + var params = new $URLSearchParams("a=1"); + if (params.has("a", 2) || !params.has("a", void 0)) { + defineBuiltIn(URLSearchParamsPrototype, "has", function has3(name) { + var length = arguments.length; + var $value = length < 2 ? void 0 : arguments[1]; + if (length && $value === void 0) return $has(this, name); + var values3 = getAll(this, name); + validateArgumentsLength(length, 1); + var value = toString2($value); + var index2 = 0; + while (index2 < values3.length) { + if (values3[index2++] === value) return true; + } + return false; + }, { enumerable: true, unsafe: true }); + } + } + ), + /***/ + 7588: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var forEachWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("forEach", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: forEachWithoutClosingOnEarlyError }, { + forEach: function forEach(fn) { + anObject(this); + try { + aCallable(fn); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + if (forEachWithoutClosingOnEarlyError) return call(forEachWithoutClosingOnEarlyError, this, fn); + var record2 = getIteratorDirect(this); + var counter = 0; + iterate(record2, function(value) { + fn(value, counter++); + }, { IS_RECORD: true }); + } + }); + } + ), + /***/ + 7594: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var fails = __webpack_require__3(9039); + var RegExp2 = globalThis2.RegExp; + var FLAGS_GETTER_IS_CORRECT = !fails(function() { + var INDICES_SUPPORT = true; + try { + RegExp2(".", "d"); + } catch (error62) { + INDICES_SUPPORT = false; + } + var O = {}; + var calls = ""; + var expected = INDICES_SUPPORT ? "dgimsy" : "gimsy"; + var addGetter = function(key2, chr) { + Object.defineProperty(O, key2, { get: function() { + calls += chr; + return true; + } }); + }; + var pairs2 = { + dotAll: "s", + global: "g", + ignoreCase: "i", + multiline: "m", + sticky: "y" + }; + if (INDICES_SUPPORT) pairs2.hasIndices = "d"; + for (var key in pairs2) addGetter(key, pairs2[key]); + var result2 = Object.getOwnPropertyDescriptor(RegExp2.prototype, "flags").get.call(O); + return result2 !== expected || calls !== expected; + }); + module2.exports = { correct: FLAGS_GETTER_IS_CORRECT }; + } + ), + /***/ + 7629: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var IS_PURE = __webpack_require__3(6395); + var globalThis2 = __webpack_require__3(4576); + var defineGlobalProperty = __webpack_require__3(9433); + var SHARED = "__core-js_shared__"; + var store = module2.exports = globalThis2[SHARED] || defineGlobalProperty(SHARED, {}); + (store.versions || (store.versions = [])).push({ + version: "3.45.1", + mode: IS_PURE ? "pure" : "global", + copyright: "\xA9 2014-2025 Denis Pushkarev (zloirock.ru)", + license: "https://github.com/zloirock/core-js/blob/v3.45.1/LICENSE", + source: "https://github.com/zloirock/core-js" + }); + } + ), + /***/ + 7642: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var difference = __webpack_require__3(3440); + var fails = __webpack_require__3(9039); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var SET_LIKE_INCORRECT_BEHAVIOR = !setMethodAcceptSetLike("difference", function(result2) { + return result2.size === 0; + }); + var FORCED = SET_LIKE_INCORRECT_BEHAVIOR || fails(function() { + var setLike = { + size: 1, + has: function() { + return true; + }, + keys: function() { + var index2 = 0; + return { + next: function() { + var done = index2++ > 1; + if (baseSet.has(1)) baseSet.clear(); + return { done, value: 2 }; + } + }; + } + }; + var baseSet = /* @__PURE__ */ new Set([1, 2, 3, 4]); + return baseSet.difference(setLike).size !== 3; + }); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + difference + }); + } + ), + /***/ + 7657: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var create2 = __webpack_require__3(2360); + var getPrototypeOf = __webpack_require__3(2787); + var defineBuiltIn = __webpack_require__3(6840); + var wellKnownSymbol = __webpack_require__3(8227); + var IS_PURE = __webpack_require__3(6395); + var ITERATOR = wellKnownSymbol("iterator"); + var BUGGY_SAFARI_ITERATORS = false; + var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator; + if ([].keys) { + arrayIterator = [].keys(); + if (!("next" in arrayIterator)) BUGGY_SAFARI_ITERATORS = true; + else { + PrototypeOfArrayIteratorPrototype = getPrototypeOf(getPrototypeOf(arrayIterator)); + if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype; + } + } + var NEW_ITERATOR_PROTOTYPE = !isObject5(IteratorPrototype) || fails(function() { + var test = {}; + return IteratorPrototype[ITERATOR].call(test) !== test; + }); + if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype = {}; + else if (IS_PURE) IteratorPrototype = create2(IteratorPrototype); + if (!isCallable(IteratorPrototype[ITERATOR])) { + defineBuiltIn(IteratorPrototype, ITERATOR, function() { + return this; + }); + } + module2.exports = { + IteratorPrototype, + BUGGY_SAFARI_ITERATORS + }; + } + ), + /***/ + 7680: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + module2.exports = uncurryThis([].slice); + } + ), + /***/ + 7696: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); + var toLength = __webpack_require__3(8014); + var $RangeError = RangeError; + module2.exports = function(it) { + if (it === void 0) return 0; + var number4 = toIntegerOrInfinity(it); + var length = toLength(number4); + if (number4 !== length) throw new $RangeError("Wrong length or index"); + return length; + }; + } + ), + /***/ + 7740: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var hasOwn = __webpack_require__3(9297); + var ownKeys = __webpack_require__3(5031); + var getOwnPropertyDescriptorModule = __webpack_require__3(7347); + var definePropertyModule = __webpack_require__3(4913); + module2.exports = function(target, source, exceptions) { + var keys2 = ownKeys(source); + var defineProperty = definePropertyModule.f; + var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f; + for (var i = 0; i < keys2.length; i++) { + var key = keys2[i]; + if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) { + defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + } + }; + } + ), + /***/ + 7750: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isNullOrUndefined = __webpack_require__3(4117); + var $TypeError = TypeError; + module2.exports = function(it) { + if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it); + return it; + }; + } + ), + /***/ + 7751: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); + var aFunction = function(argument) { + return isCallable(argument) ? argument : void 0; + }; + module2.exports = function(namespace, method) { + return arguments.length < 2 ? aFunction(globalThis2[namespace]) : globalThis2[namespace] && globalThis2[namespace][method]; + }; + } + ), + /***/ + 7811: ( + /***/ + (module2) => { + module2.exports = typeof ArrayBuffer != "undefined" && typeof DataView != "undefined"; + } + ), + /***/ + 7936: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var $transfer = __webpack_require__3(5636); + if ($transfer) $({ target: "ArrayBuffer", proto: true }, { + transferToFixedLength: function transferToFixedLength() { + return $transfer(this, arguments.length ? arguments[0] : void 0, false); + } + }); + } + ), + /***/ + 7979: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var anObject = __webpack_require__3(8551); + module2.exports = function() { + var that = anObject(this); + var result2 = ""; + if (that.hasIndices) result2 += "d"; + if (that.global) result2 += "g"; + if (that.ignoreCase) result2 += "i"; + if (that.multiline) result2 += "m"; + if (that.dotAll) result2 += "s"; + if (that.unicode) result2 += "u"; + if (that.unicodeSets) result2 += "v"; + if (that.sticky) result2 += "y"; + return result2; + }; + } + ), + /***/ + 8004: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var fails = __webpack_require__3(9039); + var intersection3 = __webpack_require__3(8750); + var setMethodAcceptSetLike = __webpack_require__3(4916); + var INCORRECT = !setMethodAcceptSetLike("intersection", function(result2) { + return result2.size === 2 && result2.has(1) && result2.has(2); + }) || fails(function() { + return String(Array.from((/* @__PURE__ */ new Set([1, 2, 3])).intersection(/* @__PURE__ */ new Set([3, 2])))) !== "3,2"; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + intersection: intersection3 + }); + } + ), + /***/ + 8014: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); + var min2 = Math.min; + module2.exports = function(argument) { + var len = toIntegerOrInfinity(argument); + return len > 0 ? min2(len, 9007199254740991) : 0; + }; + } + ), + /***/ + 8100: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var $transfer = __webpack_require__3(5636); + if ($transfer) $({ target: "ArrayBuffer", proto: true }, { + transfer: function transfer() { + return $transfer(this, arguments.length ? arguments[0] : void 0, true); + } + }); + } + ), + /***/ + 8111: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var anInstance = __webpack_require__3(679); + var anObject = __webpack_require__3(8551); + var isCallable = __webpack_require__3(4901); + var getPrototypeOf = __webpack_require__3(2787); + var defineBuiltInAccessor = __webpack_require__3(2106); + var createProperty = __webpack_require__3(4659); + var fails = __webpack_require__3(9039); + var hasOwn = __webpack_require__3(9297); + var wellKnownSymbol = __webpack_require__3(8227); + var IteratorPrototype = __webpack_require__3(7657).IteratorPrototype; + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); + var CONSTRUCTOR = "constructor"; + var ITERATOR = "Iterator"; + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var $TypeError = TypeError; + var NativeIterator = globalThis2[ITERATOR]; + var FORCED = IS_PURE || !isCallable(NativeIterator) || NativeIterator.prototype !== IteratorPrototype || !fails(function() { + NativeIterator({}); + }); + var IteratorConstructor = function Iterator2() { + anInstance(this, IteratorPrototype); + if (getPrototypeOf(this) === IteratorPrototype) throw new $TypeError("Abstract class Iterator not directly constructable"); + }; + var defineIteratorPrototypeAccessor = function(key, value) { + if (DESCRIPTORS) { + defineBuiltInAccessor(IteratorPrototype, key, { + configurable: true, + get: function() { + return value; + }, + set: function(replacement) { + anObject(this); + if (this === IteratorPrototype) throw new $TypeError("You can't redefine this property"); + if (hasOwn(this, key)) this[key] = replacement; + else createProperty(this, key, replacement); + } + }); + } else IteratorPrototype[key] = value; + }; + if (!hasOwn(IteratorPrototype, TO_STRING_TAG)) defineIteratorPrototypeAccessor(TO_STRING_TAG, ITERATOR); + if (FORCED || !hasOwn(IteratorPrototype, CONSTRUCTOR) || IteratorPrototype[CONSTRUCTOR] === Object) { + defineIteratorPrototypeAccessor(CONSTRUCTOR, IteratorConstructor); + } + IteratorConstructor.prototype = IteratorPrototype; + $({ global: true, constructor: true, forced: FORCED }, { + Iterator: IteratorConstructor + }); + } + ), + /***/ + 8227: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var shared = __webpack_require__3(5745); + var hasOwn = __webpack_require__3(9297); + var uid3 = __webpack_require__3(3392); + var NATIVE_SYMBOL = __webpack_require__3(4495); + var USE_SYMBOL_AS_UID = __webpack_require__3(7040); + var Symbol2 = globalThis2.Symbol; + var WellKnownSymbolsStore = shared("wks"); + var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid3; + module2.exports = function(name) { + if (!hasOwn(WellKnownSymbolsStore, name)) { + WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol2, name) ? Symbol2[name] : createWellKnownSymbol("Symbol." + name); + } + return WellKnownSymbolsStore[name]; + }; + } + ), + /***/ + 8237: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var apply = __webpack_require__3(8745); + var fails = __webpack_require__3(9039); + var $TypeError = TypeError; + var FAILS_ON_INITIAL_UNDEFINED = fails(function() { + [].keys().reduce(function() { + }, void 0); + }); + var reduceWithoutClosingOnEarlyError = !FAILS_ON_INITIAL_UNDEFINED && iteratorHelperWithoutClosingOnEarlyError("reduce", $TypeError); + $({ target: "Iterator", proto: true, real: true, forced: FAILS_ON_INITIAL_UNDEFINED || reduceWithoutClosingOnEarlyError }, { + reduce: function reduce(reducer) { + anObject(this); + try { + aCallable(reducer); + } catch (error62) { + iteratorClose(this, "throw", error62); + } + var noInitial = arguments.length < 2; + var accumulator = noInitial ? void 0 : arguments[1]; + if (reduceWithoutClosingOnEarlyError) { + return apply(reduceWithoutClosingOnEarlyError, this, noInitial ? [reducer] : [reducer, accumulator]); + } + var record2 = getIteratorDirect(this); + var counter = 0; + iterate(record2, function(value) { + if (noInitial) { + noInitial = false; + accumulator = value; + } else { + accumulator = reducer(accumulator, value, counter); + } + counter++; + }, { IS_RECORD: true }); + if (noInitial) throw new $TypeError("Reduce of empty iterator with no initial value"); + return accumulator; + } + }); + } + ), + /***/ + 8469: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var iterateSimple = __webpack_require__3(507); + var SetHelpers = __webpack_require__3(4402); + var Set2 = SetHelpers.Set; + var SetPrototype = SetHelpers.proto; + var forEach = uncurryThis(SetPrototype.forEach); + var keys2 = uncurryThis(SetPrototype.keys); + var next = keys2(new Set2()).next; + module2.exports = function(set2, fn, interruptible) { + return interruptible ? iterateSimple({ iterator: keys2(set2), next }, fn) : forEach(set2, fn); + }; + } + ), + /***/ + 8480: ( + /***/ + (__unused_webpack_module, exports2, __webpack_require__3) => { + var internalObjectKeys = __webpack_require__3(1828); + var enumBugKeys = __webpack_require__3(8727); + var hiddenKeys = enumBugKeys.concat("length", "prototype"); + exports2.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return internalObjectKeys(O, hiddenKeys); + }; + } + ), + /***/ + 8527: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var has3 = __webpack_require__3(4402).has; + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); + var iteratorClose = __webpack_require__3(9539); + module2.exports = function isSupersetOf(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size3(O) < otherRec.size) return false; + var iterator = otherRec.getIterator(); + return iterateSimple(iterator, function(e) { + if (!has3(O, e)) return iteratorClose(iterator, "normal", false); + }) !== false; + }; + } + ), + /***/ + 8551: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isObject5(argument)) return argument; + throw new $TypeError($String(argument) + " is not an object"); + }; + } + ), + /***/ + 8574: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var $Error = Error; + var replace = uncurryThis("".replace); + var TEST = function(arg) { + return String(new $Error(arg).stack); + }("zxcasd"); + var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/; + var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST); + module2.exports = function(stack, dropEntries) { + if (IS_V8_OR_CHAKRA_STACK && typeof stack == "string" && !$Error.prepareStackTrace) { + while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, ""); + } + return stack; + }; + } + ), + /***/ + 8622: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); + var WeakMap2 = globalThis2.WeakMap; + module2.exports = isCallable(WeakMap2) && /native code/.test(String(WeakMap2)); + } + ), + /***/ + 8646: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var getIteratorMethod = __webpack_require__3(851); + module2.exports = function(obj2, stringHandling) { + if (!stringHandling || typeof obj2 !== "string") anObject(obj2); + var method = getIteratorMethod(obj2); + return getIteratorDirect(anObject(method !== void 0 ? call(method, obj2) : obj2)); + }; + } + ), + /***/ + 8686: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var fails = __webpack_require__3(9039); + module2.exports = DESCRIPTORS && fails(function() { + return Object.defineProperty(function() { + }, "prototype", { + value: 42, + writable: false + }).prototype !== 42; + }); + } + ), + /***/ + 8721: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var uncurryThis = __webpack_require__3(9504); + var defineBuiltInAccessor = __webpack_require__3(2106); + var URLSearchParamsPrototype = URLSearchParams.prototype; + var forEach = uncurryThis(URLSearchParamsPrototype.forEach); + if (DESCRIPTORS && !("size" in URLSearchParamsPrototype)) { + defineBuiltInAccessor(URLSearchParamsPrototype, "size", { + get: function size3() { + var count = 0; + forEach(this, function() { + count++; + }); + return count; + }, + configurable: true, + enumerable: true + }); + } + } + ), + /***/ + 8727: ( + /***/ + (module2) => { + module2.exports = [ + "constructor", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "toLocaleString", + "toString", + "valueOf" + ]; + } + ), + /***/ + 8745: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); + var FunctionPrototype = Function.prototype; + var apply = FunctionPrototype.apply; + var call = FunctionPrototype.call; + module2.exports = typeof Reflect == "object" && Reflect.apply || (NATIVE_BIND ? call.bind(apply) : function() { + return call.apply(apply, arguments); + }); + } + ), + /***/ + 8750: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); + var Set2 = SetHelpers.Set; + var add = SetHelpers.add; + var has3 = SetHelpers.has; + module2.exports = function intersection3(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + var result2 = new Set2(); + if (size3(O) > otherRec.size) { + iterateSimple(otherRec.getIterator(), function(e) { + if (has3(O, e)) add(result2, e); + }); + } else { + iterateSet(O, function(e) { + if (otherRec.includes(e)) add(result2, e); + }); + } + return result2; + }; + } + ), + /***/ + 8773: ( + /***/ + (__unused_webpack_module, exports2) => { + var $propertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1); + exports2.f = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor(this, V); + return !!descriptor && descriptor.enumerable; + } : $propertyIsEnumerable; + } + ), + /***/ + 8981: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var requireObjectCoercible = __webpack_require__3(7750); + var $Object = Object; + module2.exports = function(argument) { + return $Object(requireObjectCoercible(argument)); + }; + } + ), + /***/ + 9039: ( + /***/ + (module2) => { + module2.exports = function(exec) { + try { + return !!exec(); + } catch (error62) { + return true; + } + }; + } + ), + /***/ + 9143: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anObjectOrUndefined = __webpack_require__3(3972); + var aString = __webpack_require__3(3463); + var hasOwn = __webpack_require__3(9297); + var base64Map = __webpack_require__3(2804); + var getAlphabetOption = __webpack_require__3(944); + var notDetached = __webpack_require__3(5169); + var base64Alphabet = base64Map.c2i; + var base64UrlAlphabet = base64Map.c2iUrl; + var SyntaxError2 = globalThis2.SyntaxError; + var TypeError2 = globalThis2.TypeError; + var at = uncurryThis("".charAt); + var skipAsciiWhitespace = function(string4, index2) { + var length = string4.length; + for (; index2 < length; index2++) { + var chr = at(string4, index2); + if (chr !== " " && chr !== " " && chr !== "\n" && chr !== "\f" && chr !== "\r") break; + } + return index2; + }; + var decodeBase64Chunk = function(chunk2, alphabet, throwOnExtraBits) { + var chunkLength = chunk2.length; + if (chunkLength < 4) { + chunk2 += chunkLength === 2 ? "AA" : "A"; + } + var triplet = (alphabet[at(chunk2, 0)] << 18) + (alphabet[at(chunk2, 1)] << 12) + (alphabet[at(chunk2, 2)] << 6) + alphabet[at(chunk2, 3)]; + var chunkBytes = [ + triplet >> 16 & 255, + triplet >> 8 & 255, + triplet & 255 + ]; + if (chunkLength === 2) { + if (throwOnExtraBits && chunkBytes[1] !== 0) { + throw new SyntaxError2("Extra bits"); + } + return [chunkBytes[0]]; + } + if (chunkLength === 3) { + if (throwOnExtraBits && chunkBytes[2] !== 0) { + throw new SyntaxError2("Extra bits"); + } + return [chunkBytes[0], chunkBytes[1]]; + } + return chunkBytes; + }; + var writeBytes = function(bytes, elements, written) { + var elementsLength = elements.length; + for (var index2 = 0; index2 < elementsLength; index2++) { + bytes[written + index2] = elements[index2]; + } + return written + elementsLength; + }; + module2.exports = function(string4, options, into, maxLength) { + aString(string4); + anObjectOrUndefined(options); + var alphabet = getAlphabetOption(options) === "base64" ? base64Alphabet : base64UrlAlphabet; + var lastChunkHandling = options ? options.lastChunkHandling : void 0; + if (lastChunkHandling === void 0) lastChunkHandling = "loose"; + if (lastChunkHandling !== "loose" && lastChunkHandling !== "strict" && lastChunkHandling !== "stop-before-partial") { + throw new TypeError2("Incorrect `lastChunkHandling` option"); + } + if (into) notDetached(into.buffer); + var stringLength = string4.length; + var bytes = into || []; + var written = 0; + var read = 0; + var chunk2 = ""; + var index2 = 0; + if (maxLength) while (true) { + index2 = skipAsciiWhitespace(string4, index2); + if (index2 === stringLength) { + if (chunk2.length > 0) { + if (lastChunkHandling === "stop-before-partial") { + break; + } + if (lastChunkHandling === "loose") { + if (chunk2.length === 1) { + throw new SyntaxError2("Malformed padding: exactly one additional character"); + } + written = writeBytes(bytes, decodeBase64Chunk(chunk2, alphabet, false), written); + } else { + throw new SyntaxError2("Missing padding"); + } + } + read = stringLength; + break; + } + var chr = at(string4, index2); + ++index2; + if (chr === "=") { + if (chunk2.length < 2) { + throw new SyntaxError2("Padding is too early"); + } + index2 = skipAsciiWhitespace(string4, index2); + if (chunk2.length === 2) { + if (index2 === stringLength) { + if (lastChunkHandling === "stop-before-partial") { + break; + } + throw new SyntaxError2("Malformed padding: only one ="); + } + if (at(string4, index2) === "=") { + ++index2; + index2 = skipAsciiWhitespace(string4, index2); + } + } + if (index2 < stringLength) { + throw new SyntaxError2("Unexpected character after padding"); + } + written = writeBytes(bytes, decodeBase64Chunk(chunk2, alphabet, lastChunkHandling === "strict"), written); + read = stringLength; + break; + } + if (!hasOwn(alphabet, chr)) { + throw new SyntaxError2("Unexpected character"); + } + var remainingBytes = maxLength - written; + if (remainingBytes === 1 && chunk2.length === 2 || remainingBytes === 2 && chunk2.length === 3) { + break; + } + chunk2 += chr; + if (chunk2.length === 4) { + written = writeBytes(bytes, decodeBase64Chunk(chunk2, alphabet, false), written); + chunk2 = ""; + read = index2; + if (written === maxLength) { + break; + } + } + } + return { bytes, read, written }; + }; + } + ), + /***/ + 9286: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var SetHelpers = __webpack_require__3(4402); + var iterate = __webpack_require__3(8469); + var Set2 = SetHelpers.Set; + var add = SetHelpers.add; + module2.exports = function(set2) { + var result2 = new Set2(); + iterate(set2, function(it) { + add(result2, it); + }); + return result2; + }; + } + ), + /***/ + 9297: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var toObject = __webpack_require__3(8981); + var hasOwnProperty2 = uncurryThis({}.hasOwnProperty); + module2.exports = Object.hasOwn || function hasOwn(it, key) { + return hasOwnProperty2(toObject(it), key); + }; + } + ), + /***/ + 9306: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var tryToString = __webpack_require__3(6823); + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isCallable(argument)) return argument; + throw new $TypeError(tryToString(argument) + " is not a function"); + }; + } + ), + /***/ + 9429: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var IS_NODE = __webpack_require__3(6193); + module2.exports = function(name) { + if (IS_NODE) { + try { + return globalThis2.process.getBuiltinModule(name); + } catch (error62) { + } + try { + return Function('return require("' + name + '")')(); + } catch (error62) { + } + } + }; + } + ), + /***/ + 9432: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(5213); + } + ), + /***/ + 9433: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var defineProperty = Object.defineProperty; + module2.exports = function(key, value) { + try { + defineProperty(globalThis2, key, { value, configurable: true, writable: true }); + } catch (error62) { + globalThis2[key] = value; + } + return value; + }; + } + ), + /***/ + 9462: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var create2 = __webpack_require__3(2360); + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIns = __webpack_require__3(6279); + var wellKnownSymbol = __webpack_require__3(8227); + var InternalStateModule = __webpack_require__3(1181); + var getMethod = __webpack_require__3(5966); + var IteratorPrototype = __webpack_require__3(7657).IteratorPrototype; + var createIterResultObject = __webpack_require__3(2529); + var iteratorClose = __webpack_require__3(9539); + var iteratorCloseAll = __webpack_require__3(1385); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var ITERATOR_HELPER = "IteratorHelper"; + var WRAP_FOR_VALID_ITERATOR = "WrapForValidIterator"; + var NORMAL2 = "normal"; + var THROW = "throw"; + var setInternalState = InternalStateModule.set; + var createIteratorProxyPrototype = function(IS_ITERATOR) { + var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER); + return defineBuiltIns(create2(IteratorPrototype), { + next: function next() { + var state = getInternalState(this); + if (IS_ITERATOR) return state.nextHandler(); + if (state.done) return createIterResultObject(void 0, true); + try { + var result2 = state.nextHandler(); + return state.returnHandlerResult ? result2 : createIterResultObject(result2, state.done); + } catch (error62) { + state.done = true; + throw error62; + } + }, + "return": function() { + var state = getInternalState(this); + var iterator = state.iterator; + state.done = true; + if (IS_ITERATOR) { + var returnMethod = getMethod(iterator, "return"); + return returnMethod ? call(returnMethod, iterator) : createIterResultObject(void 0, true); + } + if (state.inner) try { + iteratorClose(state.inner.iterator, NORMAL2); + } catch (error62) { + return iteratorClose(iterator, THROW, error62); + } + if (state.openIters) try { + iteratorCloseAll(state.openIters, NORMAL2); + } catch (error62) { + return iteratorClose(iterator, THROW, error62); + } + if (iterator) iteratorClose(iterator, NORMAL2); + return createIterResultObject(void 0, true); + } + }); + }; + var WrapForValidIteratorPrototype = createIteratorProxyPrototype(true); + var IteratorHelperPrototype = createIteratorProxyPrototype(false); + createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, "Iterator Helper"); + module2.exports = function(nextHandler, IS_ITERATOR, RETURN_HANDLER_RESULT) { + var IteratorProxy = function Iterator2(record2, state) { + if (state) { + state.iterator = record2.iterator; + state.next = record2.next; + } else state = record2; + state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER; + state.returnHandlerResult = !!RETURN_HANDLER_RESULT; + state.nextHandler = nextHandler; + state.counter = 0; + state.done = false; + setInternalState(this, state); + }; + IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype; + return IteratorProxy; + }; + } + ), + /***/ + 9479: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var defineBuiltInAccessor = __webpack_require__3(2106); + var regExpFlagsDetection = __webpack_require__3(7594); + var regExpFlagsGetterImplementation = __webpack_require__3(7979); + if (DESCRIPTORS && !regExpFlagsDetection.correct) { + defineBuiltInAccessor(RegExp.prototype, "flags", { + configurable: true, + get: regExpFlagsGetterImplementation + }); + regExpFlagsDetection.correct = true; + } + } + ), + /***/ + 9486: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anObjectOrUndefined = __webpack_require__3(3972); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var base64Map = __webpack_require__3(2804); + var getAlphabetOption = __webpack_require__3(944); + var base64Alphabet = base64Map.i2c; + var base64UrlAlphabet = base64Map.i2cUrl; + var charAt = uncurryThis("".charAt); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !function() { + try { + var target = new Uint8Array2(); + target.toBase64(null); + } catch (error62) { + return true; + } + }(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + toBase64: function toBase64() { + var array2 = anUint8Array(this); + var options = arguments.length ? anObjectOrUndefined(arguments[0]) : void 0; + var alphabet = getAlphabetOption(options) === "base64" ? base64Alphabet : base64UrlAlphabet; + var omitPadding = !!options && !!options.omitPadding; + notDetached(this.buffer); + var result2 = ""; + var i = 0; + var length = array2.length; + var triplet; + var at = function(shift) { + return charAt(alphabet, triplet >> 6 * shift & 63); + }; + for (; i + 2 < length; i += 3) { + triplet = (array2[i] << 16) + (array2[i + 1] << 8) + array2[i + 2]; + result2 += at(3) + at(2) + at(1) + at(0); + } + if (i + 2 === length) { + triplet = (array2[i] << 16) + (array2[i + 1] << 8); + result2 += at(3) + at(2) + at(1) + (omitPadding ? "" : "="); + } else if (i + 1 === length) { + triplet = array2[i] << 16; + result2 += at(3) + at(2) + (omitPadding ? "" : "=="); + } + return result2; + } + }); + } + ), + /***/ + 9504: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); + var FunctionPrototype = Function.prototype; + var call = FunctionPrototype.call; + var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call); + module2.exports = NATIVE_BIND ? uncurryThisWithBind : function(fn) { + return function() { + return call.apply(fn, arguments); + }; + }; + } + ), + /***/ + 9519: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var userAgent = __webpack_require__3(2839); + var process2 = globalThis2.process; + var Deno2 = globalThis2.Deno; + var versions = process2 && process2.versions || Deno2 && Deno2.version; + var v8 = versions && versions.v8; + var match, version4; + if (v8) { + match = v8.split("."); + version4 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); + } + if (!version4 && userAgent) { + match = userAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = userAgent.match(/Chrome\/(\d+)/); + if (match) version4 = +match[1]; + } + } + module2.exports = version4; + } + ), + /***/ + 9539: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getMethod = __webpack_require__3(5966); + module2.exports = function(iterator, kind, value) { + var innerResult, innerError; + anObject(iterator); + try { + innerResult = getMethod(iterator, "return"); + if (!innerResult) { + if (kind === "throw") throw value; + return value; + } + innerResult = call(innerResult, iterator); + } catch (error62) { + innerError = true; + innerResult = error62; + } + if (kind === "throw") throw value; + if (innerError) throw innerResult; + anObject(innerResult); + return value; + }; + } + ), + /***/ + 9565: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); + var call = Function.prototype.call; + module2.exports = NATIVE_BIND ? call.bind(call) : function() { + return call.apply(call, arguments); + }; + } + ), + /***/ + 9577: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var arrayWith = __webpack_require__3(9928); + var ArrayBufferViewCore = __webpack_require__3(4644); + var isBigIntArray = __webpack_require__3(1108); + var toIntegerOrInfinity = __webpack_require__3(1291); + var toBigInt = __webpack_require__3(5854); + var aTypedArray = ArrayBufferViewCore.aTypedArray; + var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor; + var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; + var PROPER_ORDER = function() { + try { + new Int8Array(1)["with"](2, { valueOf: function() { + throw 8; + } }); + } catch (error62) { + return error62 === 8; + } + }(); + var THROW_ON_NEGATIVE_FRACTIONAL_INDEX = PROPER_ORDER && function() { + try { + new Int8Array(1)["with"](-0.5, 1); + } catch (error62) { + return true; + } + }(); + exportTypedArrayMethod("with", { "with": function(index2, value) { + var O = aTypedArray(this); + var relativeIndex = toIntegerOrInfinity(index2); + var actualValue = isBigIntArray(O) ? toBigInt(value) : +value; + return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue); + } }["with"], !PROPER_ORDER || THROW_ON_NEGATIVE_FRACTIONAL_INDEX); + } + ), + /***/ + 9617: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIndexedObject = __webpack_require__3(5397); + var toAbsoluteIndex = __webpack_require__3(5610); + var lengthOfArrayLike = __webpack_require__3(6198); + var createMethod = function(IS_INCLUDES) { + return function($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = lengthOfArrayLike(O); + if (length === 0) return !IS_INCLUDES && -1; + var index2 = toAbsoluteIndex(fromIndex, length); + var value; + if (IS_INCLUDES && el !== el) while (length > index2) { + value = O[index2++]; + if (value !== value) return true; + } + else for (; length > index2; index2++) { + if ((IS_INCLUDES || index2 in O) && O[index2] === el) return IS_INCLUDES || index2 || 0; + } + return !IS_INCLUDES && -1; + }; + }; + module2.exports = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod(false) + }; + } + ), + /***/ + 9631: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(9486); + } + ), + /***/ + 9797: ( + /***/ + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(4226); + } + ), + /***/ + 9835: ( + /***/ + (module2) => { + module2.exports = function(METHOD_NAME) { + try { + var baseSet = /* @__PURE__ */ new Set(); + var setLike = { + size: 0, + has: function() { + return true; + }, + keys: function() { + return Object.defineProperty({}, "next", { + get: function() { + baseSet.clear(); + baseSet.add(4); + return function() { + return { done: true }; + }; + } + }); + } + }; + var result2 = baseSet[METHOD_NAME](setLike); + return result2.size === 1 && result2.values().next().value === 4; + } catch (error62) { + return false; + } + }; + } + ), + /***/ + 9928: ( + /***/ + (module2, __unused_webpack_exports, __webpack_require__3) => { + var lengthOfArrayLike = __webpack_require__3(6198); + var toIntegerOrInfinity = __webpack_require__3(1291); + var $RangeError = RangeError; + module2.exports = function(O, C, index2, value) { + var len = lengthOfArrayLike(O); + var relativeIndex = toIntegerOrInfinity(index2); + var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex; + if (actualIndex >= len || actualIndex < 0) throw new $RangeError("Incorrect index"); + var A2 = new C(len); + var k = 0; + for (; k < len; k++) A2[k] = k === actualIndex ? value : O[k]; + return A2; + }; + } + ) + /******/ + }; + __webpack_module_cache__2 = {}; + (() => { + __webpack_require__2.d = (exports2, definition) => { + for (var key in definition) { + if (__webpack_require__2.o(definition, key) && !__webpack_require__2.o(exports2, key)) { + Object.defineProperty(exports2, key, { enumerable: true, get: definition[key] }); + } + } + }; + })(); + (() => { + __webpack_require__2.o = (obj2, prop) => Object.prototype.hasOwnProperty.call(obj2, prop); + })(); + es_array_push2 = __webpack_require__2(4114); + es_array_buffer_detached2 = __webpack_require__2(6573); + es_array_buffer_transfer2 = __webpack_require__2(8100); + es_array_buffer_transfer_to_fixed_length2 = __webpack_require__2(7936); + es_iterator_constructor2 = __webpack_require__2(8111); + es_iterator_filter2 = __webpack_require__2(2489); + es_iterator_map2 = __webpack_require__2(1701); + es_iterator_some2 = __webpack_require__2(3579); + es_promise_with_resolvers2 = __webpack_require__2(4628); + es_set_difference_v22 = __webpack_require__2(7642); + es_set_intersection_v22 = __webpack_require__2(8004); + es_set_is_disjoint_from_v22 = __webpack_require__2(3853); + es_set_is_subset_of_v22 = __webpack_require__2(5876); + es_set_is_superset_of_v22 = __webpack_require__2(2475); + es_set_symmetric_difference_v22 = __webpack_require__2(5024); + es_set_union_v22 = __webpack_require__2(1698); + es_typed_array_with2 = __webpack_require__2(9577); + esnext_uint8_array_set_from_base642 = __webpack_require__2(1549); + esnext_uint8_array_set_from_hex2 = __webpack_require__2(9797); + esnext_uint8_array_to_base642 = __webpack_require__2(9631); + esnext_uint8_array_to_hex2 = __webpack_require__2(5623); + web_self = __webpack_require__2(3611); + es_iterator_reduce2 = __webpack_require__2(8237); + es_promise_try2 = __webpack_require__2(1689); + esnext_math_sum_precise2 = __webpack_require__2(4235); + esnext_uint8_array_from_base642 = __webpack_require__2(9432); + web_dom_exception_stack2 = __webpack_require__2(4979); + web_url_parse2 = __webpack_require__2(5781); + isNodeJS2 = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser"); + FONT_IDENTITY_MATRIX2 = [1e-3, 0, 0, 1e-3, 0, 0]; + LINE_FACTOR2 = 1.35; + LINE_DESCENT_FACTOR2 = 0.35; + BASELINE_FACTOR2 = LINE_DESCENT_FACTOR2 / LINE_FACTOR2; + RenderingIntentFlag2 = { + ANY: 1, + DISPLAY: 2, + PRINT: 4, + SAVE: 8, + ANNOTATIONS_FORMS: 16, + ANNOTATIONS_STORAGE: 32, + ANNOTATIONS_DISABLE: 64, + IS_EDITING: 128, + OPLIST: 256 + }; + AnnotationEditorPrefix2 = "pdfjs_internal_editor_"; + AnnotationEditorType2 = { + DISABLE: -1, + NONE: 0, + FREETEXT: 3, + HIGHLIGHT: 9, + STAMP: 13, + INK: 15, + POPUP: 16, + SIGNATURE: 101, + COMMENT: 102 + }; + PermissionFlag2 = { + PRINT: 4, + MODIFY_CONTENTS: 8, + COPY: 16, + MODIFY_ANNOTATIONS: 32, + FILL_INTERACTIVE_FORMS: 256, + COPY_FOR_ACCESSIBILITY: 512, + ASSEMBLE: 1024, + PRINT_HIGH_QUALITY: 2048 + }; + TextRenderingMode2 = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_ADD_TO_PATH: 4, + STROKE_ADD_TO_PATH: 5, + FILL_STROKE_ADD_TO_PATH: 6, + ADD_TO_PATH: 7, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 + }; + ImageKind2 = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 + }; + AnnotationType2 = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 + }; + AnnotationReplyType = { + GROUP: "Group", + REPLY: "R" + }; + AnnotationFlag = { + INVISIBLE: 1, + HIDDEN: 2, + PRINT: 4, + NOZOOM: 8, + NOROTATE: 16, + NOVIEW: 32, + READONLY: 64, + LOCKED: 128, + TOGGLENOVIEW: 256, + LOCKEDCONTENTS: 512 + }; + AnnotationFieldFlag = { + READONLY: 1, + REQUIRED: 2, + NOEXPORT: 4, + MULTILINE: 4096, + PASSWORD: 8192, + NOTOGGLETOOFF: 16384, + RADIO: 32768, + PUSHBUTTON: 65536, + COMBO: 131072, + EDIT: 262144, + SORT: 524288, + FILESELECT: 1048576, + MULTISELECT: 2097152, + DONOTSPELLCHECK: 4194304, + DONOTSCROLL: 8388608, + COMB: 16777216, + RICHTEXT: 33554432, + RADIOSINUNISON: 33554432, + COMMITONSELCHANGE: 67108864 + }; + AnnotationBorderStyleType2 = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 + }; + AnnotationActionEventType = { + E: "Mouse Enter", + X: "Mouse Exit", + D: "Mouse Down", + U: "Mouse Up", + Fo: "Focus", + Bl: "Blur", + PO: "PageOpen", + PC: "PageClose", + PV: "PageVisible", + PI: "PageInvisible", + K: "Keystroke", + F: "Format", + V: "Validate", + C: "Calculate" + }; + DocumentActionEventType = { + WC: "WillClose", + WS: "WillSave", + DS: "DidSave", + WP: "WillPrint", + DP: "DidPrint" + }; + PageActionEventType = { + O: "PageOpen", + C: "PageClose" + }; + VerbosityLevel2 = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 + }; + OPS2 = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotation: 80, + endAnnotation: 81, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91, + setStrokeTransparent: 92, + setFillTransparent: 93, + rawFillPath: 94 + }; + DrawOPS3 = { + moveTo: 0, + lineTo: 1, + curveTo: 2, + closePath: 3 + }; + PasswordResponses2 = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 + }; + verbosity2 = VerbosityLevel2.WARNINGS; + BaseException2 = function BaseExceptionClosure2() { + function BaseException3(message2, name) { + this.message = message2; + this.name = name; + } + BaseException3.prototype = new Error(); + BaseException3.constructor = BaseException3; + return BaseException3; + }(); + PasswordException3 = class extends BaseException2 { + constructor(msg, code) { + super(msg, "PasswordException"); + this.code = code; + } + }; + UnknownErrorException3 = class extends BaseException2 { + constructor(msg, details) { + super(msg, "UnknownErrorException"); + this.details = details; + } + }; + InvalidPDFException3 = class extends BaseException2 { + constructor(msg) { + super(msg, "InvalidPDFException"); + } + }; + ResponseException3 = class extends BaseException2 { + constructor(msg, status, missing) { + super(msg, "ResponseException"); + this.status = status; + this.missing = missing; + } + }; + FormatError3 = class extends BaseException2 { + constructor(msg) { + super(msg, "FormatError"); + } + }; + AbortException3 = class extends BaseException2 { + constructor(msg) { + super(msg, "AbortException"); + } + }; + FeatureTest2 = class { + static get isLittleEndian() { + return shadow2(this, "isLittleEndian", isLittleEndian2()); + } + static get isEvalSupported() { + return shadow2(this, "isEvalSupported", isEvalSupported2()); + } + static get isOffscreenCanvasSupported() { + return shadow2(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); + } + static get isImageDecoderSupported() { + return shadow2(this, "isImageDecoderSupported", typeof ImageDecoder !== "undefined"); + } + static get platform() { + const { + platform, + userAgent + } = navigator; + return shadow2(this, "platform", { + isAndroid: userAgent.includes("Android"), + isLinux: platform.includes("Linux"), + isMac: platform.includes("Mac"), + isWindows: platform.includes("Win"), + isFirefox: userAgent.includes("Firefox") + }); + } + static get isCSSRoundSupported() { + return shadow2(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)")); + } + }; + hexNumbers2 = Array.from(Array(256).keys(), (n) => n.toString(16).padStart(2, "0")); + Util2 = class { + static makeHexColor(r, g, b2) { + return `#${hexNumbers2[r]}${hexNumbers2[g]}${hexNumbers2[b2]}`; + } + static domMatrixToTransform(dm) { + return [dm.a, dm.b, dm.c, dm.d, dm.e, dm.f]; + } + static scaleMinMax(transform2, minMax) { + let temp; + if (transform2[0]) { + if (transform2[0] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform2[0]; + minMax[2] *= transform2[0]; + if (transform2[3] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform2[3]; + minMax[3] *= transform2[3]; + } else { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + if (transform2[1] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform2[1]; + minMax[3] *= transform2[1]; + if (transform2[2] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform2[2]; + minMax[2] *= transform2[2]; + } + minMax[0] += transform2[4]; + minMax[1] += transform2[5]; + minMax[2] += transform2[4]; + minMax[3] += transform2[5]; + } + static transform(m1, m2) { + return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; + } + static multiplyByDOMMatrix(m, md) { + return [m[0] * md.a + m[2] * md.b, m[1] * md.a + m[3] * md.b, m[0] * md.c + m[2] * md.d, m[1] * md.c + m[3] * md.d, m[0] * md.e + m[2] * md.f + m[4], m[1] * md.e + m[3] * md.f + m[5]]; + } + static applyTransform(p, m, pos = 0) { + const p0 = p[pos]; + const p1 = p[pos + 1]; + p[pos] = p0 * m[0] + p1 * m[2] + m[4]; + p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5]; + } + static applyTransformToBezier(p, transform2, pos = 0) { + const m0 = transform2[0]; + const m1 = transform2[1]; + const m2 = transform2[2]; + const m3 = transform2[3]; + const m4 = transform2[4]; + const m5 = transform2[5]; + for (let i = 0; i < 6; i += 2) { + const pI = p[pos + i]; + const pI1 = p[pos + i + 1]; + p[pos + i] = pI * m0 + pI1 * m2 + m4; + p[pos + i + 1] = pI * m1 + pI1 * m3 + m5; + } + } + static applyInverseTransform(p, m) { + const p0 = p[0]; + const p1 = p[1]; + const d = m[0] * m[3] - m[1] * m[2]; + p[0] = (p0 * m[3] - p1 * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + p[1] = (-p0 * m[1] + p1 * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + } + static axialAlignedBoundingBox(rect, transform2, output2) { + const m0 = transform2[0]; + const m1 = transform2[1]; + const m2 = transform2[2]; + const m3 = transform2[3]; + const m4 = transform2[4]; + const m5 = transform2[5]; + const r0 = rect[0]; + const r1 = rect[1]; + const r2 = rect[2]; + const r3 = rect[3]; + let a0 = m0 * r0 + m4; + let a2 = a0; + let a1 = m0 * r2 + m4; + let a3 = a1; + let b0 = m3 * r1 + m5; + let b2 = b0; + let b1 = m3 * r3 + m5; + let b3 = b1; + if (m1 !== 0 || m2 !== 0) { + const m1r0 = m1 * r0; + const m1r2 = m1 * r2; + const m2r1 = m2 * r1; + const m2r3 = m2 * r3; + a0 += m2r1; + a3 += m2r1; + a1 += m2r3; + a2 += m2r3; + b0 += m1r0; + b3 += m1r0; + b1 += m1r2; + b2 += m1r2; + } + output2[0] = Math.min(output2[0], a0, a1, a2, a3); + output2[1] = Math.min(output2[1], b0, b1, b2, b3); + output2[2] = Math.max(output2[2], a0, a1, a2, a3); + output2[3] = Math.max(output2[3], b0, b1, b2, b3); + } + static inverseTransform(m) { + const d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + } + static singularValueDecompose2dScale(matrix, output2) { + const m0 = matrix[0]; + const m1 = matrix[1]; + const m2 = matrix[2]; + const m3 = matrix[3]; + const a = m0 ** 2 + m1 ** 2; + const b2 = m0 * m2 + m1 * m3; + const c = m2 ** 2 + m3 ** 2; + const first2 = (a + c) / 2; + const second = Math.sqrt(first2 ** 2 - (a * c - b2 ** 2)); + output2[0] = Math.sqrt(first2 + second || 1); + output2[1] = Math.sqrt(first2 - second || 1); + } + static normalizeRect(rect) { + const r = rect.slice(0); + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + } + static intersect(rect1, rect2) { + const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); + const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); + if (xLow > xHigh) { + return null; + } + const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); + const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); + if (yLow > yHigh) { + return null; + } + return [xLow, yLow, xHigh, yHigh]; + } + static pointBoundingBox(x, y, minMax) { + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static rectBoundingBox(x0, y0, x1, y1, minMax) { + minMax[0] = Math.min(minMax[0], x0, x1); + minMax[1] = Math.min(minMax[1], y0, y1); + minMax[2] = Math.max(minMax[2], x0, x1); + minMax[3] = Math.max(minMax[3], y0, y1); + } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; + } + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b2, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b2) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b2, minMax); + } + return; + } + const delta = b2 ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b2 + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b2 - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + } + }; + PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 728, 711, 710, 729, 733, 731, 730, 732, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8226, 8224, 8225, 8230, 8212, 8211, 402, 8260, 8249, 8250, 8722, 8240, 8222, 8220, 8221, 8216, 8217, 8218, 8482, 64257, 64258, 321, 338, 352, 376, 381, 305, 322, 339, 353, 382, 0, 8364]; + NormalizeRegex2 = null; + NormalizationMap2 = null; + AnnotationPrefix2 = "pdfjs_internal_id_"; + if (typeof Math.sumPrecise !== "function") { + Math.sumPrecise = function(numbers) { + return numbers.reduce((a, b2) => a + b2, 0); + }; + } + if (typeof AbortSignal.any !== "function") { + AbortSignal.any = function(iterable) { + const ac = new AbortController(); + const { + signal + } = ac; + for (const s of iterable) { + if (s.aborted) { + ac.abort(s.reason); + return signal; + } + } + for (const s of iterable) { + s.addEventListener("abort", () => { + ac.abort(s.reason); + }, { + signal + }); + } + return signal; + }; + } + es_iterator_every2 = __webpack_require__2(1148); + CIRCULAR_REF = Symbol("CIRCULAR_REF"); + EOF = Symbol("EOF"); + CmdCache = /* @__PURE__ */ Object.create(null); + NameCache = /* @__PURE__ */ Object.create(null); + RefCache = /* @__PURE__ */ Object.create(null); + Name2 = class _Name { + constructor(name) { + this.name = name; + } + static get(name) { + return NameCache[name] ||= new _Name(name); + } + }; + Cmd = class _Cmd { + constructor(cmd) { + this.cmd = cmd; + } + static get(cmd) { + return CmdCache[cmd] ||= new _Cmd(cmd); + } + }; + nonSerializable = function nonSerializableClosure() { + return nonSerializable; + }; + Dict = class _Dict { + constructor(xref = null) { + this._map = /* @__PURE__ */ new Map(); + this.xref = xref; + this.objId = null; + this.suppressEncryption = false; + this.__nonSerializable__ = nonSerializable; + } + assignXref(newXref) { + this.xref = newXref; + } + get size() { + return this._map.size; + } + get(key1, key2, key3) { + let value = this._map.get(key1); + if (value === void 0 && key2 !== void 0) { + value = this._map.get(key2); + if (value === void 0 && key3 !== void 0) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + return this.xref.fetch(value, this.suppressEncryption); + } + return value; + } + async getAsync(key1, key2, key3) { + let value = this._map.get(key1); + if (value === void 0 && key2 !== void 0) { + value = this._map.get(key2); + if (value === void 0 && key3 !== void 0) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + return this.xref.fetchAsync(value, this.suppressEncryption); + } + return value; + } + getArray(key1, key2, key3) { + let value = this._map.get(key1); + if (value === void 0 && key2 !== void 0) { + value = this._map.get(key2); + if (value === void 0 && key3 !== void 0) { + value = this._map.get(key3); + } + } + if (value instanceof Ref && this.xref) { + value = this.xref.fetch(value, this.suppressEncryption); + } + if (Array.isArray(value)) { + value = value.slice(); + for (let i = 0, ii = value.length; i < ii; i++) { + if (value[i] instanceof Ref && this.xref) { + value[i] = this.xref.fetch(value[i], this.suppressEncryption); + } + } + } + return value; + } + getRaw(key) { + return this._map.get(key); + } + getKeys() { + return [...this._map.keys()]; + } + getRawValues() { + return [...this._map.values()]; + } + set(key, value) { + this._map.set(key, value); + } + setIfNotExists(key, value) { + if (!this.has(key)) { + this.set(key, value); + } + } + setIfNumber(key, value) { + if (typeof value === "number") { + this.set(key, value); + } + } + setIfArray(key, value) { + if (Array.isArray(value) || ArrayBuffer.isView(value)) { + this.set(key, value); + } + } + setIfDefined(key, value) { + if (value !== void 0 && value !== null) { + this.set(key, value); + } + } + setIfName(key, value) { + if (typeof value === "string") { + this.set(key, Name2.get(value)); + } else if (value instanceof Name2) { + this.set(key, value); + } + } + has(key) { + return this._map.has(key); + } + *[Symbol.iterator]() { + for (const [key, value] of this._map) { + yield [key, value instanceof Ref && this.xref ? this.xref.fetch(value, this.suppressEncryption) : value]; + } + } + static get empty() { + const emptyDict = new _Dict(null); + emptyDict.set = (key, value) => { + unreachable2("Should not call `set` on the empty dictionary."); + }; + return shadow2(this, "empty", emptyDict); + } + static merge({ + xref, + dictArray, + mergeSubDicts = false + }) { + const mergedDict = new _Dict(xref), properties = /* @__PURE__ */ new Map(); + for (const dict of dictArray) { + if (!(dict instanceof _Dict)) { + continue; + } + for (const [key, value] of dict._map) { + let property2 = properties.get(key); + if (property2 === void 0) { + property2 = []; + properties.set(key, property2); + } else if (!mergeSubDicts || !(value instanceof _Dict)) { + continue; + } + property2.push(value); + } + } + for (const [name, values3] of properties) { + if (values3.length === 1 || !(values3[0] instanceof _Dict)) { + mergedDict._map.set(name, values3[0]); + continue; + } + const subDict = new _Dict(xref); + for (const dict of values3) { + for (const [key, value] of dict._map) { + if (!subDict._map.has(key)) { + subDict._map.set(key, value); + } + } + } + if (subDict.size > 0) { + mergedDict._map.set(name, subDict); + } + } + properties.clear(); + return mergedDict.size > 0 ? mergedDict : _Dict.empty; + } + clone() { + const dict = new _Dict(this.xref); + for (const key of this.getKeys()) { + dict.set(key, this.getRaw(key)); + } + return dict; + } + delete(key) { + this._map.delete(key); + } + }; + Ref = class _Ref { + constructor(num, gen) { + this.num = num; + this.gen = gen; + } + toString() { + if (this.gen === 0) { + return `${this.num}R`; + } + return `${this.num}R${this.gen}`; + } + static fromString(str) { + const ref = RefCache[str]; + if (ref) { + return ref; + } + const m = /^(\d+)R(\d*)$/.exec(str); + if (!m || m[1] === "0") { + return null; + } + return RefCache[str] = new _Ref(parseInt(m[1]), !m[2] ? 0 : parseInt(m[2])); + } + static get(num, gen) { + const key = gen === 0 ? `${num}R` : `${num}R${gen}`; + return RefCache[key] ||= new _Ref(num, gen); + } + }; + RefSet = class { + constructor(parent = null) { + this._set = new Set(parent?._set); + } + has(ref) { + return this._set.has(ref.toString()); + } + put(ref) { + this._set.add(ref.toString()); + } + remove(ref) { + this._set.delete(ref.toString()); + } + [Symbol.iterator]() { + return this._set.values(); + } + clear() { + this._set.clear(); + } + }; + RefSetCache = class { + constructor() { + this._map = /* @__PURE__ */ new Map(); + } + get size() { + return this._map.size; + } + get(ref) { + return this._map.get(ref.toString()); + } + has(ref) { + return this._map.has(ref.toString()); + } + put(ref, obj2) { + this._map.set(ref.toString(), obj2); + } + putAlias(ref, aliasRef) { + this._map.set(ref.toString(), this.get(aliasRef)); + } + [Symbol.iterator]() { + return this._map.values(); + } + clear() { + this._map.clear(); + } + *values() { + yield* this._map.values(); + } + *items() { + for (const [ref, value] of this._map) { + yield [Ref.fromString(ref), value]; + } + } + }; + BaseStream = class { + get length() { + unreachable2("Abstract getter `length` accessed"); + } + get isEmpty() { + unreachable2("Abstract getter `isEmpty` accessed"); + } + get isDataLoaded() { + return shadow2(this, "isDataLoaded", true); + } + getByte() { + unreachable2("Abstract method `getByte` called"); + } + getBytes(length) { + unreachable2("Abstract method `getBytes` called"); + } + async getImageData(length, decoderOptions) { + return this.getBytes(length, decoderOptions); + } + async asyncGetBytes() { + unreachable2("Abstract method `asyncGetBytes` called"); + } + get isAsync() { + return false; + } + get isAsyncDecoder() { + return false; + } + get canAsyncDecodeImageFromBuffer() { + return false; + } + async getTransferableImage() { + return null; + } + peekByte() { + const peekedByte = this.getByte(); + if (peekedByte !== -1) { + this.pos--; + } + return peekedByte; + } + peekBytes(length) { + const bytes = this.getBytes(length); + this.pos -= bytes.length; + return bytes; + } + getUint16() { + const b0 = this.getByte(); + const b1 = this.getByte(); + if (b0 === -1 || b1 === -1) { + return -1; + } + return (b0 << 8) + b1; + } + getInt32() { + const b0 = this.getByte(); + const b1 = this.getByte(); + const b2 = this.getByte(); + const b3 = this.getByte(); + return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3; + } + getByteRange(begin, end) { + unreachable2("Abstract method `getByteRange` called"); + } + getString(length) { + return bytesToString2(this.getBytes(length)); + } + skip(n) { + this.pos += n || 1; + } + reset() { + unreachable2("Abstract method `reset` called"); + } + moveStart() { + unreachable2("Abstract method `moveStart` called"); + } + makeSubStream(start, length, dict = null) { + unreachable2("Abstract method `makeSubStream` called"); + } + getBaseStreams() { + return null; + } + }; + PDF_VERSION_REGEXP = /^[1-9]\.\d$/; + MAX_INT_32 = 2 ** 31 - 1; + MIN_INT_32 = -(2 ** 31); + IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0]; + RESOURCES_KEYS_OPERATOR_LIST = ["ColorSpace", "ExtGState", "Font", "Pattern", "Properties", "Shading", "XObject"]; + RESOURCES_KEYS_TEXT_CONTENT = ["ExtGState", "Font", "Properties", "XObject"]; + MissingDataException = class extends BaseException2 { + constructor(begin, end) { + super(`Missing data [${begin}, ${end})`, "MissingDataException"); + this.begin = begin; + this.end = end; + } + }; + ParserEOFException = class extends BaseException2 { + constructor(msg) { + super(msg, "ParserEOFException"); + } + }; + XRefEntryException = class extends BaseException2 { + constructor(msg) { + super(msg, "XRefEntryException"); + } + }; + XRefParseException = class extends BaseException2 { + constructor(msg) { + super(msg, "XRefParseException"); + } + }; + ROMAN_NUMBER_MAP = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM", "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC", "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]; + XMLEntities = { + 60: "<", + 62: ">", + 38: "&", + 34: """, + 39: "'" + }; + web_url_search_params_delete2 = __webpack_require__2(4603); + web_url_search_params_has2 = __webpack_require__2(7566); + web_url_search_params_size2 = __webpack_require__2(8721); + QCMS = class { + static #memoryArray = null; + static _memory = null; + static _mustAddAlpha = false; + static _destBuffer = null; + static _destOffset = 0; + static _destLength = 0; + static _cssColor = ""; + static _makeHexColor = null; + static get _memoryArray() { + const array2 = this.#memoryArray; + if (array2?.byteLength) { + return array2; + } + return this.#memoryArray = new Uint8Array(this._memory.buffer); + } + }; + cachedTextDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8", { + ignoreBOM: true, + fatal: true + }) : { + decode: () => { + throw Error("TextDecoder not available"); + } + }; + if (typeof TextDecoder !== "undefined") { + cachedTextDecoder.decode(); + } + cachedUint8ArrayMemory0 = null; + WASM_VECTOR_LEN = 0; + DataType = Object.freeze({ + RGB8: 0, + "0": "RGB8", + RGBA8: 1, + "1": "RGBA8", + BGRA8: 2, + "2": "BGRA8", + Gray8: 3, + "3": "Gray8", + GrayA8: 4, + "4": "GrayA8", + CMYK: 5, + "5": "CMYK" + }); + Intent = Object.freeze({ + Perceptual: 0, + "0": "Perceptual", + RelativeColorimetric: 1, + "1": "RelativeColorimetric", + Saturation: 2, + "2": "Saturation", + AbsoluteColorimetric: 3, + "3": "AbsoluteColorimetric" + }); + ColorSpace = class _ColorSpace { + static #rgbBuf = new Uint8ClampedArray(3); + constructor(name, numComps) { + this.name = name; + this.numComps = numComps; + } + getRgb(src, srcOffset, output2 = new Uint8ClampedArray(3)) { + this.getRgbItem(src, srcOffset, output2, 0); + return output2; + } + getRgbHex(src, srcOffset) { + const buffer2 = this.getRgb(src, srcOffset, _ColorSpace.#rgbBuf); + return Util2.makeHexColor(buffer2[0], buffer2[1], buffer2[2]); + } + getRgbItem(src, srcOffset, dest, destOffset) { + unreachable2("Should not call ColorSpace.getRgbItem"); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + unreachable2("Should not call ColorSpace.getRgbBuffer"); + } + getOutputLength(inputLength, alpha01) { + unreachable2("Should not call ColorSpace.getOutputLength"); + } + isPassthrough(bits) { + return false; + } + isDefaultDecode(decodeMap, bpc) { + return _ColorSpace.isDefaultDecode(decodeMap, this.numComps); + } + fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { + const count = originalWidth * originalHeight; + let rgbBuf = null; + const numComponentColors = 1 << bpc; + const needsResizing = originalHeight !== height || originalWidth !== width; + if (this.isPassthrough(bpc)) { + rgbBuf = comps; + } else if (this.numComps === 1 && count > numComponentColors && this.name !== "DeviceGray" && this.name !== "DeviceRGB") { + const allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors); + for (let i = 0; i < numComponentColors; i++) { + allColors[i] = i; + } + const colorMap = new Uint8ClampedArray(numComponentColors * 3); + this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0); + if (!needsResizing) { + let destPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + dest[destPos++] = colorMap[key]; + dest[destPos++] = colorMap[key + 1]; + dest[destPos++] = colorMap[key + 2]; + destPos += alpha01; + } + } else { + rgbBuf = new Uint8Array(count * 3); + let rgbPos = 0; + for (let i = 0; i < count; ++i) { + const key = comps[i] * 3; + rgbBuf[rgbPos++] = colorMap[key]; + rgbBuf[rgbPos++] = colorMap[key + 1]; + rgbBuf[rgbPos++] = colorMap[key + 2]; + } + } + } else if (!needsResizing) { + this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01); + } else { + rgbBuf = new Uint8ClampedArray(count * 3); + this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0); + } + if (rgbBuf) { + if (needsResizing) { + resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01); + } else { + let destPos = 0, rgbPos = 0; + for (let i = 0, ii = width * actualHeight; i < ii; i++) { + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + dest[destPos++] = rgbBuf[rgbPos++]; + destPos += alpha01; + } + } + } + } + get usesZeroToOneRange() { + return shadow2(this, "usesZeroToOneRange", true); + } + static isDefaultDecode(decode4, numComps) { + if (!Array.isArray(decode4)) { + return true; + } + if (numComps * 2 !== decode4.length) { + warn2("The decode map is not the correct length"); + return true; + } + for (let i = 0, ii = decode4.length; i < ii; i += 2) { + if (decode4[i] !== 0 || decode4[i + 1] !== 1) { + return false; + } + } + return true; + } + }; + AlternateCS = class extends ColorSpace { + constructor(numComps, base, tintFn) { + super("Alternate", numComps); + this.base = base; + this.tintFn = tintFn; + this.tmpBuf = new Float32Array(base.numComps); + } + getRgbItem(src, srcOffset, dest, destOffset) { + const tmpBuf = this.tmpBuf; + this.tintFn(src, srcOffset, tmpBuf, 0); + this.base.getRgbItem(tmpBuf, 0, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const tintFn = this.tintFn; + const base = this.base; + const scale = 1 / ((1 << bits) - 1); + const baseNumComps = base.numComps; + const usesZeroToOneRange = base.usesZeroToOneRange; + const isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0; + let pos = isPassthrough ? destOffset : 0; + const baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count); + const numComps = this.numComps; + const scaled = new Float32Array(numComps); + const tinted = new Float32Array(baseNumComps); + let i, j; + for (i = 0; i < count; i++) { + for (j = 0; j < numComps; j++) { + scaled[j] = src[srcOffset++] * scale; + } + tintFn(scaled, 0, tinted, 0); + if (usesZeroToOneRange) { + for (j = 0; j < baseNumComps; j++) { + baseBuf[pos++] = tinted[j] * 255; + } + } else { + base.getRgbItem(tinted, 0, baseBuf, pos); + pos += baseNumComps; + } + } + if (!isPassthrough) { + base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01); + } + } + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01); + } + }; + PatternCS = class extends ColorSpace { + constructor(baseCS) { + super("Pattern", null); + this.base = baseCS; + } + isDefaultDecode(decodeMap, bpc) { + unreachable2("Should not call PatternCS.isDefaultDecode"); + } + }; + IndexedCS = class extends ColorSpace { + constructor(base, highVal, lookup) { + super("Indexed", 1); + this.base = base; + this.highVal = highVal; + const length = base.numComps * (highVal + 1); + this.lookup = new Uint8Array(length); + if (lookup instanceof BaseStream) { + const bytes = lookup.getBytes(length); + this.lookup.set(bytes); + } else if (typeof lookup === "string") { + for (let i = 0; i < length; ++i) { + this.lookup[i] = lookup.charCodeAt(i) & 255; + } + } else { + throw new FormatError3(`IndexedCS - unrecognized lookup table: ${lookup}`); + } + } + getRgbItem(src, srcOffset, dest, destOffset) { + const { + base, + highVal, + lookup + } = this; + const start = MathClamp2(Math.round(src[srcOffset]), 0, highVal) * base.numComps; + base.getRgbBuffer(lookup, start, 1, dest, destOffset, 8, 0); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const { + base, + highVal, + lookup + } = this; + const { + numComps + } = base; + const outputDelta = base.getOutputLength(numComps, alpha01); + for (let i = 0; i < count; ++i) { + const lookupPos = MathClamp2(Math.round(src[srcOffset++]), 0, highVal) * numComps; + base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01); + destOffset += outputDelta; + } + } + getOutputLength(inputLength, alpha01) { + return this.base.getOutputLength(inputLength * this.base.numComps, alpha01); + } + isDefaultDecode(decodeMap, bpc) { + if (!Array.isArray(decodeMap)) { + return true; + } + if (decodeMap.length !== 2) { + warn2("Decode map length is not correct"); + return true; + } + if (!Number.isInteger(bpc) || bpc < 1) { + warn2("Bits per component is not correct"); + return true; + } + return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1; + } + }; + DeviceGrayCS = class extends ColorSpace { + constructor() { + super("DeviceGray", 1); + } + getRgbItem(src, srcOffset, dest, destOffset) { + const c = src[srcOffset] * 255; + dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 255 / ((1 << bits) - 1); + let j = srcOffset, q = destOffset; + for (let i = 0; i < count; ++i) { + const c = scale * src[j++]; + dest[q++] = c; + dest[q++] = c; + dest[q++] = c; + q += alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + } + }; + DeviceRgbCS = class extends ColorSpace { + constructor() { + super("DeviceRGB", 3); + } + getRgbItem(src, srcOffset, dest, destOffset) { + dest[destOffset] = src[srcOffset] * 255; + dest[destOffset + 1] = src[srcOffset + 1] * 255; + dest[destOffset + 2] = src[srcOffset + 2] * 255; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + if (bits === 8 && alpha01 === 0) { + dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset); + return; + } + const scale = 255 / ((1 << bits) - 1); + let j = srcOffset, q = destOffset; + for (let i = 0; i < count; ++i) { + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + dest[q++] = scale * src[j++]; + q += alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } + isPassthrough(bits) { + return bits === 8; + } + }; + DeviceRgbaCS = class extends ColorSpace { + constructor() { + super("DeviceRGBA", 4); + } + getOutputLength(inputLength, _alpha01) { + return inputLength * 4; + } + isPassthrough(bits) { + return bits === 8; + } + fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) { + if (originalHeight !== height || originalWidth !== width) { + resizeRgbaImage(comps, dest, originalWidth, originalHeight, width, height, alpha01); + } else { + copyRgbaImage(comps, dest, alpha01); + } + } + }; + DeviceCmykCS = class extends ColorSpace { + constructor() { + super("DeviceCMYK", 4); + } + #toRgb(src, srcOffset, srcScale, dest, destOffset) { + const c = src[srcOffset] * srcScale; + const m = src[srcOffset + 1] * srcScale; + const y = src[srcOffset + 2] * srcScale; + const k = src[srcOffset + 3] * srcScale; + dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747); + dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578); + dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367); + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, 1, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; i++) { + this.#toRgb(src, srcOffset, scale, dest, destOffset); + srcOffset += 4; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength / 4 * (3 + alpha01) | 0; + } + }; + CalGrayCS = class extends ColorSpace { + constructor(whitePoint, blackPoint, gamma) { + super("CalGray", 1); + if (!whitePoint) { + throw new FormatError3("WhitePoint missing - required for color space CalGray"); + } + [this.XW, this.YW, this.ZW] = whitePoint; + [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0]; + this.G = gamma || 1; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError3(`Invalid WhitePoint components for ${this.name}, no fallback available`); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info2(`Invalid BlackPoint for ${this.name}, falling back to default.`); + this.XB = this.YB = this.ZB = 0; + } + if (this.XB !== 0 || this.YB !== 0 || this.ZB !== 0) { + warn2(`${this.name}, BlackPoint: XB: ${this.XB}, YB: ${this.YB}, ZB: ${this.ZB}, only default values are supported.`); + } + if (this.G < 1) { + info2(`Invalid Gamma: ${this.G} for ${this.name}, falling back to default.`); + this.G = 1; + } + } + #toRgb(src, srcOffset, dest, destOffset, scale) { + const A2 = src[srcOffset] * scale; + const AG = A2 ** this.G; + const L = this.YW * AG; + const val = Math.max(295.8 * L ** 0.3333333333333333 - 40.8, 0); + dest[destOffset] = val; + dest[destOffset + 1] = val; + dest[destOffset + 2] = val; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, dest, destOffset, 1); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; ++i) { + this.#toRgb(src, srcOffset, dest, destOffset, scale); + srcOffset += 1; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01); + } + }; + CalRGBCS = class _CalRGBCS extends ColorSpace { + static #BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]); + static #BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -85287e-7, 0.0400428, 0.9684867]); + static #SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.969266, 1.8760108, 0.041556, 0.0556434, -0.2040259, 1.0572252]); + static #FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]); + static #tempNormalizeMatrix = new Float32Array(3); + static #tempConvertMatrix1 = new Float32Array(3); + static #tempConvertMatrix2 = new Float32Array(3); + static #DECODE_L_CONSTANT = ((8 + 16) / 116) ** 3 / 8; + constructor(whitePoint, blackPoint, gamma, matrix) { + super("CalRGB", 3); + if (!whitePoint) { + throw new FormatError3("WhitePoint missing - required for color space CalRGB"); + } + const [XW, YW, ZW] = this.whitePoint = whitePoint; + const [XB, YB, ZB] = this.blackPoint = blackPoint || new Float32Array(3); + [this.GR, this.GG, this.GB] = gamma || new Float32Array([1, 1, 1]); + [this.MXA, this.MYA, this.MZA, this.MXB, this.MYB, this.MZB, this.MXC, this.MYC, this.MZC] = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]); + if (XW < 0 || ZW < 0 || YW !== 1) { + throw new FormatError3(`Invalid WhitePoint components for ${this.name}, no fallback available`); + } + if (XB < 0 || YB < 0 || ZB < 0) { + info2(`Invalid BlackPoint for ${this.name} [${XB}, ${YB}, ${ZB}], falling back to default.`); + this.blackPoint = new Float32Array(3); + } + if (this.GR < 0 || this.GG < 0 || this.GB < 0) { + info2(`Invalid Gamma [${this.GR}, ${this.GG}, ${this.GB}] for ${this.name}, falling back to default.`); + this.GR = this.GG = this.GB = 1; + } + } + #matrixProduct(a, b2, result2) { + result2[0] = a[0] * b2[0] + a[1] * b2[1] + a[2] * b2[2]; + result2[1] = a[3] * b2[0] + a[4] * b2[1] + a[5] * b2[2]; + result2[2] = a[6] * b2[0] + a[7] * b2[1] + a[8] * b2[2]; + } + #toFlat(sourceWhitePoint, LMS, result2) { + result2[0] = LMS[0] * 1 / sourceWhitePoint[0]; + result2[1] = LMS[1] * 1 / sourceWhitePoint[1]; + result2[2] = LMS[2] * 1 / sourceWhitePoint[2]; + } + #toD65(sourceWhitePoint, LMS, result2) { + const D65X = 0.95047; + const D65Y = 1; + const D65Z = 1.08883; + result2[0] = LMS[0] * D65X / sourceWhitePoint[0]; + result2[1] = LMS[1] * D65Y / sourceWhitePoint[1]; + result2[2] = LMS[2] * D65Z / sourceWhitePoint[2]; + } + #sRGBTransferFunction(color) { + if (color <= 31308e-7) { + return MathClamp2(12.92 * color, 0, 1); + } + if (color >= 0.99554525) { + return 1; + } + return MathClamp2((1 + 0.055) * color ** (1 / 2.4) - 0.055, 0, 1); + } + #decodeL(L) { + if (L < 0) { + return -this.#decodeL(-L); + } + if (L > 8) { + return ((L + 16) / 116) ** 3; + } + return L * _CalRGBCS.#DECODE_L_CONSTANT; + } + #compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result2) { + if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) { + result2[0] = XYZ_Flat[0]; + result2[1] = XYZ_Flat[1]; + result2[2] = XYZ_Flat[2]; + return; + } + const zeroDecodeL = this.#decodeL(0); + const X_DST = zeroDecodeL; + const X_SRC = this.#decodeL(sourceBlackPoint[0]); + const Y_DST = zeroDecodeL; + const Y_SRC = this.#decodeL(sourceBlackPoint[1]); + const Z_DST = zeroDecodeL; + const Z_SRC = this.#decodeL(sourceBlackPoint[2]); + const X_Scale = (1 - X_DST) / (1 - X_SRC); + const X_Offset = 1 - X_Scale; + const Y_Scale = (1 - Y_DST) / (1 - Y_SRC); + const Y_Offset = 1 - Y_Scale; + const Z_Scale = (1 - Z_DST) / (1 - Z_SRC); + const Z_Offset = 1 - Z_Scale; + result2[0] = XYZ_Flat[0] * X_Scale + X_Offset; + result2[1] = XYZ_Flat[1] * Y_Scale + Y_Offset; + result2[2] = XYZ_Flat[2] * Z_Scale + Z_Offset; + } + #normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result2) { + if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) { + result2[0] = XYZ_In[0]; + result2[1] = XYZ_In[1]; + result2[2] = XYZ_In[2]; + return; + } + const LMS = result2; + this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + const LMS_Flat = _CalRGBCS.#tempNormalizeMatrix; + this.#toFlat(sourceWhitePoint, LMS, LMS_Flat); + this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result2); + } + #normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result2) { + const LMS = result2; + this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_MATRIX, XYZ_In, LMS); + const LMS_D65 = _CalRGBCS.#tempNormalizeMatrix; + this.#toD65(sourceWhitePoint, LMS, LMS_D65); + this.#matrixProduct(_CalRGBCS.#BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result2); + } + #toRgb(src, srcOffset, dest, destOffset, scale) { + const A2 = MathClamp2(src[srcOffset] * scale, 0, 1); + const B2 = MathClamp2(src[srcOffset + 1] * scale, 0, 1); + const C = MathClamp2(src[srcOffset + 2] * scale, 0, 1); + const AGR = A2 === 1 ? 1 : A2 ** this.GR; + const BGG = B2 === 1 ? 1 : B2 ** this.GG; + const CGB = C === 1 ? 1 : C ** this.GB; + const X = this.MXA * AGR + this.MXB * BGG + this.MXC * CGB; + const Y = this.MYA * AGR + this.MYB * BGG + this.MYC * CGB; + const Z = this.MZA * AGR + this.MZB * BGG + this.MZC * CGB; + const XYZ = _CalRGBCS.#tempConvertMatrix1; + XYZ[0] = X; + XYZ[1] = Y; + XYZ[2] = Z; + const XYZ_Flat = _CalRGBCS.#tempConvertMatrix2; + this.#normalizeWhitePointToFlat(this.whitePoint, XYZ, XYZ_Flat); + const XYZ_Black = _CalRGBCS.#tempConvertMatrix1; + this.#compensateBlackPoint(this.blackPoint, XYZ_Flat, XYZ_Black); + const XYZ_D65 = _CalRGBCS.#tempConvertMatrix2; + this.#normalizeWhitePointToD65(_CalRGBCS.#FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65); + const SRGB = _CalRGBCS.#tempConvertMatrix1; + this.#matrixProduct(_CalRGBCS.#SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB); + dest[destOffset] = this.#sRGBTransferFunction(SRGB[0]) * 255; + dest[destOffset + 1] = this.#sRGBTransferFunction(SRGB[1]) * 255; + dest[destOffset + 2] = this.#sRGBTransferFunction(SRGB[2]) * 255; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, dest, destOffset, 1); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const scale = 1 / ((1 << bits) - 1); + for (let i = 0; i < count; ++i) { + this.#toRgb(src, srcOffset, dest, destOffset, scale); + srcOffset += 3; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } + }; + LabCS = class extends ColorSpace { + constructor(whitePoint, blackPoint, range2) { + super("Lab", 3); + if (!whitePoint) { + throw new FormatError3("WhitePoint missing - required for color space Lab"); + } + [this.XW, this.YW, this.ZW] = whitePoint; + [this.amin, this.amax, this.bmin, this.bmax] = range2 || [-100, 100, -100, 100]; + [this.XB, this.YB, this.ZB] = blackPoint || [0, 0, 0]; + if (this.XW < 0 || this.ZW < 0 || this.YW !== 1) { + throw new FormatError3("Invalid WhitePoint components, no fallback available"); + } + if (this.XB < 0 || this.YB < 0 || this.ZB < 0) { + info2("Invalid BlackPoint, falling back to default"); + this.XB = this.YB = this.ZB = 0; + } + if (this.amin > this.amax || this.bmin > this.bmax) { + info2("Invalid Range, falling back to defaults"); + this.amin = -100; + this.amax = 100; + this.bmin = -100; + this.bmax = 100; + } + } + #fn_g(x) { + return x >= 6 / 29 ? x ** 3 : 108 / 841 * (x - 4 / 29); + } + #decode(value, high1, low2, high2) { + return low2 + value * (high2 - low2) / high1; + } + #toRgb(src, srcOffset, maxVal, dest, destOffset) { + let Ls = src[srcOffset]; + let as = src[srcOffset + 1]; + let bs = src[srcOffset + 2]; + if (maxVal !== false) { + Ls = this.#decode(Ls, maxVal, 0, 100); + as = this.#decode(as, maxVal, this.amin, this.amax); + bs = this.#decode(bs, maxVal, this.bmin, this.bmax); + } + if (as > this.amax) { + as = this.amax; + } else if (as < this.amin) { + as = this.amin; + } + if (bs > this.bmax) { + bs = this.bmax; + } else if (bs < this.bmin) { + bs = this.bmin; + } + const M = (Ls + 16) / 116; + const L = M + as / 500; + const N = M - bs / 200; + const X = this.XW * this.#fn_g(L); + const Y = this.YW * this.#fn_g(M); + const Z = this.ZW * this.#fn_g(N); + let r, g, b2; + if (this.ZW < 1) { + r = X * 3.1339 + Y * -1.617 + Z * -0.4906; + g = X * -0.9785 + Y * 1.916 + Z * 0.0333; + b2 = X * 0.072 + Y * -0.229 + Z * 1.4057; + } else { + r = X * 3.2406 + Y * -1.5372 + Z * -0.4986; + g = X * -0.9689 + Y * 1.8758 + Z * 0.0415; + b2 = X * 0.0557 + Y * -0.204 + Z * 1.057; + } + dest[destOffset] = Math.sqrt(r) * 255; + dest[destOffset + 1] = Math.sqrt(g) * 255; + dest[destOffset + 2] = Math.sqrt(b2) * 255; + } + getRgbItem(src, srcOffset, dest, destOffset) { + this.#toRgb(src, srcOffset, false, dest, destOffset); + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + const maxVal = (1 << bits) - 1; + for (let i = 0; i < count; i++) { + this.#toRgb(src, srcOffset, maxVal, dest, destOffset); + srcOffset += 3; + destOffset += 3 + alpha01; + } + } + getOutputLength(inputLength, alpha01) { + return inputLength * (3 + alpha01) / 3 | 0; + } + isDefaultDecode(decodeMap, bpc) { + return true; + } + get usesZeroToOneRange() { + return shadow2(this, "usesZeroToOneRange", false); + } + }; + IccColorSpace = class _IccColorSpace extends ColorSpace { + #transformer; + #convertPixel; + static #useWasm = true; + static #wasmUrl = null; + static #finalizer = null; + constructor(iccProfile, name, numComps) { + if (!_IccColorSpace.isUsable) { + throw new Error("No ICC color space support"); + } + super(name, numComps); + let inType; + switch (numComps) { + case 1: + inType = DataType.Gray8; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_one(this.#transformer, src[srcOffset] * 255, css); + break; + case 3: + inType = DataType.RGB8; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_three(this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, src[srcOffset + 2] * 255, css); + break; + case 4: + inType = DataType.CMYK; + this.#convertPixel = (src, srcOffset, css) => qcms_convert_four(this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, src[srcOffset + 2] * 255, src[srcOffset + 3] * 255, css); + break; + default: + throw new Error(`Unsupported number of components: ${numComps}`); + } + this.#transformer = qcms_transformer_from_memory(iccProfile, inType, Intent.Perceptual); + if (!this.#transformer) { + throw new Error("Failed to create ICC color space"); + } + _IccColorSpace.#finalizer ||= new FinalizationRegistry((transformer) => { + qcms_drop_transformer(transformer); + }); + _IccColorSpace.#finalizer.register(this, this.#transformer); + } + getRgbHex(src, srcOffset) { + this.#convertPixel(src, srcOffset, true); + return QCMS._cssColor; + } + getRgbItem(src, srcOffset, dest, destOffset) { + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = 3; + this.#convertPixel(src, srcOffset, false); + QCMS._destBuffer = null; + } + getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) { + src = src.subarray(srcOffset, srcOffset + count * this.numComps); + if (bits !== 8) { + const scale = 255 / ((1 << bits) - 1); + for (let i = 0, ii = src.length; i < ii; i++) { + src[i] *= scale; + } + } + QCMS._mustAddAlpha = alpha01 && dest.buffer === src.buffer; + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = count * (3 + alpha01); + qcms_convert_array(this.#transformer, src); + QCMS._mustAddAlpha = false; + QCMS._destBuffer = null; + } + getOutputLength(inputLength, alpha01) { + return inputLength / this.numComps * (3 + alpha01) | 0; + } + static setOptions({ + useWasm, + useWorkerFetch, + wasmUrl + }) { + if (!useWorkerFetch) { + this.#useWasm = false; + return; + } + this.#useWasm = useWasm; + this.#wasmUrl = wasmUrl; + } + static get isUsable() { + let isUsable = false; + if (this.#useWasm) { + if (this.#wasmUrl) { + try { + this._module = initSync({ + module: fetchSync(`${this.#wasmUrl}qcms_bg.wasm`) + }); + isUsable = !!this._module; + QCMS._memory = this._module.memory; + QCMS._makeHexColor = Util2.makeHexColor; + } catch (e) { + warn2(`ICCBased color space: "${e}".`); + } + } else { + warn2("No ICC color space support due to missing `wasmUrl` API option"); + } + } + return shadow2(this, "isUsable", isUsable); + } + }; + CmykICCBasedCS = class _CmykICCBasedCS extends IccColorSpace { + static #iccUrl; + constructor() { + const iccProfile = new Uint8Array(fetchSync(`${_CmykICCBasedCS.#iccUrl}CGATS001Compat-v2-micro.icc`)); + super(iccProfile, "DeviceCMYK", 4); + } + static setOptions({ + iccUrl + }) { + this.#iccUrl = iccUrl; + } + static get isUsable() { + let isUsable = false; + if (IccColorSpace.isUsable) { + if (this.#iccUrl) { + isUsable = true; + } else { + warn2("No CMYK ICC profile support due to missing `iccUrl` API option"); + } + } + return shadow2(this, "isUsable", isUsable); + } + }; + Stream3 = class _Stream extends BaseStream { + constructor(arrayBuffer, start, length, dict) { + super(); + this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer); + this.start = start || 0; + this.pos = this.start; + this.end = start + length || this.bytes.length; + this.dict = dict; + } + get length() { + return this.end - this.start; + } + get isEmpty() { + return this.length === 0; + } + getByte() { + if (this.pos >= this.end) { + return -1; + } + return this.bytes[this.pos++]; + } + getBytes(length) { + const bytes = this.bytes; + const pos = this.pos; + const strEnd = this.end; + if (!length) { + return bytes.subarray(pos, strEnd); + } + let end = pos + length; + if (end > strEnd) { + end = strEnd; + } + this.pos = end; + return bytes.subarray(pos, end); + } + getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } + return this.bytes.subarray(begin, end); + } + reset() { + this.pos = this.start; + } + moveStart() { + this.start = this.pos; + } + makeSubStream(start, length, dict = null) { + return new _Stream(this.bytes.buffer, start, length, dict); + } + }; + StringStream = class extends Stream3 { + constructor(str) { + super(stringToBytes2(str)); + } + }; + NullStream = class extends Stream3 { + constructor() { + super(new Uint8Array(0)); + } + }; + ChunkedStream = class extends Stream3 { + constructor(length, chunkSize2, manager) { + super(new Uint8Array(length), 0, length, null); + this.chunkSize = chunkSize2; + this._loadedChunks = /* @__PURE__ */ new Set(); + this.numChunks = Math.ceil(length / chunkSize2); + this.manager = manager; + this.progressiveDataLength = 0; + this.lastSuccessfulEnsureByteChunk = -1; + } + getMissingChunks() { + const chunks = []; + for (let chunk2 = 0, n = this.numChunks; chunk2 < n; ++chunk2) { + if (!this._loadedChunks.has(chunk2)) { + chunks.push(chunk2); + } + } + return chunks; + } + get numChunksLoaded() { + return this._loadedChunks.size; + } + get isDataLoaded() { + return this.numChunksLoaded === this.numChunks; + } + onReceiveData(begin, chunk2) { + const chunkSize2 = this.chunkSize; + if (begin % chunkSize2 !== 0) { + throw new Error(`Bad begin offset: ${begin}`); + } + const end = begin + chunk2.byteLength; + if (end % chunkSize2 !== 0 && end !== this.bytes.length) { + throw new Error(`Bad end offset: ${end}`); + } + this.bytes.set(new Uint8Array(chunk2), begin); + const beginChunk = Math.floor(begin / chunkSize2); + const endChunk = Math.floor((end - 1) / chunkSize2) + 1; + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + this._loadedChunks.add(curChunk); + } + } + onReceiveProgressiveData(data) { + let position = this.progressiveDataLength; + const beginChunk = Math.floor(position / this.chunkSize); + this.bytes.set(new Uint8Array(data), position); + position += data.byteLength; + this.progressiveDataLength = position; + const endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize); + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + this._loadedChunks.add(curChunk); + } + } + ensureByte(pos) { + if (pos < this.progressiveDataLength) { + return; + } + const chunk2 = Math.floor(pos / this.chunkSize); + if (chunk2 > this.numChunks) { + return; + } + if (chunk2 === this.lastSuccessfulEnsureByteChunk) { + return; + } + if (!this._loadedChunks.has(chunk2)) { + throw new MissingDataException(pos, pos + 1); + } + this.lastSuccessfulEnsureByteChunk = chunk2; + } + ensureRange(begin, end) { + if (begin >= end) { + return; + } + if (end <= this.progressiveDataLength) { + return; + } + const beginChunk = Math.floor(begin / this.chunkSize); + if (beginChunk > this.numChunks) { + return; + } + const endChunk = Math.min(Math.floor((end - 1) / this.chunkSize) + 1, this.numChunks); + for (let chunk2 = beginChunk; chunk2 < endChunk; ++chunk2) { + if (!this._loadedChunks.has(chunk2)) { + throw new MissingDataException(begin, end); + } + } + } + nextEmptyChunk(beginChunk) { + const numChunks = this.numChunks; + for (let i = 0; i < numChunks; ++i) { + const chunk2 = (beginChunk + i) % numChunks; + if (!this._loadedChunks.has(chunk2)) { + return chunk2; + } + } + return null; + } + hasChunk(chunk2) { + return this._loadedChunks.has(chunk2); + } + getByte() { + const pos = this.pos; + if (pos >= this.end) { + return -1; + } + if (pos >= this.progressiveDataLength) { + this.ensureByte(pos); + } + return this.bytes[this.pos++]; + } + getBytes(length) { + const bytes = this.bytes; + const pos = this.pos; + const strEnd = this.end; + if (!length) { + if (strEnd > this.progressiveDataLength) { + this.ensureRange(pos, strEnd); + } + return bytes.subarray(pos, strEnd); + } + let end = pos + length; + if (end > strEnd) { + end = strEnd; + } + if (end > this.progressiveDataLength) { + this.ensureRange(pos, end); + } + this.pos = end; + return bytes.subarray(pos, end); + } + getByteRange(begin, end) { + if (begin < 0) { + begin = 0; + } + if (end > this.end) { + end = this.end; + } + if (end > this.progressiveDataLength) { + this.ensureRange(begin, end); + } + return this.bytes.subarray(begin, end); + } + makeSubStream(start, length, dict = null) { + if (length) { + if (start + length > this.progressiveDataLength) { + this.ensureRange(start, start + length); + } + } else if (start >= this.progressiveDataLength) { + this.ensureByte(start); + } + function ChunkedStreamSubstream() { + } + ChunkedStreamSubstream.prototype = Object.create(this); + ChunkedStreamSubstream.prototype.getMissingChunks = function() { + const chunkSize2 = this.chunkSize; + const beginChunk = Math.floor(this.start / chunkSize2); + const endChunk = Math.floor((this.end - 1) / chunkSize2) + 1; + const missingChunks = []; + for (let chunk2 = beginChunk; chunk2 < endChunk; ++chunk2) { + if (!this._loadedChunks.has(chunk2)) { + missingChunks.push(chunk2); + } + } + return missingChunks; + }; + Object.defineProperty(ChunkedStreamSubstream.prototype, "isDataLoaded", { + get() { + if (this.numChunksLoaded === this.numChunks) { + return true; + } + return this.getMissingChunks().length === 0; + }, + configurable: true + }); + const subStream = new ChunkedStreamSubstream(); + subStream.pos = subStream.start = start; + subStream.end = start + length || this.end; + subStream.dict = dict; + return subStream; + } + getBaseStreams() { + return [this]; + } + }; + ChunkedStreamManager = class { + constructor(pdfNetworkStream, args) { + this.length = args.length; + this.chunkSize = args.rangeChunkSize; + this.stream = new ChunkedStream(this.length, this.chunkSize, this); + this.pdfNetworkStream = pdfNetworkStream; + this.disableAutoFetch = args.disableAutoFetch; + this.msgHandler = args.msgHandler; + this.currRequestId = 0; + this._chunksNeededByRequest = /* @__PURE__ */ new Map(); + this._requestsByChunk = /* @__PURE__ */ new Map(); + this._promisesByRequest = /* @__PURE__ */ new Map(); + this.progressiveDataLength = 0; + this.aborted = false; + this._loadedStreamCapability = Promise.withResolvers(); + } + sendRequest(begin, end) { + const rangeReader = this.pdfNetworkStream.getRangeReader(begin, end); + if (!rangeReader.isStreamingSupported) { + rangeReader.onProgress = this.onProgress.bind(this); + } + let chunks = [], loaded = 0; + return new Promise((resolve2, reject2) => { + const readChunk = ({ + value, + done + }) => { + try { + if (done) { + const chunkData = arrayBuffersToBytes(chunks); + chunks = null; + resolve2(chunkData); + return; + } + loaded += value.byteLength; + if (rangeReader.isStreamingSupported) { + this.onProgress({ + loaded + }); + } + chunks.push(value); + rangeReader.read().then(readChunk, reject2); + } catch (e) { + reject2(e); + } + }; + rangeReader.read().then(readChunk, reject2); + }).then((data) => { + if (this.aborted) { + return; + } + this.onReceiveData({ + chunk: data, + begin + }); + }); + } + requestAllChunks(noFetch = false) { + if (!noFetch) { + const missingChunks = this.stream.getMissingChunks(); + this._requestChunks(missingChunks); + } + return this._loadedStreamCapability.promise; + } + _requestChunks(chunks) { + const requestId = this.currRequestId++; + const chunksNeeded = /* @__PURE__ */ new Set(); + this._chunksNeededByRequest.set(requestId, chunksNeeded); + for (const chunk2 of chunks) { + if (!this.stream.hasChunk(chunk2)) { + chunksNeeded.add(chunk2); + } + } + if (chunksNeeded.size === 0) { + return Promise.resolve(); + } + const capability = Promise.withResolvers(); + this._promisesByRequest.set(requestId, capability); + const chunksToRequest = []; + for (const chunk2 of chunksNeeded) { + let requestIds = this._requestsByChunk.get(chunk2); + if (!requestIds) { + requestIds = []; + this._requestsByChunk.set(chunk2, requestIds); + chunksToRequest.push(chunk2); + } + requestIds.push(requestId); + } + if (chunksToRequest.length > 0) { + const groupedChunksToRequest = this.groupChunks(chunksToRequest); + for (const groupedChunk of groupedChunksToRequest) { + const begin = groupedChunk.beginChunk * this.chunkSize; + const end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length); + this.sendRequest(begin, end).catch(capability.reject); + } + } + return capability.promise.catch((reason) => { + if (this.aborted) { + return; + } + throw reason; + }); + } + getStream() { + return this.stream; + } + requestRange(begin, end) { + end = Math.min(end, this.length); + const beginChunk = this.getBeginChunk(begin); + const endChunk = this.getEndChunk(end); + const chunks = []; + for (let chunk2 = beginChunk; chunk2 < endChunk; ++chunk2) { + chunks.push(chunk2); + } + return this._requestChunks(chunks); + } + requestRanges(ranges = []) { + const chunksToRequest = []; + for (const range2 of ranges) { + const beginChunk = this.getBeginChunk(range2.begin); + const endChunk = this.getEndChunk(range2.end); + for (let chunk2 = beginChunk; chunk2 < endChunk; ++chunk2) { + if (!chunksToRequest.includes(chunk2)) { + chunksToRequest.push(chunk2); + } + } + } + chunksToRequest.sort((a, b2) => a - b2); + return this._requestChunks(chunksToRequest); + } + groupChunks(chunks) { + const groupedChunks = []; + let beginChunk = -1; + let prevChunk = -1; + for (let i = 0, ii = chunks.length; i < ii; ++i) { + const chunk2 = chunks[i]; + if (beginChunk < 0) { + beginChunk = chunk2; + } + if (prevChunk >= 0 && prevChunk + 1 !== chunk2) { + groupedChunks.push({ + beginChunk, + endChunk: prevChunk + 1 + }); + beginChunk = chunk2; + } + if (i + 1 === chunks.length) { + groupedChunks.push({ + beginChunk, + endChunk: chunk2 + 1 + }); + } + prevChunk = chunk2; + } + return groupedChunks; + } + onProgress(args) { + this.msgHandler.send("DocProgress", { + loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded, + total: this.length + }); + } + onReceiveData(args) { + const chunk2 = args.chunk; + const isProgressive = args.begin === void 0; + const begin = isProgressive ? this.progressiveDataLength : args.begin; + const end = begin + chunk2.byteLength; + const beginChunk = Math.floor(begin / this.chunkSize); + const endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize); + if (isProgressive) { + this.stream.onReceiveProgressiveData(chunk2); + this.progressiveDataLength = end; + } else { + this.stream.onReceiveData(begin, chunk2); + } + if (this.stream.isDataLoaded) { + this._loadedStreamCapability.resolve(this.stream); + } + const loadedRequests = []; + for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) { + const requestIds = this._requestsByChunk.get(curChunk); + if (!requestIds) { + continue; + } + this._requestsByChunk.delete(curChunk); + for (const requestId of requestIds) { + const chunksNeeded = this._chunksNeededByRequest.get(requestId); + if (chunksNeeded.has(curChunk)) { + chunksNeeded.delete(curChunk); + } + if (chunksNeeded.size > 0) { + continue; + } + loadedRequests.push(requestId); + } + } + if (!this.disableAutoFetch && this._requestsByChunk.size === 0) { + let nextEmptyChunk; + if (this.stream.numChunksLoaded === 1) { + const lastChunk = this.stream.numChunks - 1; + if (!this.stream.hasChunk(lastChunk)) { + nextEmptyChunk = lastChunk; + } + } else { + nextEmptyChunk = this.stream.nextEmptyChunk(endChunk); + } + if (Number.isInteger(nextEmptyChunk)) { + this._requestChunks([nextEmptyChunk]); + } + } + for (const requestId of loadedRequests) { + const capability = this._promisesByRequest.get(requestId); + this._promisesByRequest.delete(requestId); + capability.resolve(); + } + this.msgHandler.send("DocProgress", { + loaded: this.stream.numChunksLoaded * this.chunkSize, + total: this.length + }); + } + onError(err) { + this._loadedStreamCapability.reject(err); + } + getBeginChunk(begin) { + return Math.floor(begin / this.chunkSize); + } + getEndChunk(end) { + return Math.floor((end - 1) / this.chunkSize) + 1; + } + abort(reason) { + this.aborted = true; + this.pdfNetworkStream?.cancelAllRequests(reason); + for (const capability of this._promisesByRequest.values()) { + capability.reject(reason); + } + } + }; + MIN_IMAGE_DIM = 2048; + MAX_IMAGE_DIM = 65537; + MAX_ERROR = 128; + ImageResizer = class _ImageResizer { + static #goodSquareLength = MIN_IMAGE_DIM; + static #isImageDecoderSupported = FeatureTest2.isImageDecoderSupported; + constructor(imgData, isMask) { + this._imgData = imgData; + this._isMask = isMask; + } + static get canUseImageDecoder() { + return shadow2(this, "canUseImageDecoder", this.#isImageDecoderSupported ? ImageDecoder.isTypeSupported("image/bmp") : Promise.resolve(false)); + } + static needsToBeResized(width, height) { + if (width <= this.#goodSquareLength && height <= this.#goodSquareLength) { + return false; + } + const { + MAX_DIM + } = this; + if (width > MAX_DIM || height > MAX_DIM) { + return true; + } + const area = width * height; + if (this._hasMaxArea) { + return area > this.MAX_AREA; + } + if (area < this.#goodSquareLength ** 2) { + return false; + } + if (this._areGoodDims(width, height)) { + this.#goodSquareLength = Math.max(this.#goodSquareLength, Math.floor(Math.sqrt(width * height))); + return false; + } + this.#goodSquareLength = this._guessMax(this.#goodSquareLength, MAX_DIM, MAX_ERROR, 0); + const maxArea = this.MAX_AREA = this.#goodSquareLength ** 2; + return area > maxArea; + } + static getReducePowerForJPX(width, height, componentsCount) { + const area = width * height; + const maxJPXArea = 2 ** 30 / (componentsCount * 4); + if (!this.needsToBeResized(width, height)) { + if (area > maxJPXArea) { + return Math.ceil(Math.log2(area / maxJPXArea)); + } + return 0; + } + const { + MAX_DIM, + MAX_AREA + } = this; + const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(area / Math.min(maxJPXArea, MAX_AREA))); + return Math.ceil(Math.log2(minFactor)); + } + static get MAX_DIM() { + return shadow2(this, "MAX_DIM", this._guessMax(MIN_IMAGE_DIM, MAX_IMAGE_DIM, 0, 1)); + } + static get MAX_AREA() { + this._hasMaxArea = true; + return shadow2(this, "MAX_AREA", this._guessMax(this.#goodSquareLength, this.MAX_DIM, MAX_ERROR, 0) ** 2); + } + static set MAX_AREA(area) { + if (area >= 0) { + this._hasMaxArea = true; + shadow2(this, "MAX_AREA", area); + } + } + static setOptions({ + canvasMaxAreaInBytes = -1, + isImageDecoderSupported = false + }) { + if (!this._hasMaxArea) { + this.MAX_AREA = canvasMaxAreaInBytes >> 2; + } + this.#isImageDecoderSupported = isImageDecoderSupported; + } + static _areGoodDims(width, height) { + try { + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + ctx.fillRect(0, 0, 1, 1); + const opacity = ctx.getImageData(0, 0, 1, 1).data[3]; + canvas.width = canvas.height = 1; + return opacity !== 0; + } catch { + return false; + } + } + static _guessMax(start, end, tolerance, defaultHeight) { + while (start + tolerance + 1 < end) { + const middle = Math.floor((start + end) / 2); + const height = defaultHeight || middle; + if (this._areGoodDims(middle, height)) { + start = middle; + } else { + end = middle; + } + } + return start; + } + static async createImage(imgData, isMask = false) { + return new _ImageResizer(imgData, isMask)._createImage(); + } + async _createImage() { + const { + _imgData: imgData + } = this; + const { + width, + height + } = imgData; + if (width * height * 4 > MAX_INT_32) { + const result3 = this.#rescaleImageData(); + if (result3) { + return result3; + } + } + const data = this._encodeBMP(); + let decoder2, imagePromise; + if (await _ImageResizer.canUseImageDecoder) { + decoder2 = new ImageDecoder({ + data, + type: "image/bmp", + preferAnimation: false, + transfer: [data.buffer] + }); + imagePromise = decoder2.decode().catch((reason) => { + warn2(`BMP image decoding failed: ${reason}`); + return createImageBitmap(new Blob([this._encodeBMP().buffer], { + type: "image/bmp" + })); + }).finally(() => { + decoder2.close(); + }); + } else { + imagePromise = createImageBitmap(new Blob([data.buffer], { + type: "image/bmp" + })); + } + const { + MAX_AREA, + MAX_DIM + } = _ImageResizer; + const minFactor = Math.max(width / MAX_DIM, height / MAX_DIM, Math.sqrt(width * height / MAX_AREA)); + const firstFactor = Math.max(minFactor, 2); + const factor = Math.round(10 * (minFactor + 1.25)) / 10 / firstFactor; + const N = Math.floor(Math.log2(factor)); + const steps = new Array(N + 2).fill(2); + steps[0] = firstFactor; + steps.splice(-1, 1, factor / (1 << N)); + let newWidth = width; + let newHeight = height; + const result2 = await imagePromise; + let bitmap = result2.image || result2; + for (const step of steps) { + const prevWidth = newWidth; + const prevHeight = newHeight; + newWidth = Math.floor(newWidth / step) - 1; + newHeight = Math.floor(newHeight / step) - 1; + const canvas = new OffscreenCanvas(newWidth, newHeight); + const ctx = canvas.getContext("2d"); + ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + bitmap.close(); + bitmap = canvas.transferToImageBitmap(); + } + imgData.data = null; + imgData.bitmap = bitmap; + imgData.width = newWidth; + imgData.height = newHeight; + return imgData; + } + #rescaleImageData() { + const { + _imgData: imgData + } = this; + const { + data, + width, + height, + kind + } = imgData; + const rgbaSize = width * height * 4; + const K = Math.ceil(Math.log2(rgbaSize / MAX_INT_32)); + const newWidth = width >> K; + const newHeight = height >> K; + let rgbaData; + let maxHeight = height; + try { + rgbaData = new Uint8Array(rgbaSize); + } catch { + let n = Math.floor(Math.log2(rgbaSize + 1)); + while (true) { + try { + rgbaData = new Uint8Array(2 ** n - 1); + break; + } catch { + n -= 1; + } + } + maxHeight = Math.floor((2 ** n - 1) / (width * 4)); + const newSize = width * maxHeight * 4; + if (newSize < rgbaData.length) { + rgbaData = new Uint8Array(newSize); + } + } + const src32 = new Uint32Array(rgbaData.buffer); + const dest32 = new Uint32Array(newWidth * newHeight); + let srcPos = 0; + let newIndex = 0; + const step = Math.ceil(height / maxHeight); + const remainder = height % maxHeight === 0 ? height : height % maxHeight; + for (let k = 0; k < step; k++) { + const h = k < step - 1 ? maxHeight : remainder; + ({ + srcPos + } = convertToRGBA({ + kind, + src: data, + dest: src32, + width, + height: h, + inverseDecode: this._isMask, + srcPos + })); + for (let i = 0, ii = h >> K; i < ii; i++) { + const buf = src32.subarray((i << K) * width); + for (let j = 0; j < newWidth; j++) { + dest32[newIndex++] = buf[j << K]; + } + } + } + if (_ImageResizer.needsToBeResized(newWidth, newHeight)) { + imgData.data = dest32; + imgData.width = newWidth; + imgData.height = newHeight; + imgData.kind = ImageKind2.RGBA_32BPP; + return null; + } + const canvas = new OffscreenCanvas(newWidth, newHeight); + const ctx = canvas.getContext("2d", { + willReadFrequently: true + }); + ctx.putImageData(new ImageData(new Uint8ClampedArray(dest32.buffer), newWidth, newHeight), 0, 0); + imgData.data = null; + imgData.bitmap = canvas.transferToImageBitmap(); + imgData.width = newWidth; + imgData.height = newHeight; + return imgData; + } + _encodeBMP() { + const { + width, + height, + kind + } = this._imgData; + let data = this._imgData.data; + let bitPerPixel; + let colorTable = new Uint8Array(0); + let maskTable = colorTable; + let compression = 0; + switch (kind) { + case ImageKind2.GRAYSCALE_1BPP: { + bitPerPixel = 1; + colorTable = new Uint8Array(this._isMask ? [255, 255, 255, 255, 0, 0, 0, 0] : [0, 0, 0, 0, 255, 255, 255, 255]); + const rowLen = width + 7 >> 3; + const rowSize = rowLen + 3 & -4; + if (rowLen !== rowSize) { + const newData = new Uint8Array(rowSize * height); + let k = 0; + for (let i2 = 0, ii = height * rowLen; i2 < ii; i2 += rowLen, k += rowSize) { + newData.set(data.subarray(i2, i2 + rowLen), k); + } + data = newData; + } + break; + } + case ImageKind2.RGB_24BPP: { + bitPerPixel = 24; + if (width & 3) { + const rowLen = 3 * width; + const rowSize = rowLen + 3 & -4; + const extraLen = rowSize - rowLen; + const newData = new Uint8Array(rowSize * height); + let k = 0; + for (let i2 = 0, ii = height * rowLen; i2 < ii; i2 += rowLen) { + const row = data.subarray(i2, i2 + rowLen); + for (let j = 0; j < rowLen; j += 3) { + newData[k++] = row[j + 2]; + newData[k++] = row[j + 1]; + newData[k++] = row[j]; + } + k += extraLen; + } + data = newData; + } else { + for (let i2 = 0, ii = data.length; i2 < ii; i2 += 3) { + const tmp = data[i2]; + data[i2] = data[i2 + 2]; + data[i2 + 2] = tmp; + } + } + break; + } + case ImageKind2.RGBA_32BPP: + bitPerPixel = 32; + compression = 3; + maskTable = new Uint8Array(4 + 4 + 4 + 4 + 52); + const view2 = new DataView(maskTable.buffer); + if (FeatureTest2.isLittleEndian) { + view2.setUint32(0, 255, true); + view2.setUint32(4, 65280, true); + view2.setUint32(8, 16711680, true); + view2.setUint32(12, 4278190080, true); + } else { + view2.setUint32(0, 4278190080, true); + view2.setUint32(4, 16711680, true); + view2.setUint32(8, 65280, true); + view2.setUint32(12, 255, true); + } + break; + default: + throw new Error("invalid format"); + } + let i = 0; + const headerLength = 40 + maskTable.length; + const fileLength = 14 + headerLength + colorTable.length + data.length; + const bmpData = new Uint8Array(fileLength); + const view = new DataView(bmpData.buffer); + view.setUint16(i, 19778, true); + i += 2; + view.setUint32(i, fileLength, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + view.setUint32(i, 14 + headerLength + colorTable.length, true); + i += 4; + view.setUint32(i, headerLength, true); + i += 4; + view.setInt32(i, width, true); + i += 4; + view.setInt32(i, -height, true); + i += 4; + view.setUint16(i, 1, true); + i += 2; + view.setUint16(i, bitPerPixel, true); + i += 2; + view.setUint32(i, compression, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + view.setInt32(i, 0, true); + i += 4; + view.setInt32(i, 0, true); + i += 4; + view.setUint32(i, colorTable.length / 4, true); + i += 4; + view.setUint32(i, 0, true); + i += 4; + bmpData.set(maskTable, i); + i += maskTable.length; + bmpData.set(colorTable, i); + i += colorTable.length; + bmpData.set(data, i); + return bmpData; + } + }; + emptyBuffer = new Uint8Array(0); + DecodeStream = class extends BaseStream { + constructor(maybeMinBufferLength) { + super(); + this._rawMinBufferLength = maybeMinBufferLength || 0; + this.pos = 0; + this.bufferLength = 0; + this.eof = false; + this.buffer = emptyBuffer; + this.minBufferLength = 512; + if (maybeMinBufferLength) { + while (this.minBufferLength < maybeMinBufferLength) { + this.minBufferLength *= 2; + } + } + } + get isEmpty() { + while (!this.eof && this.bufferLength === 0) { + this.readBlock(); + } + return this.bufferLength === 0; + } + ensureBuffer(requested) { + const buffer2 = this.buffer; + if (requested <= buffer2.byteLength) { + return buffer2; + } + let size3 = this.minBufferLength; + while (size3 < requested) { + size3 *= 2; + } + const buffer22 = new Uint8Array(size3); + buffer22.set(buffer2); + return this.buffer = buffer22; + } + getByte() { + const pos = this.pos; + while (this.bufferLength <= pos) { + if (this.eof) { + return -1; + } + this.readBlock(); + } + return this.buffer[this.pos++]; + } + getBytes(length, decoderOptions = null) { + const pos = this.pos; + let end; + if (length) { + this.ensureBuffer(pos + length); + end = pos + length; + while (!this.eof && this.bufferLength < end) { + this.readBlock(decoderOptions); + } + const bufEnd = this.bufferLength; + if (end > bufEnd) { + end = bufEnd; + } + } else { + while (!this.eof) { + this.readBlock(decoderOptions); + } + end = this.bufferLength; + } + this.pos = end; + return this.buffer.subarray(pos, end); + } + async getImageData(length, decoderOptions) { + if (!this.canAsyncDecodeImageFromBuffer) { + if (this.isAsyncDecoder) { + return this.decodeImage(null, decoderOptions); + } + return this.getBytes(length, decoderOptions); + } + const data = await this.stream.asyncGetBytes(); + return this.decodeImage(data, decoderOptions); + } + reset() { + this.pos = 0; + } + makeSubStream(start, length, dict = null) { + if (length === void 0) { + while (!this.eof) { + this.readBlock(); + } + } else { + const end = start + length; + while (this.bufferLength <= end && !this.eof) { + this.readBlock(); + } + } + return new Stream3(this.buffer, start, length, dict); + } + getBaseStreams() { + return this.str ? this.str.getBaseStreams() : null; + } + }; + StreamsSequenceStream = class extends DecodeStream { + constructor(streams, onError = null) { + streams = streams.filter((s) => s instanceof BaseStream); + let maybeLength = 0; + for (const stream of streams) { + maybeLength += stream instanceof DecodeStream ? stream._rawMinBufferLength : stream.length; + } + super(maybeLength); + this.streams = streams; + this._onError = onError; + } + readBlock() { + const streams = this.streams; + if (streams.length === 0) { + this.eof = true; + return; + } + const stream = streams.shift(); + let chunk2; + try { + chunk2 = stream.getBytes(); + } catch (reason) { + if (this._onError) { + this._onError(reason, stream.dict?.objId); + return; + } + throw reason; + } + const bufferLength = this.bufferLength; + const newLength = bufferLength + chunk2.length; + const buffer2 = this.ensureBuffer(newLength); + buffer2.set(chunk2, bufferLength); + this.bufferLength = newLength; + } + getBaseStreams() { + const baseStreamsBuf = []; + for (const stream of this.streams) { + const baseStreams = stream.getBaseStreams(); + if (baseStreams) { + baseStreamsBuf.push(...baseStreams); + } + } + return baseStreamsBuf.length > 0 ? baseStreamsBuf : null; + } + }; + ColorSpaceUtils = class { + static parse({ + cs, + xref, + resources = null, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache, + asyncIfNotCached = false + }) { + const options = { + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }; + let csName, csRef, parsedCS; + if (cs instanceof Ref) { + csRef = cs; + const cachedCS = globalColorSpaceCache.getByRef(csRef) || localColorSpaceCache.getByRef(csRef); + if (cachedCS) { + return cachedCS; + } + cs = xref.fetch(cs); + } + if (cs instanceof Name2) { + csName = cs.name; + const cachedCS = localColorSpaceCache.getByName(csName); + if (cachedCS) { + return cachedCS; + } + } + try { + parsedCS = this.#parse(cs, options); + } catch (ex) { + if (asyncIfNotCached && !(ex instanceof MissingDataException)) { + return Promise.reject(ex); + } + throw ex; + } + if (csName || csRef) { + localColorSpaceCache.set(csName, csRef, parsedCS); + if (csRef) { + globalColorSpaceCache.set(null, csRef, parsedCS); + } + } + return asyncIfNotCached ? Promise.resolve(parsedCS) : parsedCS; + } + static #subParse(cs, options) { + const { + globalColorSpaceCache + } = options; + let csRef; + if (cs instanceof Ref) { + csRef = cs; + const cachedCS = globalColorSpaceCache.getByRef(csRef); + if (cachedCS) { + return cachedCS; + } + } + const parsedCS = this.#parse(cs, options); + if (csRef) { + globalColorSpaceCache.set(null, csRef, parsedCS); + } + return parsedCS; + } + static #parse(cs, options) { + const { + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache + } = options; + cs = xref.fetchIfRef(cs); + if (cs instanceof Name2) { + switch (cs.name) { + case "G": + case "DeviceGray": + return this.gray; + case "RGB": + case "DeviceRGB": + return this.rgb; + case "DeviceRGBA": + return this.rgba; + case "CMYK": + case "DeviceCMYK": + return this.cmyk; + case "Pattern": + return new PatternCS(null); + default: + if (resources instanceof Dict) { + const colorSpaces = resources.get("ColorSpace"); + if (colorSpaces instanceof Dict) { + const resourcesCS = colorSpaces.get(cs.name); + if (resourcesCS) { + if (resourcesCS instanceof Name2) { + return this.#parse(resourcesCS, options); + } + cs = resourcesCS; + break; + } + } + } + warn2(`Unrecognized ColorSpace: ${cs.name}`); + return this.gray; + } + } + if (Array.isArray(cs)) { + const mode = xref.fetchIfRef(cs[0]).name; + let params, numComps, baseCS, whitePoint, blackPoint, gamma; + switch (mode) { + case "G": + case "DeviceGray": + return this.gray; + case "RGB": + case "DeviceRGB": + return this.rgb; + case "CMYK": + case "DeviceCMYK": + return this.cmyk; + case "CalGray": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + gamma = params.get("Gamma"); + return new CalGrayCS(whitePoint, blackPoint, gamma); + case "CalRGB": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + gamma = params.getArray("Gamma"); + const matrix = params.getArray("Matrix"); + return new CalRGBCS(whitePoint, blackPoint, gamma, matrix); + case "ICCBased": + const isRef3 = cs[1] instanceof Ref; + if (isRef3) { + const cachedCS = globalColorSpaceCache.getByRef(cs[1]); + if (cachedCS) { + return cachedCS; + } + } + const stream = xref.fetchIfRef(cs[1]); + const dict = stream.dict; + numComps = dict.get("N"); + if (IccColorSpace.isUsable) { + try { + const iccCS = new IccColorSpace(stream.getBytes(), "ICCBased", numComps); + if (isRef3) { + globalColorSpaceCache.set(null, cs[1], iccCS); + } + return iccCS; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`ICCBased color space (${cs[1]}): "${ex}".`); + } + } + const altRaw = dict.getRaw("Alternate"); + if (altRaw) { + const altCS = this.#subParse(altRaw, options); + if (altCS.numComps === numComps) { + return altCS; + } + warn2("ICCBased color space: Ignoring incorrect /Alternate entry."); + } + if (numComps === 1) { + return this.gray; + } else if (numComps === 3) { + return this.rgb; + } else if (numComps === 4) { + return this.cmyk; + } + break; + case "Pattern": + baseCS = cs[1] || null; + if (baseCS) { + baseCS = this.#subParse(baseCS, options); + } + return new PatternCS(baseCS); + case "I": + case "Indexed": + baseCS = this.#subParse(cs[1], options); + const hiVal = MathClamp2(xref.fetchIfRef(cs[2]), 0, 255); + const lookup = xref.fetchIfRef(cs[3]); + return new IndexedCS(baseCS, hiVal, lookup); + case "Separation": + case "DeviceN": + const name = xref.fetchIfRef(cs[1]); + numComps = Array.isArray(name) ? name.length : 1; + baseCS = this.#subParse(cs[2], options); + const tintFn = pdfFunctionFactory.create(cs[3]); + return new AlternateCS(numComps, baseCS, tintFn); + case "Lab": + params = xref.fetchIfRef(cs[1]); + whitePoint = params.getArray("WhitePoint"); + blackPoint = params.getArray("BlackPoint"); + const range2 = params.getArray("Range"); + return new LabCS(whitePoint, blackPoint, range2); + default: + warn2(`Unimplemented ColorSpace object: ${mode}`); + return this.gray; + } + } + warn2(`Unrecognized ColorSpace object: ${cs}`); + return this.gray; + } + static get gray() { + return shadow2(this, "gray", new DeviceGrayCS()); + } + static get rgb() { + return shadow2(this, "rgb", new DeviceRgbCS()); + } + static get rgba() { + return shadow2(this, "rgba", new DeviceRgbaCS()); + } + static get cmyk() { + if (CmykICCBasedCS.isUsable) { + try { + return shadow2(this, "cmyk", new CmykICCBasedCS()); + } catch { + warn2("CMYK fallback: DeviceCMYK"); + } + } + return shadow2(this, "cmyk", new DeviceCmykCS()); + } + }; + JpegError = class extends BaseException2 { + constructor(msg) { + super(msg, "JpegError"); + } + }; + DNLMarkerError = class extends BaseException2 { + constructor(message2, scanLines) { + super(message2, "DNLMarkerError"); + this.scanLines = scanLines; + } + }; + EOIMarkerError = class extends BaseException2 { + constructor(msg) { + super(msg, "EOIMarkerError"); + } + }; + dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]); + dctCos1 = 4017; + dctSin1 = 799; + dctCos3 = 3406; + dctSin3 = 2276; + dctCos6 = 1567; + dctSin6 = 3784; + dctSqrt2 = 5793; + dctSqrt1d2 = 2896; + JpegImage = class { + constructor({ + decodeTransform = null, + colorTransform = -1 + } = {}) { + this._decodeTransform = decodeTransform; + this._colorTransform = colorTransform; + } + static canUseImageDecoder(data, colorTransform = -1) { + let exifOffsets = null; + let offset = 0; + let numComponents = null; + let fileMarker = readUint16(data, offset); + offset += 2; + if (fileMarker !== 65496) { + throw new JpegError("SOI not found"); + } + fileMarker = readUint16(data, offset); + offset += 2; + markerLoop: while (fileMarker !== 65497) { + switch (fileMarker) { + case 65505: + const { + appData, + oldOffset, + newOffset + } = readDataBlock(data, offset); + offset = newOffset; + if (appData[0] === 69 && appData[1] === 120 && appData[2] === 105 && appData[3] === 102 && appData[4] === 0 && appData[5] === 0) { + if (exifOffsets) { + throw new JpegError("Duplicate EXIF-blocks found."); + } + exifOffsets = { + exifStart: oldOffset + 6, + exifEnd: newOffset + }; + } + fileMarker = readUint16(data, offset); + offset += 2; + continue; + case 65472: + case 65473: + case 65474: + numComponents = data[offset + (2 + 1 + 2 + 2)]; + break markerLoop; + case 65535: + if (data[offset] !== 255) { + offset--; + } + break; + } + offset = skipData(data, offset); + fileMarker = readUint16(data, offset); + offset += 2; + } + if (numComponents === 4) { + return null; + } + if (numComponents === 3 && colorTransform === 0) { + return null; + } + return exifOffsets || {}; + } + parse(data, { + dnlScanLines = null + } = {}) { + let offset = 0; + let jfif = null; + let adobe = null; + let frame, resetInterval; + let numSOSMarkers = 0; + const quantizationTables = []; + const huffmanTablesAC = [], huffmanTablesDC = []; + let fileMarker = readUint16(data, offset); + offset += 2; + if (fileMarker !== 65496) { + throw new JpegError("SOI not found"); + } + fileMarker = readUint16(data, offset); + offset += 2; + markerLoop: while (fileMarker !== 65497) { + let i, j, l2; + switch (fileMarker) { + case 65504: + case 65505: + case 65506: + case 65507: + case 65508: + case 65509: + case 65510: + case 65511: + case 65512: + case 65513: + case 65514: + case 65515: + case 65516: + case 65517: + case 65518: + case 65519: + case 65534: + const { + appData, + newOffset + } = readDataBlock(data, offset); + offset = newOffset; + if (fileMarker === 65504) { + if (appData[0] === 74 && appData[1] === 70 && appData[2] === 73 && appData[3] === 70 && appData[4] === 0) { + jfif = { + version: { + major: appData[5], + minor: appData[6] + }, + densityUnits: appData[7], + xDensity: appData[8] << 8 | appData[9], + yDensity: appData[10] << 8 | appData[11], + thumbWidth: appData[12], + thumbHeight: appData[13], + thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13]) + }; + } + } + if (fileMarker === 65518) { + if (appData[0] === 65 && appData[1] === 100 && appData[2] === 111 && appData[3] === 98 && appData[4] === 101) { + adobe = { + version: appData[5] << 8 | appData[6], + flags0: appData[7] << 8 | appData[8], + flags1: appData[9] << 8 | appData[10], + transformCode: appData[11] + }; + } + } + break; + case 65499: + const quantizationTablesLength = readUint16(data, offset); + offset += 2; + const quantizationTablesEnd = quantizationTablesLength + offset - 2; + let z2; + while (offset < quantizationTablesEnd) { + const quantizationTableSpec = data[offset++]; + const tableData = new Uint16Array(64); + if (quantizationTableSpec >> 4 === 0) { + for (j = 0; j < 64; j++) { + z2 = dctZigZag[j]; + tableData[z2] = data[offset++]; + } + } else if (quantizationTableSpec >> 4 === 1) { + for (j = 0; j < 64; j++) { + z2 = dctZigZag[j]; + tableData[z2] = readUint16(data, offset); + offset += 2; + } + } else { + throw new JpegError("DQT - invalid table spec"); + } + quantizationTables[quantizationTableSpec & 15] = tableData; + } + break; + case 65472: + case 65473: + case 65474: + if (frame) { + throw new JpegError("Only single frame JPEGs supported"); + } + offset += 2; + frame = {}; + frame.extended = fileMarker === 65473; + frame.progressive = fileMarker === 65474; + frame.precision = data[offset++]; + const sofScanLines = readUint16(data, offset); + offset += 2; + frame.scanLines = dnlScanLines || sofScanLines; + frame.samplesPerLine = readUint16(data, offset); + offset += 2; + frame.components = []; + frame.componentIds = {}; + const componentsCount = data[offset++]; + let maxH = 0, maxV = 0; + for (i = 0; i < componentsCount; i++) { + const componentId = data[offset]; + const h = data[offset + 1] >> 4; + const v = data[offset + 1] & 15; + if (maxH < h) { + maxH = h; + } + if (maxV < v) { + maxV = v; + } + const qId = data[offset + 2]; + l2 = frame.components.push({ + h, + v, + quantizationId: qId, + quantizationTable: null + }); + frame.componentIds[componentId] = l2 - 1; + offset += 3; + } + frame.maxH = maxH; + frame.maxV = maxV; + prepareComponents(frame); + break; + case 65476: + const huffmanLength = readUint16(data, offset); + offset += 2; + for (i = 2; i < huffmanLength; ) { + const huffmanTableSpec = data[offset++]; + const codeLengths = new Uint8Array(16); + let codeLengthSum = 0; + for (j = 0; j < 16; j++, offset++) { + codeLengthSum += codeLengths[j] = data[offset]; + } + const huffmanValues = new Uint8Array(codeLengthSum); + for (j = 0; j < codeLengthSum; j++, offset++) { + huffmanValues[j] = data[offset]; + } + i += 17 + codeLengthSum; + (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues); + } + break; + case 65501: + offset += 2; + resetInterval = readUint16(data, offset); + offset += 2; + break; + case 65498: + const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines; + offset += 2; + const selectorsCount = data[offset++], components = []; + for (i = 0; i < selectorsCount; i++) { + const index2 = data[offset++]; + const componentIndex = frame.componentIds[index2]; + const component = frame.components[componentIndex]; + component.index = index2; + const tableSpec = data[offset++]; + component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; + component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; + components.push(component); + } + const spectralStart = data[offset++], spectralEnd = data[offset++], successiveApproximation = data[offset++]; + try { + const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker); + offset += processed; + } catch (ex) { + if (ex instanceof DNLMarkerError) { + warn2(`${ex.message} -- attempting to re-parse the JPEG image.`); + return this.parse(data, { + dnlScanLines: ex.scanLines + }); + } else if (ex instanceof EOIMarkerError) { + warn2(`${ex.message} -- ignoring the rest of the image data.`); + break markerLoop; + } + throw ex; + } + break; + case 65500: + offset += 4; + break; + case 65535: + if (data[offset] !== 255) { + offset--; + } + break; + default: + const nextFileMarker = findNextFileMarker(data, offset - 2, offset - 3); + if (nextFileMarker?.invalid) { + warn2("JpegImage.parse - unexpected data, current marker is: " + nextFileMarker.invalid); + offset = nextFileMarker.offset; + break; + } + if (!nextFileMarker || offset >= data.length - 1) { + warn2("JpegImage.parse - reached the end of the image data without finding an EOI marker (0xFFD9)."); + break markerLoop; + } + throw new JpegError("JpegImage.parse - unknown marker: " + fileMarker.toString(16)); + } + fileMarker = readUint16(data, offset); + offset += 2; + } + if (!frame) { + throw new JpegError("JpegImage.parse - no frame data found."); + } + this.width = frame.samplesPerLine; + this.height = frame.scanLines; + this.jfif = jfif; + this.adobe = adobe; + this.components = []; + for (const component of frame.components) { + const quantizationTable = quantizationTables[component.quantizationId]; + if (quantizationTable) { + component.quantizationTable = quantizationTable; + } + this.components.push({ + index: component.index, + output: buildComponentData(frame, component), + scaleX: component.h / frame.maxH, + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn + }); + } + this.numComponents = this.components.length; + return void 0; + } + _getLinearizedBlockData(width, height, isSourcePDF = false) { + const scaleX = this.width / width, scaleY = this.height / height; + let component, componentScaleX, componentScaleY, blocksPerScanline; + let x, y, i, j, k; + let index2; + let offset = 0; + let output2; + const numComponents = this.components.length; + const dataLength = width * height * numComponents; + const data = new Uint8ClampedArray(dataLength); + const xScaleBlockOffset = new Uint32Array(width); + const mask3LSB = 4294967288; + let lastComponentScaleX; + for (i = 0; i < numComponents; i++) { + component = this.components[i]; + componentScaleX = component.scaleX * scaleX; + componentScaleY = component.scaleY * scaleY; + offset = i; + output2 = component.output; + blocksPerScanline = component.blocksPerLine + 1 << 3; + if (componentScaleX !== lastComponentScaleX) { + for (x = 0; x < width; x++) { + j = 0 | x * componentScaleX; + xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7; + } + lastComponentScaleX = componentScaleX; + } + for (y = 0; y < height; y++) { + j = 0 | y * componentScaleY; + index2 = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3; + for (x = 0; x < width; x++) { + data[offset] = output2[index2 + xScaleBlockOffset[x]]; + offset += numComponents; + } + } + } + let transform2 = this._decodeTransform; + if (!isSourcePDF && numComponents === 4 && !transform2) { + transform2 = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]); + } + if (transform2) { + for (i = 0; i < dataLength; ) { + for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) { + data[i] = (data[i] * transform2[k] >> 8) + transform2[k + 1]; + } + } + } + return data; + } + get _isColorConversionNeeded() { + if (this.adobe) { + return !!this.adobe.transformCode; + } + if (this.numComponents === 3) { + if (this._colorTransform === 0) { + return false; + } else if (this.components[0].index === 82 && this.components[1].index === 71 && this.components[2].index === 66) { + return false; + } + return true; + } + if (this._colorTransform === 1) { + return true; + } + return false; + } + _convertYccToRgb(data) { + let Y, Cb, Cr; + for (let i = 0, length = data.length; i < length; i += 3) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = Y - 179.456 + 1.402 * Cr; + data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr; + data[i + 2] = Y - 226.816 + 1.772 * Cb; + } + return data; + } + _convertYccToRgba(data, out) { + for (let i = 0, j = 0, length = data.length; i < length; i += 3, j += 4) { + const Y = data[i]; + const Cb = data[i + 1]; + const Cr = data[i + 2]; + out[j] = Y - 179.456 + 1.402 * Cr; + out[j + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr; + out[j + 2] = Y - 226.816 + 1.772 * Cb; + out[j + 3] = 255; + } + return out; + } + _convertYcckToRgb(data) { + this._convertYcckToCmyk(data); + return this._convertCmykToRgb(data); + } + _convertYcckToRgba(data) { + this._convertYcckToCmyk(data); + return this._convertCmykToRgba(data); + } + _convertYcckToCmyk(data) { + let Y, Cb, Cr; + for (let i = 0, length = data.length; i < length; i += 4) { + Y = data[i]; + Cb = data[i + 1]; + Cr = data[i + 2]; + data[i] = 434.456 - Y - 1.402 * Cr; + data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr; + data[i + 2] = 481.816 - Y - 1.772 * Cb; + } + return data; + } + _convertCmykToRgb(data) { + const count = data.length / 4; + ColorSpaceUtils.cmyk.getRgbBuffer(data, 0, count, data, 0, 8, 0); + return data.subarray(0, count * 3); + } + _convertCmykToRgba(data) { + ColorSpaceUtils.cmyk.getRgbBuffer(data, 0, data.length / 4, data, 0, 8, 1); + if (ColorSpaceUtils.cmyk instanceof DeviceCmykCS) { + for (let i = 3, ii = data.length; i < ii; i += 4) { + data[i] = 255; + } + } + return data; + } + getData({ + width, + height, + forceRGBA = false, + forceRGB = false, + isSourcePDF = false + }) { + if (this.numComponents > 4) { + throw new JpegError("Unsupported color mode"); + } + const data = this._getLinearizedBlockData(width, height, isSourcePDF); + if (this.numComponents === 1 && (forceRGBA || forceRGB)) { + const len = data.length * (forceRGBA ? 4 : 3); + const rgbaData = new Uint8ClampedArray(len); + let offset = 0; + if (forceRGBA) { + grayToRGBA(data, new Uint32Array(rgbaData.buffer)); + } else { + for (const grayColor of data) { + rgbaData[offset++] = grayColor; + rgbaData[offset++] = grayColor; + rgbaData[offset++] = grayColor; + } + } + return rgbaData; + } else if (this.numComponents === 3 && this._isColorConversionNeeded) { + if (forceRGBA) { + const rgbaData = new Uint8ClampedArray(data.length / 3 * 4); + return this._convertYccToRgba(data, rgbaData); + } + return this._convertYccToRgb(data); + } else if (this.numComponents === 4) { + if (this._isColorConversionNeeded) { + if (forceRGBA) { + return this._convertYcckToRgba(data); + } + if (forceRGB) { + return this._convertYcckToRgb(data); + } + return this._convertYcckToCmyk(data); + } else if (forceRGBA) { + return this._convertCmykToRgba(data); + } else if (forceRGB) { + return this._convertCmykToRgb(data); + } + } + return data; + } + }; + JpegStream = class _JpegStream extends DecodeStream { + static #isImageDecoderSupported = FeatureTest2.isImageDecoderSupported; + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + static get canUseImageDecoder() { + return shadow2(this, "canUseImageDecoder", this.#isImageDecoderSupported ? ImageDecoder.isTypeSupported("image/jpeg") : Promise.resolve(false)); + } + static setOptions({ + isImageDecoderSupported = false + }) { + this.#isImageDecoderSupported = isImageDecoderSupported; + } + get bytes() { + return shadow2(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) { + } + readBlock() { + this.decodeImage(); + } + get jpegOptions() { + const jpegOptions = { + decodeTransform: void 0, + colorTransform: void 0 + }; + const decodeArr = this.dict.getArray("D", "Decode"); + if ((this.forceRGBA || this.forceRGB) && Array.isArray(decodeArr)) { + const bitsPerComponent = this.dict.get("BPC", "BitsPerComponent") || 8; + const decodeArrLength = decodeArr.length; + const transform2 = new Int32Array(decodeArrLength); + let transformNeeded = false; + const maxValue = (1 << bitsPerComponent) - 1; + for (let i = 0; i < decodeArrLength; i += 2) { + transform2[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0; + transform2[i + 1] = decodeArr[i] * maxValue | 0; + if (transform2[i] !== 256 || transform2[i + 1] !== 0) { + transformNeeded = true; + } + } + if (transformNeeded) { + jpegOptions.decodeTransform = transform2; + } + } + if (this.params instanceof Dict) { + const colorTransform = this.params.get("ColorTransform"); + if (Number.isInteger(colorTransform)) { + jpegOptions.colorTransform = colorTransform; + } + } + return shadow2(this, "jpegOptions", jpegOptions); + } + #skipUselessBytes(data) { + for (let i = 0, ii = data.length - 1; i < ii; i++) { + if (data[i] === 255 && data[i + 1] === 216) { + if (i > 0) { + data = data.subarray(i); + } + break; + } + } + return data; + } + decodeImage(bytes) { + if (this.eof) { + return this.buffer; + } + bytes = this.#skipUselessBytes(bytes || this.bytes); + const jpegImage = new JpegImage(this.jpegOptions); + jpegImage.parse(bytes); + const data = jpegImage.getData({ + width: this.drawWidth, + height: this.drawHeight, + forceRGBA: this.forceRGBA, + forceRGB: this.forceRGB, + isSourcePDF: true + }); + this.buffer = data; + this.bufferLength = data.length; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } + async getTransferableImage() { + if (!await _JpegStream.canUseImageDecoder) { + return null; + } + const jpegOptions = this.jpegOptions; + if (jpegOptions.decodeTransform) { + return null; + } + let decoder2; + try { + const bytes = this.canAsyncDecodeImageFromBuffer && await this.stream.asyncGetBytes() || this.bytes; + if (!bytes) { + return null; + } + let data = this.#skipUselessBytes(bytes); + const useImageDecoder = JpegImage.canUseImageDecoder(data, jpegOptions.colorTransform); + if (!useImageDecoder) { + return null; + } + if (useImageDecoder.exifStart) { + data = data.slice(); + data.fill(0, useImageDecoder.exifStart, useImageDecoder.exifEnd); + } + decoder2 = new ImageDecoder({ + data, + type: "image/jpeg", + preferAnimation: false + }); + return (await decoder2.decode()).image; + } catch (reason) { + warn2(`getTransferableImage - failed: "${reason}".`); + return null; + } finally { + decoder2?.close(); + } + } + }; + openjpeg = OpenJPEG; + JpxError = class extends BaseException2 { + constructor(msg) { + super(msg, "JpxError"); + } + }; + JpxImage = class { + static #buffer = null; + static #handler = null; + static #modulePromise = null; + static #useWasm = true; + static #useWorkerFetch = true; + static #wasmUrl = null; + static setOptions({ + handler, + useWasm, + useWorkerFetch, + wasmUrl + }) { + this.#useWasm = useWasm; + this.#useWorkerFetch = useWorkerFetch; + this.#wasmUrl = wasmUrl; + if (!useWorkerFetch) { + this.#handler = handler; + } + } + static async #getJsModule(fallbackCallback) { + const path2 = `${this.#wasmUrl}openjpeg_nowasm_fallback.js`; + let instance = null; + try { + const mod = await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + path2 + ); + instance = mod.default(); + } catch (e) { + warn2(`JpxImage#getJsModule: ${e}`); + } + fallbackCallback(instance); + } + static async #instantiateWasm(fallbackCallback, imports, successCallback) { + const filename = "openjpeg.wasm"; + try { + if (!this.#buffer) { + if (this.#useWorkerFetch) { + this.#buffer = await fetchBinaryData(`${this.#wasmUrl}${filename}`); + } else { + this.#buffer = await this.#handler.sendWithPromise("FetchBinaryData", { + type: "wasmFactory", + filename + }); + } + } + const results = await WebAssembly.instantiate(this.#buffer, imports); + return successCallback(results.instance); + } catch (reason) { + warn2(`JpxImage#instantiateWasm: ${reason}`); + this.#getJsModule(fallbackCallback); + return null; + } finally { + this.#handler = null; + } + } + static async decode(bytes, { + numComponents = 4, + isIndexedColormap = false, + smaskInData = false, + reducePower = 0 + } = {}) { + if (!this.#modulePromise) { + const { + promise: promise2, + resolve: resolve2 + } = Promise.withResolvers(); + const promises = [promise2]; + if (!this.#useWasm) { + this.#getJsModule(resolve2); + } else { + promises.push(openjpeg({ + warn: warn2, + instantiateWasm: this.#instantiateWasm.bind(this, resolve2) + })); + } + this.#modulePromise = Promise.race(promises); + } + const module2 = await this.#modulePromise; + if (!module2) { + throw new JpxError("OpenJPEG failed to initialize"); + } + let ptr; + try { + const size3 = bytes.length; + ptr = module2._malloc(size3); + module2.writeArrayToMemory(bytes, ptr); + const ret2 = module2._jp2_decode(ptr, size3, numComponents > 0 ? numComponents : 0, !!isIndexedColormap, !!smaskInData, reducePower); + if (ret2) { + const { + errorMessages + } = module2; + if (errorMessages) { + delete module2.errorMessages; + throw new JpxError(errorMessages); + } + throw new JpxError("Unknown error"); + } + const { + imageData + } = module2; + module2.imageData = null; + return imageData; + } finally { + if (ptr) { + module2._free(ptr); + } + } + } + static cleanup() { + this.#modulePromise = null; + } + static parseImageProperties(stream) { + let newByte = stream.getByte(); + while (newByte >= 0) { + const oldByte = newByte; + newByte = stream.getByte(); + const code = oldByte << 8 | newByte; + if (code === 65361) { + stream.skip(4); + const Xsiz = stream.getInt32() >>> 0; + const Ysiz = stream.getInt32() >>> 0; + const XOsiz = stream.getInt32() >>> 0; + const YOsiz = stream.getInt32() >>> 0; + stream.skip(16); + const Csiz = stream.getUint16(); + return { + width: Xsiz - XOsiz, + height: Ysiz - YOsiz, + bitsPerComponent: 8, + componentsCount: Csiz + }; + } + } + throw new JpxError("No size marker found in JPX stream"); + } + }; + InitialState = []; + addState(InitialState, [OPS2.save, OPS2.transform, OPS2.paintInlineImageXObject, OPS2.restore], null, function iterateInlineImageGroup(context2, i) { + const fnArray = context2.fnArray; + const iFirstSave = context2.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS2.save; + case 1: + return fnArray[i] === OPS2.transform; + case 2: + return fnArray[i] === OPS2.paintInlineImageXObject; + case 3: + return fnArray[i] === OPS2.restore; + } + throw new Error(`iterateInlineImageGroup - invalid pos: ${pos}`); + }, function foundInlineImageGroup(context2, i) { + const MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10; + const MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200; + const MAX_WIDTH = 1e3; + const IMAGE_PADDING = 1; + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const curr = context2.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIIXO = curr - 1; + const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK); + if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) { + return i - (i - iFirstSave) % 4; + } + let maxX = 0; + const map3 = []; + let maxLineHeight = 0; + let currentX = IMAGE_PADDING, currentY = IMAGE_PADDING; + for (let q = 0; q < count; q++) { + const transform2 = argsArray[iFirstTransform + (q << 2)]; + const img2 = argsArray[iFirstPIIXO + (q << 2)][0]; + if (currentX + img2.width > MAX_WIDTH) { + maxX = Math.max(maxX, currentX); + currentY += maxLineHeight + 2 * IMAGE_PADDING; + currentX = 0; + maxLineHeight = 0; + } + map3.push({ + transform: transform2, + x: currentX, + y: currentY, + w: img2.width, + h: img2.height + }); + currentX += img2.width + 2 * IMAGE_PADDING; + maxLineHeight = Math.max(maxLineHeight, img2.height); + } + const imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING; + const imgHeight = currentY + maxLineHeight + IMAGE_PADDING; + const imgData = new Uint8Array(imgWidth * imgHeight * 4); + const imgRowSize = imgWidth << 2; + for (let q = 0; q < count; q++) { + const data = argsArray[iFirstPIIXO + (q << 2)][0].data; + const rowSize = map3[q].w << 2; + let dataOffset = 0; + let offset = map3[q].x + map3[q].y * imgWidth << 2; + imgData.set(data.subarray(0, rowSize), offset - imgRowSize); + for (let k = 0, kk = map3[q].h; k < kk; k++) { + imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset); + dataOffset += rowSize; + offset += imgRowSize; + } + imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset); + while (offset >= 0) { + data[offset - 4] = data[offset]; + data[offset - 3] = data[offset + 1]; + data[offset - 2] = data[offset + 2]; + data[offset - 1] = data[offset + 3]; + data[offset + rowSize] = data[offset + rowSize - 4]; + data[offset + rowSize + 1] = data[offset + rowSize - 3]; + data[offset + rowSize + 2] = data[offset + rowSize - 2]; + data[offset + rowSize + 3] = data[offset + rowSize - 1]; + offset -= imgRowSize; + } + } + const img = { + width: imgWidth, + height: imgHeight + }; + if (context2.isOffscreenCanvasSupported) { + const canvas = new OffscreenCanvas(imgWidth, imgHeight); + const ctx = canvas.getContext("2d"); + ctx.putImageData(new ImageData(new Uint8ClampedArray(imgData.buffer), imgWidth, imgHeight), 0, 0); + img.bitmap = canvas.transferToImageBitmap(); + img.data = null; + } else { + img.kind = ImageKind2.RGBA_32BPP; + img.data = imgData; + } + fnArray.splice(iFirstSave, count * 4, OPS2.paintInlineImageXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [img, map3]); + return iFirstSave + 1; + }); + addState(InitialState, [OPS2.save, OPS2.transform, OPS2.paintImageMaskXObject, OPS2.restore], null, function iterateImageMaskGroup(context2, i) { + const fnArray = context2.fnArray; + const iFirstSave = context2.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS2.save; + case 1: + return fnArray[i] === OPS2.transform; + case 2: + return fnArray[i] === OPS2.paintImageMaskXObject; + case 3: + return fnArray[i] === OPS2.restore; + } + throw new Error(`iterateImageMaskGroup - invalid pos: ${pos}`); + }, function foundImageMaskGroup(context2, i) { + const MIN_IMAGES_IN_MASKS_BLOCK = 10; + const MAX_IMAGES_IN_MASKS_BLOCK = 100; + const MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1e3; + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const curr = context2.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIMXO = curr - 1; + let count = Math.floor((i - iFirstSave) / 4); + if (count < MIN_IMAGES_IN_MASKS_BLOCK) { + return i - (i - iFirstSave) % 4; + } + let isSameImage = false; + let iTransform, transformArgs; + const firstPIMXOArg0 = argsArray[iFirstPIMXO][0]; + const firstTransformArg0 = argsArray[iFirstTransform][0], firstTransformArg1 = argsArray[iFirstTransform][1], firstTransformArg2 = argsArray[iFirstTransform][2], firstTransformArg3 = argsArray[iFirstTransform][3]; + if (firstTransformArg1 === firstTransformArg2) { + isSameImage = true; + iTransform = iFirstTransform + 4; + let iPIMXO = iFirstPIMXO + 4; + for (let q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) { + transformArgs = argsArray[iTransform]; + if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== firstTransformArg1 || transformArgs[2] !== firstTransformArg2 || transformArgs[3] !== firstTransformArg3) { + if (q < MIN_IMAGES_IN_MASKS_BLOCK) { + isSameImage = false; + } else { + count = q; + } + break; + } + } + } + if (isSameImage) { + count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK); + const positions = new Float32Array(count * 2); + iTransform = iFirstTransform; + for (let q = 0; q < count; q++, iTransform += 4) { + transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + fnArray.splice(iFirstSave, count * 4, OPS2.paintImageMaskXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg1, firstTransformArg2, firstTransformArg3, positions]); + } else { + count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK); + const images = []; + for (let q = 0; q < count; q++) { + transformArgs = argsArray[iFirstTransform + (q << 2)]; + const maskParams = argsArray[iFirstPIMXO + (q << 2)][0]; + images.push({ + data: maskParams.data, + width: maskParams.width, + height: maskParams.height, + interpolate: maskParams.interpolate, + count: maskParams.count, + transform: transformArgs + }); + } + fnArray.splice(iFirstSave, count * 4, OPS2.paintImageMaskXObjectGroup); + argsArray.splice(iFirstSave, count * 4, [images]); + } + return iFirstSave + 1; + }); + addState(InitialState, [OPS2.save, OPS2.transform, OPS2.paintImageXObject, OPS2.restore], function(context2) { + const argsArray = context2.argsArray; + const iFirstTransform = context2.iCurr - 2; + return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0; + }, function iterateImageGroup(context2, i) { + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const iFirstSave = context2.iCurr - 3; + const pos = (i - iFirstSave) % 4; + switch (pos) { + case 0: + return fnArray[i] === OPS2.save; + case 1: + if (fnArray[i] !== OPS2.transform) { + return false; + } + const iFirstTransform = context2.iCurr - 2; + const firstTransformArg0 = argsArray[iFirstTransform][0]; + const firstTransformArg3 = argsArray[iFirstTransform][3]; + if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) { + return false; + } + return true; + case 2: + if (fnArray[i] !== OPS2.paintImageXObject) { + return false; + } + const iFirstPIXO = context2.iCurr - 1; + const firstPIXOArg0 = argsArray[iFirstPIXO][0]; + if (argsArray[i][0] !== firstPIXOArg0) { + return false; + } + return true; + case 3: + return fnArray[i] === OPS2.restore; + } + throw new Error(`iterateImageGroup - invalid pos: ${pos}`); + }, function(context2, i) { + const MIN_IMAGES_IN_BLOCK = 3; + const MAX_IMAGES_IN_BLOCK = 1e3; + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const curr = context2.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstPIXO = curr - 1; + const firstPIXOArg0 = argsArray[iFirstPIXO][0]; + const firstTransformArg0 = argsArray[iFirstTransform][0]; + const firstTransformArg3 = argsArray[iFirstTransform][3]; + const count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK); + if (count < MIN_IMAGES_IN_BLOCK) { + return i - (i - iFirstSave) % 4; + } + const positions = new Float32Array(count * 2); + let iTransform = iFirstTransform; + for (let q = 0; q < count; q++, iTransform += 4) { + const transformArgs = argsArray[iTransform]; + positions[q << 1] = transformArgs[4]; + positions[(q << 1) + 1] = transformArgs[5]; + } + const args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions]; + fnArray.splice(iFirstSave, count * 4, OPS2.paintImageXObjectRepeat); + argsArray.splice(iFirstSave, count * 4, args); + return iFirstSave + 1; + }); + addState(InitialState, [OPS2.beginText, OPS2.setFont, OPS2.setTextMatrix, OPS2.showText, OPS2.endText], null, function iterateShowTextGroup(context2, i) { + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const iFirstSave = context2.iCurr - 4; + const pos = (i - iFirstSave) % 5; + switch (pos) { + case 0: + return fnArray[i] === OPS2.beginText; + case 1: + return fnArray[i] === OPS2.setFont; + case 2: + return fnArray[i] === OPS2.setTextMatrix; + case 3: + if (fnArray[i] !== OPS2.showText) { + return false; + } + const iFirstSetFont = context2.iCurr - 3; + const firstSetFontArg0 = argsArray[iFirstSetFont][0]; + const firstSetFontArg1 = argsArray[iFirstSetFont][1]; + if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) { + return false; + } + return true; + case 4: + return fnArray[i] === OPS2.endText; + } + throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`); + }, function(context2, i) { + const MIN_CHARS_IN_BLOCK = 3; + const MAX_CHARS_IN_BLOCK = 1e3; + const fnArray = context2.fnArray, argsArray = context2.argsArray; + const curr = context2.iCurr; + const iFirstBeginText = curr - 4; + const iFirstSetFont = curr - 3; + const iFirstSetTextMatrix = curr - 2; + const iFirstShowText = curr - 1; + const iFirstEndText = curr; + const firstSetFontArg0 = argsArray[iFirstSetFont][0]; + const firstSetFontArg1 = argsArray[iFirstSetFont][1]; + let count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK); + if (count < MIN_CHARS_IN_BLOCK) { + return i - (i - iFirstBeginText) % 5; + } + let iFirst = iFirstBeginText; + if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) { + count++; + iFirst -= 5; + } + let iEndText = iFirst + 4; + for (let q = 1; q < count; q++) { + fnArray.splice(iEndText, 3); + argsArray.splice(iEndText, 3); + iEndText += 2; + } + return iEndText + 1; + }); + addState(InitialState, [OPS2.save, OPS2.transform, OPS2.constructPath, OPS2.restore], (context2) => { + const argsArray = context2.argsArray; + const iFirstConstructPath = context2.iCurr - 1; + const op = argsArray[iFirstConstructPath][0]; + if (op !== OPS2.stroke && op !== OPS2.closeStroke && op !== OPS2.fillStroke && op !== OPS2.eoFillStroke && op !== OPS2.closeFillStroke && op !== OPS2.closeEOFillStroke) { + return true; + } + const iFirstTransform = context2.iCurr - 2; + const transform2 = argsArray[iFirstTransform]; + return transform2[0] === 1 && transform2[1] === 0 && transform2[2] === 0 && transform2[3] === 1; + }, () => false, (context2, i) => { + const { + fnArray, + argsArray + } = context2; + const curr = context2.iCurr; + const iFirstSave = curr - 3; + const iFirstTransform = curr - 2; + const iFirstConstructPath = curr - 1; + const args = argsArray[iFirstConstructPath]; + const transform2 = argsArray[iFirstTransform]; + const [, [buffer2], minMax] = args; + if (minMax) { + Util2.scaleMinMax(transform2, minMax); + for (let k = 0, kk = buffer2.length; k < kk; ) { + switch (buffer2[k++]) { + case DrawOPS3.moveTo: + case DrawOPS3.lineTo: + Util2.applyTransform(buffer2, transform2, k); + k += 2; + break; + case DrawOPS3.curveTo: + Util2.applyTransformToBezier(buffer2, transform2, k); + k += 6; + break; + } + } + } + fnArray.splice(iFirstSave, 4, OPS2.constructPath); + argsArray.splice(iFirstSave, 4, args); + return iFirstSave + 1; + }); + NullOptimizer = class { + constructor(queue) { + this.queue = queue; + } + _optimize() { + } + push(fn, args) { + this.queue.fnArray.push(fn); + this.queue.argsArray.push(args); + this._optimize(); + } + flush() { + } + reset() { + } + }; + QueueOptimizer = class extends NullOptimizer { + constructor(queue) { + super(queue); + this.state = null; + this.context = { + iCurr: 0, + fnArray: queue.fnArray, + argsArray: queue.argsArray, + isOffscreenCanvasSupported: OperatorList.isOffscreenCanvasSupported + }; + this.match = null; + this.lastProcessed = 0; + } + _optimize() { + const fnArray = this.queue.fnArray; + let i = this.lastProcessed, ii = fnArray.length; + let state = this.state; + let match = this.match; + if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) { + this.lastProcessed = ii; + return; + } + const context2 = this.context; + while (i < ii) { + if (match) { + const iterate = (0, match.iterateFn)(context2, i); + if (iterate) { + i++; + continue; + } + i = (0, match.processFn)(context2, i + 1); + ii = fnArray.length; + match = null; + state = null; + if (i >= ii) { + break; + } + } + state = (state || InitialState)[fnArray[i]]; + if (!state || Array.isArray(state)) { + i++; + continue; + } + context2.iCurr = i; + i++; + if (state.checkFn && !(0, state.checkFn)(context2)) { + state = null; + continue; + } + match = state; + state = null; + } + this.state = state; + this.match = match; + this.lastProcessed = i; + } + flush() { + while (this.match) { + const length = this.queue.fnArray.length; + this.lastProcessed = (0, this.match.processFn)(this.context, length); + this.match = null; + this.state = null; + this._optimize(); + } + } + reset() { + this.state = null; + this.match = null; + this.lastProcessed = 0; + } + }; + OperatorList = class _OperatorList { + static CHUNK_SIZE = 1e3; + static CHUNK_SIZE_ABOUT = this.CHUNK_SIZE - 5; + static isOffscreenCanvasSupported = false; + constructor(intent = 0, streamSink) { + this._streamSink = streamSink; + this.fnArray = []; + this.argsArray = []; + this.optimizer = streamSink && !(intent & RenderingIntentFlag2.OPLIST) ? new QueueOptimizer(this) : new NullOptimizer(this); + this.dependencies = /* @__PURE__ */ new Set(); + this._totalLength = 0; + this.weight = 0; + this._resolved = streamSink ? null : Promise.resolve(); + } + static setOptions({ + isOffscreenCanvasSupported + }) { + this.isOffscreenCanvasSupported = isOffscreenCanvasSupported; + } + get length() { + return this.argsArray.length; + } + get ready() { + return this._resolved || this._streamSink.ready; + } + get totalLength() { + return this._totalLength + this.length; + } + addOp(fn, args) { + this.optimizer.push(fn, args); + this.weight++; + if (this._streamSink) { + if (this.weight >= _OperatorList.CHUNK_SIZE) { + this.flush(); + } else if (this.weight >= _OperatorList.CHUNK_SIZE_ABOUT && (fn === OPS2.restore || fn === OPS2.endText)) { + this.flush(); + } + } + } + addImageOps(fn, args, optionalContent, hasMask = false) { + if (hasMask) { + this.addOp(OPS2.save); + this.addOp(OPS2.setGState, [[["SMask", false]]]); + } + if (optionalContent !== void 0) { + this.addOp(OPS2.beginMarkedContentProps, ["OC", optionalContent]); + } + this.addOp(fn, args); + if (optionalContent !== void 0) { + this.addOp(OPS2.endMarkedContent, []); + } + if (hasMask) { + this.addOp(OPS2.restore); + } + } + addDependency(dependency) { + if (this.dependencies.has(dependency)) { + return; + } + this.dependencies.add(dependency); + this.addOp(OPS2.dependency, [dependency]); + } + addDependencies(dependencies) { + for (const dependency of dependencies) { + this.addDependency(dependency); + } + } + addOpList(opList) { + if (!(opList instanceof _OperatorList)) { + warn2('addOpList - ignoring invalid "opList" parameter.'); + return; + } + for (const dependency of opList.dependencies) { + this.dependencies.add(dependency); + } + for (let i = 0, ii = opList.length; i < ii; i++) { + this.addOp(opList.fnArray[i], opList.argsArray[i]); + } + } + getIR() { + return { + fnArray: this.fnArray, + argsArray: this.argsArray, + length: this.length + }; + } + get _transfers() { + const transfers = []; + const { + fnArray, + argsArray, + length + } = this; + for (let i = 0; i < length; i++) { + switch (fnArray[i]) { + case OPS2.paintInlineImageXObject: + case OPS2.paintInlineImageXObjectGroup: + case OPS2.paintImageMaskXObject: { + const { + bitmap, + data + } = argsArray[i][0]; + if (bitmap || data?.buffer) { + transfers.push(bitmap || data.buffer); + } + break; + } + case OPS2.constructPath: { + const [, [data], minMax] = argsArray[i]; + if (data) { + transfers.push(data.buffer, minMax.buffer); + } + break; + } + case OPS2.paintFormXObjectBegin: + const [matrix, bbox] = argsArray[i]; + if (matrix) { + transfers.push(matrix.buffer); + } + if (bbox) { + transfers.push(bbox.buffer); + } + break; + case OPS2.setTextMatrix: + transfers.push(argsArray[i][0].buffer); + break; + } + } + return transfers; + } + flush(lastChunk = false, separateAnnots = null) { + this.optimizer.flush(); + const length = this.length; + this._totalLength += length; + this._streamSink.enqueue({ + fnArray: this.fnArray, + argsArray: this.argsArray, + lastChunk, + separateAnnots, + length + }, 1, this._transfers); + this.dependencies.clear(); + this.fnArray.length = 0; + this.argsArray.length = 0; + this.weight = 0; + this.optimizer.reset(); + } + }; + es_iterator_find2 = __webpack_require__2(116); + es_regexp_flags = __webpack_require__2(9479); + es_iterator_for_each2 = __webpack_require__2(7588); + MAX_NUM_SIZE = 16; + MAX_ENCODED_NUM_SIZE = 19; + BinaryCMapStream = class { + constructor(data) { + this.buffer = data; + this.pos = 0; + this.end = data.length; + this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE); + } + readByte() { + if (this.pos >= this.end) { + return -1; + } + return this.buffer[this.pos++]; + } + readNumber() { + let n = 0; + let last2; + do { + const b2 = this.readByte(); + if (b2 < 0) { + throw new FormatError3("unexpected EOF in bcmap"); + } + last2 = !(b2 & 128); + n = n << 7 | b2 & 127; + } while (!last2); + return n; + } + readSigned() { + const n = this.readNumber(); + return n & 1 ? ~(n >>> 1) : n >>> 1; + } + readHex(num, size3) { + num.set(this.buffer.subarray(this.pos, this.pos + size3 + 1)); + this.pos += size3 + 1; + } + readHexNumber(num, size3) { + let last2; + const stack = this.tmpBuf; + let sp = 0; + do { + const b2 = this.readByte(); + if (b2 < 0) { + throw new FormatError3("unexpected EOF in bcmap"); + } + last2 = !(b2 & 128); + stack[sp++] = b2 & 127; + } while (!last2); + let i = size3, buffer2 = 0, bufferSize = 0; + while (i >= 0) { + while (bufferSize < 8 && stack.length > 0) { + buffer2 |= stack[--sp] << bufferSize; + bufferSize += 7; + } + num[i] = buffer2 & 255; + i--; + buffer2 >>= 8; + bufferSize -= 8; + } + } + readHexSigned(num, size3) { + this.readHexNumber(num, size3); + const sign = num[size3] & 1 ? 255 : 0; + let c = 0; + for (let i = 0; i <= size3; i++) { + c = (c & 1) << 8 | num[i]; + num[i] = c >> 1 ^ sign; + } + } + readString() { + const len = this.readNumber(), buf = new Array(len); + for (let i = 0; i < len; i++) { + buf[i] = this.readNumber(); + } + return String.fromCharCode(...buf); + } + }; + BinaryCMapReader = class { + async process(data, cMap, extend2) { + const stream = new BinaryCMapStream(data); + const header = stream.readByte(); + cMap.vertical = !!(header & 1); + let useCMap = null; + const start = new Uint8Array(MAX_NUM_SIZE); + const end = new Uint8Array(MAX_NUM_SIZE); + const char2 = new Uint8Array(MAX_NUM_SIZE); + const charCode = new Uint8Array(MAX_NUM_SIZE); + const tmp = new Uint8Array(MAX_NUM_SIZE); + let code; + let b2; + while ((b2 = stream.readByte()) >= 0) { + const type = b2 >> 5; + if (type === 7) { + switch (b2 & 31) { + case 0: + stream.readString(); + break; + case 1: + useCMap = stream.readString(); + break; + } + continue; + } + const sequence = !!(b2 & 16); + const dataSize = b2 & 15; + if (dataSize + 1 > MAX_NUM_SIZE) { + throw new Error("BinaryCMapReader.process: Invalid dataSize."); + } + const ucs2DataSize = 1; + const subitemsCount = stream.readNumber(); + switch (type) { + case 0: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize)); + } + break; + case 1: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + stream.readNumber(); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + stream.readNumber(); + } + break; + case 2: + stream.readHex(char2, dataSize); + code = stream.readNumber(); + cMap.mapOne(hexToInt(char2, dataSize), code); + for (let i = 1; i < subitemsCount; i++) { + incHex(char2, dataSize); + if (!sequence) { + stream.readHexNumber(tmp, dataSize); + addHex(char2, tmp, dataSize); + } + code = stream.readSigned() + (code + 1); + cMap.mapOne(hexToInt(char2, dataSize), code); + } + break; + case 3: + stream.readHex(start, dataSize); + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, dataSize); + if (!sequence) { + stream.readHexNumber(start, dataSize); + addHex(start, end, dataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, dataSize); + addHex(end, start, dataSize); + code = stream.readNumber(); + cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code); + } + break; + case 4: + stream.readHex(char2, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapOne(hexToInt(char2, ucs2DataSize), hexToStr(charCode, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(char2, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(tmp, ucs2DataSize); + addHex(char2, tmp, ucs2DataSize); + } + incHex(charCode, dataSize); + stream.readHexSigned(tmp, dataSize); + addHex(charCode, tmp, dataSize); + cMap.mapOne(hexToInt(char2, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + case 5: + stream.readHex(start, ucs2DataSize); + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + for (let i = 1; i < subitemsCount; i++) { + incHex(end, ucs2DataSize); + if (!sequence) { + stream.readHexNumber(start, ucs2DataSize); + addHex(start, end, ucs2DataSize); + } else { + start.set(end); + } + stream.readHexNumber(end, ucs2DataSize); + addHex(end, start, ucs2DataSize); + stream.readHex(charCode, dataSize); + cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize)); + } + break; + default: + throw new Error(`BinaryCMapReader.process - unknown type: ${type}`); + } + } + if (useCMap) { + return extend2(useCMap); + } + return cMap; + } + }; + Ascii85Stream = class extends DecodeStream { + constructor(str, maybeLength) { + if (maybeLength) { + maybeLength *= 0.8; + } + super(maybeLength); + this.str = str; + this.dict = str.dict; + this.input = new Uint8Array(5); + } + readBlock() { + const TILDA_CHAR = 126; + const Z_LOWER_CHAR = 122; + const EOF2 = -1; + const str = this.str; + let c = str.getByte(); + while (isWhiteSpace(c)) { + c = str.getByte(); + } + if (c === EOF2 || c === TILDA_CHAR) { + this.eof = true; + return; + } + const bufferLength = this.bufferLength; + let buffer2, i; + if (c === Z_LOWER_CHAR) { + buffer2 = this.ensureBuffer(bufferLength + 4); + for (i = 0; i < 4; ++i) { + buffer2[bufferLength + i] = 0; + } + this.bufferLength += 4; + } else { + const input2 = this.input; + input2[0] = c; + for (i = 1; i < 5; ++i) { + c = str.getByte(); + while (isWhiteSpace(c)) { + c = str.getByte(); + } + input2[i] = c; + if (c === EOF2 || c === TILDA_CHAR) { + break; + } + } + buffer2 = this.ensureBuffer(bufferLength + i - 1); + this.bufferLength += i - 1; + if (i < 5) { + for (; i < 5; ++i) { + input2[i] = 33 + 84; + } + this.eof = true; + } + let t = 0; + for (i = 0; i < 5; ++i) { + t = t * 85 + (input2[i] - 33); + } + for (i = 3; i >= 0; --i) { + buffer2[bufferLength + i] = t & 255; + t >>= 8; + } + } + } + }; + AsciiHexStream = class extends DecodeStream { + constructor(str, maybeLength) { + if (maybeLength) { + maybeLength *= 0.5; + } + super(maybeLength); + this.str = str; + this.dict = str.dict; + this.firstDigit = -1; + } + readBlock() { + const UPSTREAM_BLOCK_SIZE = 8e3; + const bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE); + if (!bytes.length) { + this.eof = true; + return; + } + const maxDecodeLength = bytes.length + 1 >> 1; + const buffer2 = this.ensureBuffer(this.bufferLength + maxDecodeLength); + let bufferLength = this.bufferLength; + let firstDigit = this.firstDigit; + for (const ch2 of bytes) { + let digit; + if (ch2 >= 48 && ch2 <= 57) { + digit = ch2 & 15; + } else if (ch2 >= 65 && ch2 <= 70 || ch2 >= 97 && ch2 <= 102) { + digit = (ch2 & 15) + 9; + } else if (ch2 === 62) { + this.eof = true; + break; + } else { + continue; + } + if (firstDigit < 0) { + firstDigit = digit; + } else { + buffer2[bufferLength++] = firstDigit << 4 | digit; + firstDigit = -1; + } + } + if (firstDigit >= 0 && this.eof) { + buffer2[bufferLength++] = firstDigit << 4; + firstDigit = -1; + } + this.firstDigit = firstDigit; + this.bufferLength = bufferLength; + } + }; + ccittEOL = -2; + ccittEOF = -1; + twoDimPass = 0; + twoDimHoriz = 1; + twoDimVert0 = 2; + twoDimVertR1 = 3; + twoDimVertL1 = 4; + twoDimVertR2 = 5; + twoDimVertL2 = 6; + twoDimVertR3 = 7; + twoDimVertL3 = 8; + twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]]; + whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]]; + whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]]; + blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]]; + blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]]; + blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]]; + CCITTFaxDecoder = class { + constructor(source, options = {}) { + if (typeof source?.next !== "function") { + throw new Error('CCITTFaxDecoder - invalid "source" parameter.'); + } + this.source = source; + this.eof = false; + this.encoding = options.K || 0; + this.eoline = options.EndOfLine || false; + this.byteAlign = options.EncodedByteAlign || false; + this.columns = options.Columns || 1728; + this.rows = options.Rows || 0; + this.eoblock = options.EndOfBlock ?? true; + this.black = options.BlackIs1 || false; + this.codingLine = new Uint32Array(this.columns + 1); + this.refLine = new Uint32Array(this.columns + 2); + this.codingLine[0] = this.columns; + this.codingPos = 0; + this.row = 0; + this.nextLine2D = this.encoding < 0; + this.inputBits = 0; + this.inputBuf = 0; + this.outputBits = 0; + this.rowsDone = false; + let code1; + while ((code1 = this._lookBits(12)) === 0) { + this._eatBits(1); + } + if (code1 === 1) { + this._eatBits(12); + } + if (this.encoding > 0) { + this.nextLine2D = !this._lookBits(1); + this._eatBits(1); + } + } + readNextChar() { + if (this.eof) { + return -1; + } + const refLine = this.refLine; + const codingLine = this.codingLine; + const columns = this.columns; + let refPos, blackPixels, bits, i; + if (this.outputBits === 0) { + if (this.rowsDone) { + this.eof = true; + } + if (this.eof) { + return -1; + } + this.err = false; + let code1, code2, code3; + if (this.nextLine2D) { + for (i = 0; codingLine[i] < columns; ++i) { + refLine[i] = codingLine[i]; + } + refLine[i++] = columns; + refLine[i] = columns; + codingLine[0] = 0; + this.codingPos = 0; + refPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = this._getTwoDimCode(); + switch (code1) { + case twoDimPass: + this._addPixels(refLine[refPos + 1], blackPixels); + if (refLine[refPos + 1] < columns) { + refPos += 2; + } + break; + case twoDimHoriz: + code1 = code2 = 0; + if (blackPixels) { + do { + code1 += code3 = this._getBlackCode(); + } while (code3 >= 64); + do { + code2 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + do { + code2 += code3 = this._getBlackCode(); + } while (code3 >= 64); + } + this._addPixels(codingLine[this.codingPos] + code1, blackPixels); + if (codingLine[this.codingPos] < columns) { + this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1); + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + break; + case twoDimVertR3: + this._addPixels(refLine[refPos] + 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR2: + this._addPixels(refLine[refPos] + 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertR1: + this._addPixels(refLine[refPos] + 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVert0: + this._addPixels(refLine[refPos], blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + ++refPos; + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL3: + this._addPixelsNeg(refLine[refPos] - 3, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL2: + this._addPixelsNeg(refLine[refPos] - 2, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case twoDimVertL1: + this._addPixelsNeg(refLine[refPos] - 1, blackPixels); + blackPixels ^= 1; + if (codingLine[this.codingPos] < columns) { + if (refPos > 0) { + --refPos; + } else { + ++refPos; + } + while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) { + refPos += 2; + } + } + break; + case ccittEOF: + this._addPixels(columns, 0); + this.eof = true; + break; + default: + info2("bad 2d code"); + this._addPixels(columns, 0); + this.err = true; + } + } + } else { + codingLine[0] = 0; + this.codingPos = 0; + blackPixels = 0; + while (codingLine[this.codingPos] < columns) { + code1 = 0; + if (blackPixels) { + do { + code1 += code3 = this._getBlackCode(); + } while (code3 >= 64); + } else { + do { + code1 += code3 = this._getWhiteCode(); + } while (code3 >= 64); + } + this._addPixels(codingLine[this.codingPos] + code1, blackPixels); + blackPixels ^= 1; + } + } + let gotEOL = false; + if (this.byteAlign) { + this.inputBits &= ~7; + } + if (!this.eoblock && this.row === this.rows - 1) { + this.rowsDone = true; + } else { + code1 = this._lookBits(12); + if (this.eoline) { + while (code1 !== ccittEOF && code1 !== 1) { + this._eatBits(1); + code1 = this._lookBits(12); + } + } else { + while (code1 === 0) { + this._eatBits(1); + code1 = this._lookBits(12); + } + } + if (code1 === 1) { + this._eatBits(12); + gotEOL = true; + } else if (code1 === ccittEOF) { + this.eof = true; + } + } + if (!this.eof && this.encoding > 0 && !this.rowsDone) { + this.nextLine2D = !this._lookBits(1); + this._eatBits(1); + } + if (this.eoblock && gotEOL && this.byteAlign) { + code1 = this._lookBits(12); + if (code1 === 1) { + this._eatBits(12); + if (this.encoding > 0) { + this._lookBits(1); + this._eatBits(1); + } + if (this.encoding >= 0) { + for (i = 0; i < 4; ++i) { + code1 = this._lookBits(12); + if (code1 !== 1) { + info2("bad rtc code: " + code1); + } + this._eatBits(12); + if (this.encoding > 0) { + this._lookBits(1); + this._eatBits(1); + } + } + } + this.eof = true; + } + } else if (this.err && this.eoline) { + while (true) { + code1 = this._lookBits(13); + if (code1 === ccittEOF) { + this.eof = true; + return -1; + } + if (code1 >> 1 === 1) { + break; + } + this._eatBits(1); + } + this._eatBits(12); + if (this.encoding > 0) { + this._eatBits(1); + this.nextLine2D = !(code1 & 1); + } + } + this.outputBits = codingLine[0] > 0 ? codingLine[this.codingPos = 0] : codingLine[this.codingPos = 1]; + this.row++; + } + let c; + if (this.outputBits >= 8) { + c = this.codingPos & 1 ? 0 : 255; + this.outputBits -= 8; + if (this.outputBits === 0 && codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } + } else { + bits = 8; + c = 0; + do { + if (typeof this.outputBits !== "number") { + throw new FormatError3('Invalid /CCITTFaxDecode data, "outputBits" must be a number.'); + } + if (this.outputBits > bits) { + c <<= bits; + if (!(this.codingPos & 1)) { + c |= 255 >> 8 - bits; + } + this.outputBits -= bits; + bits = 0; + } else { + c <<= this.outputBits; + if (!(this.codingPos & 1)) { + c |= 255 >> 8 - this.outputBits; + } + bits -= this.outputBits; + this.outputBits = 0; + if (codingLine[this.codingPos] < columns) { + this.codingPos++; + this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1]; + } else if (bits > 0) { + c <<= bits; + bits = 0; + } + } + } while (bits); + } + if (this.black) { + c ^= 255; + } + return c; + } + _addPixels(a1, blackPixels) { + const codingLine = this.codingLine; + let codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info2("row is wrong length"); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + } + _addPixelsNeg(a1, blackPixels) { + const codingLine = this.codingLine; + let codingPos = this.codingPos; + if (a1 > codingLine[codingPos]) { + if (a1 > this.columns) { + info2("row is wrong length"); + this.err = true; + a1 = this.columns; + } + if (codingPos & 1 ^ blackPixels) { + ++codingPos; + } + codingLine[codingPos] = a1; + } else if (a1 < codingLine[codingPos]) { + if (a1 < 0) { + info2("invalid code"); + this.err = true; + a1 = 0; + } + while (codingPos > 0 && a1 < codingLine[codingPos - 1]) { + --codingPos; + } + codingLine[codingPos] = a1; + } + this.codingPos = codingPos; + } + _findTableCode(start, end, table2, limit) { + const limitValue = limit || 0; + for (let i = start; i <= end; ++i) { + let code = this._lookBits(i); + if (code === ccittEOF) { + return [true, 1, false]; + } + if (i < end) { + code <<= end - i; + } + if (!limitValue || code >= limitValue) { + const p = table2[code - limitValue]; + if (p[0] === i) { + this._eatBits(i); + return [true, p[1], true]; + } + } + } + return [false, 0, false]; + } + _getTwoDimCode() { + let code = 0; + let p; + if (this.eoblock) { + code = this._lookBits(7); + p = twoDimTable[code]; + if (p?.[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + const result2 = this._findTableCode(1, 7, twoDimTable); + if (result2[0] && result2[2]) { + return result2[1]; + } + } + info2("Bad two dim code"); + return ccittEOF; + } + _getWhiteCode() { + let code = 0; + let p; + if (this.eoblock) { + code = this._lookBits(12); + if (code === ccittEOF) { + return 1; + } + p = code >> 5 === 0 ? whiteTable1[code] : whiteTable2[code >> 3]; + if (p[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + let result2 = this._findTableCode(1, 9, whiteTable2); + if (result2[0]) { + return result2[1]; + } + result2 = this._findTableCode(11, 12, whiteTable1); + if (result2[0]) { + return result2[1]; + } + } + info2("bad white code"); + this._eatBits(1); + return 1; + } + _getBlackCode() { + let code, p; + if (this.eoblock) { + code = this._lookBits(13); + if (code === ccittEOF) { + return 1; + } + if (code >> 7 === 0) { + p = blackTable1[code]; + } else if (code >> 9 === 0 && code >> 7 !== 0) { + p = blackTable2[(code >> 1) - 64]; + } else { + p = blackTable3[code >> 7]; + } + if (p[0] > 0) { + this._eatBits(p[0]); + return p[1]; + } + } else { + let result2 = this._findTableCode(2, 6, blackTable3); + if (result2[0]) { + return result2[1]; + } + result2 = this._findTableCode(7, 12, blackTable2, 64); + if (result2[0]) { + return result2[1]; + } + result2 = this._findTableCode(10, 13, blackTable1); + if (result2[0]) { + return result2[1]; + } + } + info2("bad black code"); + this._eatBits(1); + return 1; + } + _lookBits(n) { + let c; + while (this.inputBits < n) { + if ((c = this.source.next()) === -1) { + if (this.inputBits === 0) { + return ccittEOF; + } + return this.inputBuf << n - this.inputBits & 65535 >> 16 - n; + } + this.inputBuf = this.inputBuf << 8 | c; + this.inputBits += 8; + } + return this.inputBuf >> this.inputBits - n & 65535 >> 16 - n; + } + _eatBits(n) { + if ((this.inputBits -= n) < 0) { + this.inputBits = 0; + } + } + }; + CCITTFaxStream = class extends DecodeStream { + constructor(str, maybeLength, params) { + super(maybeLength); + this.str = str; + this.dict = str.dict; + if (!(params instanceof Dict)) { + params = Dict.empty; + } + const source = { + next() { + return str.getByte(); + } + }; + this.ccittFaxDecoder = new CCITTFaxDecoder(source, { + K: params.get("K"), + EndOfLine: params.get("EndOfLine"), + EncodedByteAlign: params.get("EncodedByteAlign"), + Columns: params.get("Columns"), + Rows: params.get("Rows"), + EndOfBlock: params.get("EndOfBlock"), + BlackIs1: params.get("BlackIs1") + }); + } + readBlock() { + while (!this.eof) { + const c = this.ccittFaxDecoder.readNextChar(); + if (c === -1) { + this.eof = true; + return; + } + this.ensureBuffer(this.bufferLength + 1); + this.buffer[this.bufferLength++] = c; + } + } + }; + codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]); + lengthDecode = new Int32Array([3, 4, 5, 6, 7, 8, 9, 10, 65547, 65549, 65551, 65553, 131091, 131095, 131099, 131103, 196643, 196651, 196659, 196667, 262211, 262227, 262243, 262259, 327811, 327843, 327875, 327907, 258, 258, 258]); + distDecode = new Int32Array([1, 2, 3, 4, 65541, 65543, 131081, 131085, 196625, 196633, 262177, 262193, 327745, 327777, 393345, 393409, 459009, 459137, 524801, 525057, 590849, 591361, 657409, 658433, 724993, 727041, 794625, 798721, 868353, 876545]); + fixedLitCodeTab = [new Int32Array([459008, 524368, 524304, 524568, 459024, 524400, 524336, 590016, 459016, 524384, 524320, 589984, 524288, 524416, 524352, 590048, 459012, 524376, 524312, 589968, 459028, 524408, 524344, 590032, 459020, 524392, 524328, 59e4, 524296, 524424, 524360, 590064, 459010, 524372, 524308, 524572, 459026, 524404, 524340, 590024, 459018, 524388, 524324, 589992, 524292, 524420, 524356, 590056, 459014, 524380, 524316, 589976, 459030, 524412, 524348, 590040, 459022, 524396, 524332, 590008, 524300, 524428, 524364, 590072, 459009, 524370, 524306, 524570, 459025, 524402, 524338, 590020, 459017, 524386, 524322, 589988, 524290, 524418, 524354, 590052, 459013, 524378, 524314, 589972, 459029, 524410, 524346, 590036, 459021, 524394, 524330, 590004, 524298, 524426, 524362, 590068, 459011, 524374, 524310, 524574, 459027, 524406, 524342, 590028, 459019, 524390, 524326, 589996, 524294, 524422, 524358, 590060, 459015, 524382, 524318, 589980, 459031, 524414, 524350, 590044, 459023, 524398, 524334, 590012, 524302, 524430, 524366, 590076, 459008, 524369, 524305, 524569, 459024, 524401, 524337, 590018, 459016, 524385, 524321, 589986, 524289, 524417, 524353, 590050, 459012, 524377, 524313, 589970, 459028, 524409, 524345, 590034, 459020, 524393, 524329, 590002, 524297, 524425, 524361, 590066, 459010, 524373, 524309, 524573, 459026, 524405, 524341, 590026, 459018, 524389, 524325, 589994, 524293, 524421, 524357, 590058, 459014, 524381, 524317, 589978, 459030, 524413, 524349, 590042, 459022, 524397, 524333, 590010, 524301, 524429, 524365, 590074, 459009, 524371, 524307, 524571, 459025, 524403, 524339, 590022, 459017, 524387, 524323, 589990, 524291, 524419, 524355, 590054, 459013, 524379, 524315, 589974, 459029, 524411, 524347, 590038, 459021, 524395, 524331, 590006, 524299, 524427, 524363, 590070, 459011, 524375, 524311, 524575, 459027, 524407, 524343, 590030, 459019, 524391, 524327, 589998, 524295, 524423, 524359, 590062, 459015, 524383, 524319, 589982, 459031, 524415, 524351, 590046, 459023, 524399, 524335, 590014, 524303, 524431, 524367, 590078, 459008, 524368, 524304, 524568, 459024, 524400, 524336, 590017, 459016, 524384, 524320, 589985, 524288, 524416, 524352, 590049, 459012, 524376, 524312, 589969, 459028, 524408, 524344, 590033, 459020, 524392, 524328, 590001, 524296, 524424, 524360, 590065, 459010, 524372, 524308, 524572, 459026, 524404, 524340, 590025, 459018, 524388, 524324, 589993, 524292, 524420, 524356, 590057, 459014, 524380, 524316, 589977, 459030, 524412, 524348, 590041, 459022, 524396, 524332, 590009, 524300, 524428, 524364, 590073, 459009, 524370, 524306, 524570, 459025, 524402, 524338, 590021, 459017, 524386, 524322, 589989, 524290, 524418, 524354, 590053, 459013, 524378, 524314, 589973, 459029, 524410, 524346, 590037, 459021, 524394, 524330, 590005, 524298, 524426, 524362, 590069, 459011, 524374, 524310, 524574, 459027, 524406, 524342, 590029, 459019, 524390, 524326, 589997, 524294, 524422, 524358, 590061, 459015, 524382, 524318, 589981, 459031, 524414, 524350, 590045, 459023, 524398, 524334, 590013, 524302, 524430, 524366, 590077, 459008, 524369, 524305, 524569, 459024, 524401, 524337, 590019, 459016, 524385, 524321, 589987, 524289, 524417, 524353, 590051, 459012, 524377, 524313, 589971, 459028, 524409, 524345, 590035, 459020, 524393, 524329, 590003, 524297, 524425, 524361, 590067, 459010, 524373, 524309, 524573, 459026, 524405, 524341, 590027, 459018, 524389, 524325, 589995, 524293, 524421, 524357, 590059, 459014, 524381, 524317, 589979, 459030, 524413, 524349, 590043, 459022, 524397, 524333, 590011, 524301, 524429, 524365, 590075, 459009, 524371, 524307, 524571, 459025, 524403, 524339, 590023, 459017, 524387, 524323, 589991, 524291, 524419, 524355, 590055, 459013, 524379, 524315, 589975, 459029, 524411, 524347, 590039, 459021, 524395, 524331, 590007, 524299, 524427, 524363, 590071, 459011, 524375, 524311, 524575, 459027, 524407, 524343, 590031, 459019, 524391, 524327, 589999, 524295, 524423, 524359, 590063, 459015, 524383, 524319, 589983, 459031, 524415, 524351, 590047, 459023, 524399, 524335, 590015, 524303, 524431, 524367, 590079]), 9]; + fixedDistCodeTab = [new Int32Array([327680, 327696, 327688, 327704, 327684, 327700, 327692, 327708, 327682, 327698, 327690, 327706, 327686, 327702, 327694, 0, 327681, 327697, 327689, 327705, 327685, 327701, 327693, 327709, 327683, 327699, 327691, 327707, 327687, 327703, 327695, 0]), 5]; + FlateStream = class extends DecodeStream { + constructor(str, maybeLength) { + super(maybeLength); + this.str = str; + this.dict = str.dict; + const cmf = str.getByte(); + const flg = str.getByte(); + if (cmf === -1 || flg === -1) { + throw new FormatError3(`Invalid header in flate stream: ${cmf}, ${flg}`); + } + if ((cmf & 15) !== 8) { + throw new FormatError3(`Unknown compression method in flate stream: ${cmf}, ${flg}`); + } + if (((cmf << 8) + flg) % 31 !== 0) { + throw new FormatError3(`Bad FCHECK in flate stream: ${cmf}, ${flg}`); + } + if (flg & 32) { + throw new FormatError3(`FDICT bit set in flate stream: ${cmf}, ${flg}`); + } + this.codeSize = 0; + this.codeBuf = 0; + } + async getImageData(length, _decoderOptions) { + const data = await this.asyncGetBytes(); + if (!data) { + return this.getBytes(length); + } + if (data.length <= length) { + return data; + } + return data.subarray(0, length); + } + async asyncGetBytes() { + this.str.reset(); + const bytes = this.str.getBytes(); + try { + const { + readable, + writable + } = new DecompressionStream("deflate"); + const writer = writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => { + }); + const chunks = []; + let totalLength = 0; + for await (const chunk2 of readable) { + chunks.push(chunk2); + totalLength += chunk2.byteLength; + } + const data = new Uint8Array(totalLength); + let offset = 0; + for (const chunk2 of chunks) { + data.set(chunk2, offset); + offset += chunk2.byteLength; + } + return data; + } catch { + this.str = new Stream3(bytes, 2, bytes.length, this.str.dict); + this.reset(); + return null; + } + } + get isAsync() { + return true; + } + getBits(bits) { + const str = this.str; + let codeSize = this.codeSize; + let codeBuf = this.codeBuf; + let b2; + while (codeSize < bits) { + if ((b2 = str.getByte()) === -1) { + throw new FormatError3("Bad encoding in flate stream"); + } + codeBuf |= b2 << codeSize; + codeSize += 8; + } + b2 = codeBuf & (1 << bits) - 1; + this.codeBuf = codeBuf >> bits; + this.codeSize = codeSize -= bits; + return b2; + } + getCode(table2) { + const str = this.str; + const codes = table2[0]; + const maxLen = table2[1]; + let codeSize = this.codeSize; + let codeBuf = this.codeBuf; + let b2; + while (codeSize < maxLen) { + if ((b2 = str.getByte()) === -1) { + break; + } + codeBuf |= b2 << codeSize; + codeSize += 8; + } + const code = codes[codeBuf & (1 << maxLen) - 1]; + const codeLen = code >> 16; + const codeVal = code & 65535; + if (codeLen < 1 || codeSize < codeLen) { + throw new FormatError3("Bad encoding in flate stream"); + } + this.codeBuf = codeBuf >> codeLen; + this.codeSize = codeSize - codeLen; + return codeVal; + } + generateHuffmanTable(lengths) { + const n = lengths.length; + let maxLen = 0; + let i; + for (i = 0; i < n; ++i) { + if (lengths[i] > maxLen) { + maxLen = lengths[i]; + } + } + const size3 = 1 << maxLen; + const codes = new Int32Array(size3); + for (let len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) { + for (let val = 0; val < n; ++val) { + if (lengths[val] === len) { + let code2 = 0; + let t = code; + for (i = 0; i < len; ++i) { + code2 = code2 << 1 | t & 1; + t >>= 1; + } + for (i = code2; i < size3; i += skip) { + codes[i] = len << 16 | val; + } + ++code; + } + } + } + return [codes, maxLen]; + } + #endsStreamOnError(err) { + info2(err); + this.eof = true; + } + readBlock() { + let buffer2, hdr, len; + const str = this.str; + try { + hdr = this.getBits(3); + } catch (ex) { + this.#endsStreamOnError(ex.message); + return; + } + if (hdr & 1) { + this.eof = true; + } + hdr >>= 1; + if (hdr === 0) { + let b2; + if ((b2 = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + let blockLen = b2; + if ((b2 = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + blockLen |= b2 << 8; + if ((b2 = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + let check3 = b2; + if ((b2 = str.getByte()) === -1) { + this.#endsStreamOnError("Bad block header in flate stream"); + return; + } + check3 |= b2 << 8; + if (check3 !== (~blockLen & 65535) && (blockLen !== 0 || check3 !== 0)) { + throw new FormatError3("Bad uncompressed block length in flate stream"); + } + this.codeBuf = 0; + this.codeSize = 0; + const bufferLength = this.bufferLength, end = bufferLength + blockLen; + buffer2 = this.ensureBuffer(end); + this.bufferLength = end; + if (blockLen === 0) { + if (str.peekByte() === -1) { + this.eof = true; + } + } else { + const block = str.getBytes(blockLen); + buffer2.set(block, bufferLength); + if (block.length < blockLen) { + this.eof = true; + } + } + return; + } + let litCodeTable; + let distCodeTable; + if (hdr === 1) { + litCodeTable = fixedLitCodeTab; + distCodeTable = fixedDistCodeTab; + } else if (hdr === 2) { + const numLitCodes = this.getBits(5) + 257; + const numDistCodes = this.getBits(5) + 1; + const numCodeLenCodes = this.getBits(4) + 4; + const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length); + let i; + for (i = 0; i < numCodeLenCodes; ++i) { + codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3); + } + const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths); + len = 0; + i = 0; + const codes = numLitCodes + numDistCodes; + const codeLengths = new Uint8Array(codes); + let bitsLength, bitsOffset, what; + while (i < codes) { + const code = this.getCode(codeLenCodeTab); + if (code === 16) { + bitsLength = 2; + bitsOffset = 3; + what = len; + } else if (code === 17) { + bitsLength = 3; + bitsOffset = 3; + what = len = 0; + } else if (code === 18) { + bitsLength = 7; + bitsOffset = 11; + what = len = 0; + } else { + codeLengths[i++] = len = code; + continue; + } + let repeatLength = this.getBits(bitsLength) + bitsOffset; + while (repeatLength-- > 0) { + codeLengths[i++] = what; + } + } + litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes)); + distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes)); + } else { + throw new FormatError3("Unknown block type in flate stream"); + } + buffer2 = this.buffer; + let limit = buffer2 ? buffer2.length : 0; + let pos = this.bufferLength; + while (true) { + let code1 = this.getCode(litCodeTable); + if (code1 < 256) { + if (pos + 1 >= limit) { + buffer2 = this.ensureBuffer(pos + 1); + limit = buffer2.length; + } + buffer2[pos++] = code1; + continue; + } + if (code1 === 256) { + this.bufferLength = pos; + return; + } + code1 -= 257; + code1 = lengthDecode[code1]; + let code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + len = (code1 & 65535) + code2; + code1 = this.getCode(distCodeTable); + code1 = distDecode[code1]; + code2 = code1 >> 16; + if (code2 > 0) { + code2 = this.getBits(code2); + } + const dist = (code1 & 65535) + code2; + if (pos + len >= limit) { + buffer2 = this.ensureBuffer(pos + len); + limit = buffer2.length; + } + for (let k = 0; k < len; ++k, ++pos) { + buffer2[pos] = buffer2[pos - dist]; + } + } + } + }; + QeTable = [{ + qe: 22017, + nmps: 1, + nlps: 1, + switchFlag: 1 + }, { + qe: 13313, + nmps: 2, + nlps: 6, + switchFlag: 0 + }, { + qe: 6145, + nmps: 3, + nlps: 9, + switchFlag: 0 + }, { + qe: 2753, + nmps: 4, + nlps: 12, + switchFlag: 0 + }, { + qe: 1313, + nmps: 5, + nlps: 29, + switchFlag: 0 + }, { + qe: 545, + nmps: 38, + nlps: 33, + switchFlag: 0 + }, { + qe: 22017, + nmps: 7, + nlps: 6, + switchFlag: 1 + }, { + qe: 21505, + nmps: 8, + nlps: 14, + switchFlag: 0 + }, { + qe: 18433, + nmps: 9, + nlps: 14, + switchFlag: 0 + }, { + qe: 14337, + nmps: 10, + nlps: 14, + switchFlag: 0 + }, { + qe: 12289, + nmps: 11, + nlps: 17, + switchFlag: 0 + }, { + qe: 9217, + nmps: 12, + nlps: 18, + switchFlag: 0 + }, { + qe: 7169, + nmps: 13, + nlps: 20, + switchFlag: 0 + }, { + qe: 5633, + nmps: 29, + nlps: 21, + switchFlag: 0 + }, { + qe: 22017, + nmps: 15, + nlps: 14, + switchFlag: 1 + }, { + qe: 21505, + nmps: 16, + nlps: 14, + switchFlag: 0 + }, { + qe: 20737, + nmps: 17, + nlps: 15, + switchFlag: 0 + }, { + qe: 18433, + nmps: 18, + nlps: 16, + switchFlag: 0 + }, { + qe: 14337, + nmps: 19, + nlps: 17, + switchFlag: 0 + }, { + qe: 13313, + nmps: 20, + nlps: 18, + switchFlag: 0 + }, { + qe: 12289, + nmps: 21, + nlps: 19, + switchFlag: 0 + }, { + qe: 10241, + nmps: 22, + nlps: 19, + switchFlag: 0 + }, { + qe: 9217, + nmps: 23, + nlps: 20, + switchFlag: 0 + }, { + qe: 8705, + nmps: 24, + nlps: 21, + switchFlag: 0 + }, { + qe: 7169, + nmps: 25, + nlps: 22, + switchFlag: 0 + }, { + qe: 6145, + nmps: 26, + nlps: 23, + switchFlag: 0 + }, { + qe: 5633, + nmps: 27, + nlps: 24, + switchFlag: 0 + }, { + qe: 5121, + nmps: 28, + nlps: 25, + switchFlag: 0 + }, { + qe: 4609, + nmps: 29, + nlps: 26, + switchFlag: 0 + }, { + qe: 4353, + nmps: 30, + nlps: 27, + switchFlag: 0 + }, { + qe: 2753, + nmps: 31, + nlps: 28, + switchFlag: 0 + }, { + qe: 2497, + nmps: 32, + nlps: 29, + switchFlag: 0 + }, { + qe: 2209, + nmps: 33, + nlps: 30, + switchFlag: 0 + }, { + qe: 1313, + nmps: 34, + nlps: 31, + switchFlag: 0 + }, { + qe: 1089, + nmps: 35, + nlps: 32, + switchFlag: 0 + }, { + qe: 673, + nmps: 36, + nlps: 33, + switchFlag: 0 + }, { + qe: 545, + nmps: 37, + nlps: 34, + switchFlag: 0 + }, { + qe: 321, + nmps: 38, + nlps: 35, + switchFlag: 0 + }, { + qe: 273, + nmps: 39, + nlps: 36, + switchFlag: 0 + }, { + qe: 133, + nmps: 40, + nlps: 37, + switchFlag: 0 + }, { + qe: 73, + nmps: 41, + nlps: 38, + switchFlag: 0 + }, { + qe: 37, + nmps: 42, + nlps: 39, + switchFlag: 0 + }, { + qe: 21, + nmps: 43, + nlps: 40, + switchFlag: 0 + }, { + qe: 9, + nmps: 44, + nlps: 41, + switchFlag: 0 + }, { + qe: 5, + nmps: 45, + nlps: 42, + switchFlag: 0 + }, { + qe: 1, + nmps: 45, + nlps: 43, + switchFlag: 0 + }, { + qe: 22017, + nmps: 46, + nlps: 46, + switchFlag: 0 + }]; + ArithmeticDecoder = class { + constructor(data, start, end) { + this.data = data; + this.bp = start; + this.dataEnd = end; + this.chigh = data[start]; + this.clow = 0; + this.byteIn(); + this.chigh = this.chigh << 7 & 65535 | this.clow >> 9 & 127; + this.clow = this.clow << 7 & 65535; + this.ct -= 7; + this.a = 32768; + } + byteIn() { + const data = this.data; + let bp = this.bp; + if (data[bp] === 255) { + if (data[bp + 1] > 143) { + this.clow += 65280; + this.ct = 8; + } else { + bp++; + this.clow += data[bp] << 9; + this.ct = 7; + this.bp = bp; + } + } else { + bp++; + this.clow += bp < this.dataEnd ? data[bp] << 8 : 65280; + this.ct = 8; + this.bp = bp; + } + if (this.clow > 65535) { + this.chigh += this.clow >> 16; + this.clow &= 65535; + } + } + readBit(contexts, pos) { + let cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1; + const qeTableIcx = QeTable[cx_index]; + const qeIcx = qeTableIcx.qe; + let d; + let a = this.a - qeIcx; + if (this.chigh < qeIcx) { + if (a < qeIcx) { + a = qeIcx; + d = cx_mps; + cx_index = qeTableIcx.nmps; + } else { + a = qeIcx; + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } + } else { + this.chigh -= qeIcx; + if ((a & 32768) !== 0) { + this.a = a; + return cx_mps; + } + if (a < qeIcx) { + d = 1 ^ cx_mps; + if (qeTableIcx.switchFlag === 1) { + cx_mps = d; + } + cx_index = qeTableIcx.nlps; + } else { + d = cx_mps; + cx_index = qeTableIcx.nmps; + } + } + do { + if (this.ct === 0) { + this.byteIn(); + } + a <<= 1; + this.chigh = this.chigh << 1 & 65535 | this.clow >> 15 & 1; + this.clow = this.clow << 1 & 65535; + this.ct--; + } while ((a & 32768) === 0); + this.a = a; + contexts[pos] = cx_index << 1 | cx_mps; + return d; + } + }; + Jbig2Error = class extends BaseException2 { + constructor(msg) { + super(msg, "Jbig2Error"); + } + }; + ContextCache = class { + getContexts(id) { + if (id in this) { + return this[id]; + } + return this[id] = new Int8Array(1 << 16); + } + }; + DecodingContext = class { + constructor(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + } + get decoder() { + const decoder2 = new ArithmeticDecoder(this.data, this.start, this.end); + return shadow2(this, "decoder", decoder2); + } + get contextCache() { + const cache2 = new ContextCache(); + return shadow2(this, "contextCache", cache2); + } + }; + SegmentTypes = ["SymbolDictionary", null, null, null, "IntermediateTextRegion", null, "ImmediateTextRegion", "ImmediateLosslessTextRegion", null, null, null, null, null, null, null, null, "PatternDictionary", null, null, null, "IntermediateHalftoneRegion", null, "ImmediateHalftoneRegion", "ImmediateLosslessHalftoneRegion", null, null, null, null, null, null, null, null, null, null, null, null, "IntermediateGenericRegion", null, "ImmediateGenericRegion", "ImmediateLosslessGenericRegion", "IntermediateGenericRefinementRegion", null, "ImmediateGenericRefinementRegion", "ImmediateLosslessGenericRefinementRegion", null, null, null, null, "PageInformation", "EndOfPage", "EndOfStripe", "EndOfFile", "Profiles", "Tables", null, null, null, null, null, null, null, null, "Extension"]; + CodingTemplates = [[{ + x: -1, + y: -2 + }, { + x: 0, + y: -2 + }, { + x: 1, + y: -2 + }, { + x: -2, + y: -1 + }, { + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: 2, + y: -1 + }, { + x: -4, + y: 0 + }, { + x: -3, + y: 0 + }, { + x: -2, + y: 0 + }, { + x: -1, + y: 0 + }], [{ + x: -1, + y: -2 + }, { + x: 0, + y: -2 + }, { + x: 1, + y: -2 + }, { + x: 2, + y: -2 + }, { + x: -2, + y: -1 + }, { + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: 2, + y: -1 + }, { + x: -3, + y: 0 + }, { + x: -2, + y: 0 + }, { + x: -1, + y: 0 + }], [{ + x: -1, + y: -2 + }, { + x: 0, + y: -2 + }, { + x: 1, + y: -2 + }, { + x: -2, + y: -1 + }, { + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -2, + y: 0 + }, { + x: -1, + y: 0 + }], [{ + x: -3, + y: -1 + }, { + x: -2, + y: -1 + }, { + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -4, + y: 0 + }, { + x: -3, + y: 0 + }, { + x: -2, + y: 0 + }, { + x: -1, + y: 0 + }]]; + RefinementTemplates = [{ + coding: [{ + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }], + reference: [{ + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }, { + x: 0, + y: 0 + }, { + x: 1, + y: 0 + }, { + x: -1, + y: 1 + }, { + x: 0, + y: 1 + }, { + x: 1, + y: 1 + }] + }, { + coding: [{ + x: -1, + y: -1 + }, { + x: 0, + y: -1 + }, { + x: 1, + y: -1 + }, { + x: -1, + y: 0 + }], + reference: [{ + x: 0, + y: -1 + }, { + x: -1, + y: 0 + }, { + x: 0, + y: 0 + }, { + x: 1, + y: 0 + }, { + x: 0, + y: 1 + }, { + x: 1, + y: 1 + }] + }]; + ReusedContexts = [39717, 1941, 229, 405]; + RefinementReusedContexts = [32, 8]; + RegionSegmentInformationFieldLength = 17; + SimpleSegmentVisitor = class { + onPageInformation(info3) { + this.currentPageInfo = info3; + const rowSize = info3.width + 7 >> 3; + const buffer2 = new Uint8ClampedArray(rowSize * info3.height); + if (info3.defaultPixelValue) { + buffer2.fill(255); + } + this.buffer = buffer2; + } + drawBitmap(regionInfo, bitmap) { + const pageInfo = this.currentPageInfo; + const width = regionInfo.width, height = regionInfo.height; + const rowSize = pageInfo.width + 7 >> 3; + const combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator; + const buffer2 = this.buffer; + const mask0 = 128 >> (regionInfo.x & 7); + let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3); + let i, j, mask, offset; + switch (combinationOperator) { + case 0: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer2[offset] |= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + case 2: + for (i = 0; i < height; i++) { + mask = mask0; + offset = offset0; + for (j = 0; j < width; j++) { + if (bitmap[i][j]) { + buffer2[offset] ^= mask; + } + mask >>= 1; + if (!mask) { + mask = 128; + offset++; + } + } + offset0 += rowSize; + } + break; + default: + throw new Jbig2Error(`operator ${combinationOperator} is not supported`); + } + } + onImmediateGenericRegion(region, data, start, end) { + const regionInfo = region.info; + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessGenericRegion() { + this.onImmediateGenericRegion(...arguments); + } + onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) { + let huffmanTables, huffmanInput; + if (dictionary.huffman) { + huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables); + huffmanInput = new Reader(data, start, end); + } + let symbols = this.symbols; + if (!symbols) { + this.symbols = symbols = {}; + } + const inputSymbols = []; + for (const referredSegment of referredSegments) { + const referredSymbols = symbols[referredSegment]; + if (referredSymbols) { + inputSymbols.push(...referredSymbols); + } + } + const decodingContext = new DecodingContext(data, start, end); + symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput); + } + onImmediateTextRegion(region, referredSegments, data, start, end) { + const regionInfo = region.info; + let huffmanTables, huffmanInput; + const symbols = this.symbols; + const inputSymbols = []; + for (const referredSegment of referredSegments) { + const referredSymbols = symbols[referredSegment]; + if (referredSymbols) { + inputSymbols.push(...referredSymbols); + } + } + const symbolCodeLength = log2(inputSymbols.length); + if (region.huffman) { + huffmanInput = new Reader(data, start, end); + huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput); + } + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessTextRegion() { + this.onImmediateTextRegion(...arguments); + } + onPatternDictionary(dictionary, currentSegment, data, start, end) { + let patterns = this.patterns; + if (!patterns) { + this.patterns = patterns = {}; + } + const decodingContext = new DecodingContext(data, start, end); + patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext); + } + onImmediateHalftoneRegion(region, referredSegments, data, start, end) { + const patterns = this.patterns[referredSegments[0]]; + const regionInfo = region.info; + const decodingContext = new DecodingContext(data, start, end); + const bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext); + this.drawBitmap(regionInfo, bitmap); + } + onImmediateLosslessHalftoneRegion() { + this.onImmediateHalftoneRegion(...arguments); + } + onTables(currentSegment, data, start, end) { + let customTables = this.customTables; + if (!customTables) { + this.customTables = customTables = {}; + } + customTables[currentSegment] = decodeTablesSegment(data, start, end); + } + }; + HuffmanLine = class { + constructor(lineData) { + if (lineData.length === 2) { + this.isOOB = true; + this.rangeLow = 0; + this.prefixLength = lineData[0]; + this.rangeLength = 0; + this.prefixCode = lineData[1]; + this.isLowerRange = false; + } else { + this.isOOB = false; + this.rangeLow = lineData[0]; + this.prefixLength = lineData[1]; + this.rangeLength = lineData[2]; + this.prefixCode = lineData[3]; + this.isLowerRange = lineData[4] === "lower"; + } + } + }; + HuffmanTreeNode = class _HuffmanTreeNode { + constructor(line2) { + this.children = []; + if (line2) { + this.isLeaf = true; + this.rangeLength = line2.rangeLength; + this.rangeLow = line2.rangeLow; + this.isLowerRange = line2.isLowerRange; + this.isOOB = line2.isOOB; + } else { + this.isLeaf = false; + } + } + buildTree(line2, shift) { + const bit2 = line2.prefixCode >> shift & 1; + if (shift <= 0) { + this.children[bit2] = new _HuffmanTreeNode(line2); + } else { + let node2 = this.children[bit2]; + if (!node2) { + this.children[bit2] = node2 = new _HuffmanTreeNode(null); + } + node2.buildTree(line2, shift - 1); + } + } + decodeNode(reader) { + if (this.isLeaf) { + if (this.isOOB) { + return null; + } + const htOffset = reader.readBits(this.rangeLength); + return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset); + } + const node2 = this.children[reader.readBit()]; + if (!node2) { + throw new Jbig2Error("invalid Huffman data"); + } + return node2.decodeNode(reader); + } + }; + HuffmanTable = class { + constructor(lines, prefixCodesDone) { + if (!prefixCodesDone) { + this.assignPrefixCodes(lines); + } + this.rootNode = new HuffmanTreeNode(null); + for (let i = 0, ii = lines.length; i < ii; i++) { + const line2 = lines[i]; + if (line2.prefixLength > 0) { + this.rootNode.buildTree(line2, line2.prefixLength - 1); + } + } + } + decode(reader) { + return this.rootNode.decodeNode(reader); + } + assignPrefixCodes(lines) { + const linesLength = lines.length; + let prefixLengthMax = 0; + for (let i = 0; i < linesLength; i++) { + prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength); + } + const histogram = new Uint32Array(prefixLengthMax + 1); + for (let i = 0; i < linesLength; i++) { + histogram[lines[i].prefixLength]++; + } + let currentLength = 1, firstCode = 0, currentCode, currentTemp, line2; + histogram[0] = 0; + while (currentLength <= prefixLengthMax) { + firstCode = firstCode + histogram[currentLength - 1] << 1; + currentCode = firstCode; + currentTemp = 0; + while (currentTemp < linesLength) { + line2 = lines[currentTemp]; + if (line2.prefixLength === currentLength) { + line2.prefixCode = currentCode; + currentCode++; + } + currentTemp++; + } + currentLength++; + } + } + }; + standardTablesCache = {}; + Reader = class { + constructor(data, start, end) { + this.data = data; + this.start = start; + this.end = end; + this.position = start; + this.shift = -1; + this.currentByte = 0; + } + readBit() { + if (this.shift < 0) { + if (this.position >= this.end) { + throw new Jbig2Error("end of data while reading bit"); + } + this.currentByte = this.data[this.position++]; + this.shift = 7; + } + const bit2 = this.currentByte >> this.shift & 1; + this.shift--; + return bit2; + } + readBits(numBits) { + let result2 = 0, i; + for (i = numBits - 1; i >= 0; i--) { + result2 |= this.readBit() << i; + } + return result2; + } + byteAlign() { + this.shift = -1; + } + next() { + if (this.position >= this.end) { + return -1; + } + return this.data[this.position++]; + } + }; + Jbig2Image = class { + parseChunks(chunks) { + return parseJbig2Chunks(chunks); + } + parse(data) { + throw new Error("Not implemented: Jbig2Image.parse"); + } + }; + Jbig2Stream = class extends DecodeStream { + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + get bytes() { + return shadow2(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) { + } + readBlock() { + this.decodeImage(); + } + decodeImage(bytes) { + if (this.eof) { + return this.buffer; + } + bytes ||= this.bytes; + const jbig2Image = new Jbig2Image(); + const chunks = []; + if (this.params instanceof Dict) { + const globalsStream = this.params.get("JBIG2Globals"); + if (globalsStream instanceof BaseStream) { + const globals = globalsStream.getBytes(); + chunks.push({ + data: globals, + start: 0, + end: globals.length + }); + } + } + chunks.push({ + data: bytes, + start: 0, + end: bytes.length + }); + const data = jbig2Image.parseChunks(chunks); + const dataLength = data.length; + for (let i = 0; i < dataLength; i++) { + data[i] ^= 255; + } + this.buffer = data; + this.bufferLength = dataLength; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } + }; + JpxStream = class extends DecodeStream { + constructor(stream, maybeLength, params) { + super(maybeLength); + this.stream = stream; + this.dict = stream.dict; + this.maybeLength = maybeLength; + this.params = params; + } + get bytes() { + return shadow2(this, "bytes", this.stream.getBytes(this.maybeLength)); + } + ensureBuffer(requested) { + } + readBlock(decoderOptions) { + unreachable2("JpxStream.readBlock"); + } + get isAsyncDecoder() { + return true; + } + async decodeImage(bytes, decoderOptions) { + if (this.eof) { + return this.buffer; + } + bytes ||= this.bytes; + this.buffer = await JpxImage.decode(bytes, decoderOptions); + this.bufferLength = this.buffer.length; + this.eof = true; + return this.buffer; + } + get canAsyncDecodeImageFromBuffer() { + return this.stream.isAsync; + } + }; + LZWStream = class extends DecodeStream { + constructor(str, maybeLength, earlyChange) { + super(maybeLength); + this.str = str; + this.dict = str.dict; + this.cachedData = 0; + this.bitsCached = 0; + const maxLzwDictionarySize = 4096; + const lzwState = { + earlyChange, + codeLength: 9, + nextCode: 258, + dictionaryValues: new Uint8Array(maxLzwDictionarySize), + dictionaryLengths: new Uint16Array(maxLzwDictionarySize), + dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize), + currentSequence: new Uint8Array(maxLzwDictionarySize), + currentSequenceLength: 0 + }; + for (let i = 0; i < 256; ++i) { + lzwState.dictionaryValues[i] = i; + lzwState.dictionaryLengths[i] = 1; + } + this.lzwState = lzwState; + } + readBits(n) { + let bitsCached = this.bitsCached; + let cachedData = this.cachedData; + while (bitsCached < n) { + const c = this.str.getByte(); + if (c === -1) { + this.eof = true; + return null; + } + cachedData = cachedData << 8 | c; + bitsCached += 8; + } + this.bitsCached = bitsCached -= n; + this.cachedData = cachedData; + this.lastCode = null; + return cachedData >>> bitsCached & (1 << n) - 1; + } + readBlock() { + const blockSize = 512, decodedSizeDelta = blockSize; + let estimatedDecodedSize = blockSize * 2; + let i, j, q; + const lzwState = this.lzwState; + if (!lzwState) { + return; + } + const earlyChange = lzwState.earlyChange; + let nextCode = lzwState.nextCode; + const dictionaryValues = lzwState.dictionaryValues; + const dictionaryLengths = lzwState.dictionaryLengths; + const dictionaryPrevCodes = lzwState.dictionaryPrevCodes; + let codeLength = lzwState.codeLength; + let prevCode = lzwState.prevCode; + const currentSequence = lzwState.currentSequence; + let currentSequenceLength = lzwState.currentSequenceLength; + let decodedLength = 0; + let currentBufferLength = this.bufferLength; + let buffer2 = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + for (i = 0; i < blockSize; i++) { + const code = this.readBits(codeLength); + const hasPrev = currentSequenceLength > 0; + if (code < 256) { + currentSequence[0] = code; + currentSequenceLength = 1; + } else if (code >= 258) { + if (code < nextCode) { + currentSequenceLength = dictionaryLengths[code]; + for (j = currentSequenceLength - 1, q = code; j >= 0; j--) { + currentSequence[j] = dictionaryValues[q]; + q = dictionaryPrevCodes[q]; + } + } else { + currentSequence[currentSequenceLength++] = currentSequence[0]; + } + } else if (code === 256) { + codeLength = 9; + nextCode = 258; + currentSequenceLength = 0; + continue; + } else { + this.eof = true; + delete this.lzwState; + break; + } + if (hasPrev) { + dictionaryPrevCodes[nextCode] = prevCode; + dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1; + dictionaryValues[nextCode] = currentSequence[0]; + nextCode++; + codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0; + } + prevCode = code; + decodedLength += currentSequenceLength; + if (estimatedDecodedSize < decodedLength) { + do { + estimatedDecodedSize += decodedSizeDelta; + } while (estimatedDecodedSize < decodedLength); + buffer2 = this.ensureBuffer(this.bufferLength + estimatedDecodedSize); + } + for (j = 0; j < currentSequenceLength; j++) { + buffer2[currentBufferLength++] = currentSequence[j]; + } + } + lzwState.nextCode = nextCode; + lzwState.codeLength = codeLength; + lzwState.prevCode = prevCode; + lzwState.currentSequenceLength = currentSequenceLength; + this.bufferLength = currentBufferLength; + } + }; + PredictorStream = class extends DecodeStream { + constructor(str, maybeLength, params) { + super(maybeLength); + if (!(params instanceof Dict)) { + return str; + } + const predictor = this.predictor = params.get("Predictor") || 1; + if (predictor <= 1) { + return str; + } + if (predictor !== 2 && (predictor < 10 || predictor > 15)) { + throw new FormatError3(`Unsupported predictor: ${predictor}`); + } + this.readBlock = predictor === 2 ? this.readBlockTiff : this.readBlockPng; + this.str = str; + this.dict = str.dict; + const colors = this.colors = params.get("Colors") || 1; + const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8; + const columns = this.columns = params.get("Columns") || 1; + this.pixBytes = colors * bits + 7 >> 3; + this.rowBytes = columns * colors * bits + 7 >> 3; + return this; + } + readBlockTiff() { + const rowBytes = this.rowBytes; + const bufferLength = this.bufferLength; + const buffer2 = this.ensureBuffer(bufferLength + rowBytes); + const bits = this.bits; + const colors = this.colors; + const rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + let inbuf = 0, outbuf = 0; + let inbits = 0, outbits = 0; + let pos = bufferLength; + let i; + if (bits === 1 && colors === 1) { + for (i = 0; i < rowBytes; ++i) { + let c = rawBytes[i] ^ inbuf; + c ^= c >> 1; + c ^= c >> 2; + c ^= c >> 4; + inbuf = (c & 1) << 7; + buffer2[pos++] = c; + } + } else if (bits === 8) { + for (i = 0; i < colors; ++i) { + buffer2[pos++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer2[pos] = buffer2[pos - colors] + rawBytes[i]; + pos++; + } + } else if (bits === 16) { + const bytesPerPixel = colors * 2; + for (i = 0; i < bytesPerPixel; ++i) { + buffer2[pos++] = rawBytes[i]; + } + for (; i < rowBytes; i += 2) { + const sum = ((rawBytes[i] & 255) << 8) + (rawBytes[i + 1] & 255) + ((buffer2[pos - bytesPerPixel] & 255) << 8) + (buffer2[pos - bytesPerPixel + 1] & 255); + buffer2[pos++] = sum >> 8 & 255; + buffer2[pos++] = sum & 255; + } + } else { + const compArray = new Uint8Array(colors + 1); + const bitMask = (1 << bits) - 1; + let j = 0, k = bufferLength; + const columns = this.columns; + for (i = 0; i < columns; ++i) { + for (let kk = 0; kk < colors; ++kk) { + if (inbits < bits) { + inbuf = inbuf << 8 | rawBytes[j++] & 255; + inbits += 8; + } + compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask; + inbits -= bits; + outbuf = outbuf << bits | compArray[kk]; + outbits += bits; + if (outbits >= 8) { + buffer2[k++] = outbuf >> outbits - 8 & 255; + outbits -= 8; + } + } + } + if (outbits > 0) { + buffer2[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1); + } + } + this.bufferLength += rowBytes; + } + readBlockPng() { + const rowBytes = this.rowBytes; + const pixBytes = this.pixBytes; + const predictor = this.str.getByte(); + const rawBytes = this.str.getBytes(rowBytes); + this.eof = !rawBytes.length; + if (this.eof) { + return; + } + const bufferLength = this.bufferLength; + const buffer2 = this.ensureBuffer(bufferLength + rowBytes); + let prevRow = buffer2.subarray(bufferLength - rowBytes, bufferLength); + if (prevRow.length === 0) { + prevRow = new Uint8Array(rowBytes); + } + let i, j = bufferLength, up, c; + switch (predictor) { + case 0: + for (i = 0; i < rowBytes; ++i) { + buffer2[j++] = rawBytes[i]; + } + break; + case 1: + for (i = 0; i < pixBytes; ++i) { + buffer2[j++] = rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer2[j] = buffer2[j - pixBytes] + rawBytes[i] & 255; + j++; + } + break; + case 2: + for (i = 0; i < rowBytes; ++i) { + buffer2[j++] = prevRow[i] + rawBytes[i] & 255; + } + break; + case 3: + for (i = 0; i < pixBytes; ++i) { + buffer2[j++] = (prevRow[i] >> 1) + rawBytes[i]; + } + for (; i < rowBytes; ++i) { + buffer2[j] = (prevRow[i] + buffer2[j - pixBytes] >> 1) + rawBytes[i] & 255; + j++; + } + break; + case 4: + for (i = 0; i < pixBytes; ++i) { + up = prevRow[i]; + c = rawBytes[i]; + buffer2[j++] = up + c; + } + for (; i < rowBytes; ++i) { + up = prevRow[i]; + const upLeft = prevRow[i - pixBytes]; + const left = buffer2[j - pixBytes]; + const p = left + up - upLeft; + let pa = p - left; + if (pa < 0) { + pa = -pa; + } + let pb = p - up; + if (pb < 0) { + pb = -pb; + } + let pc = p - upLeft; + if (pc < 0) { + pc = -pc; + } + c = rawBytes[i]; + if (pa <= pb && pa <= pc) { + buffer2[j++] = left + c; + } else if (pb <= pc) { + buffer2[j++] = up + c; + } else { + buffer2[j++] = upLeft + c; + } + } + break; + default: + throw new FormatError3(`Unsupported predictor: ${predictor}`); + } + this.bufferLength += rowBytes; + } + }; + RunLengthStream = class extends DecodeStream { + constructor(str, maybeLength) { + super(maybeLength); + this.str = str; + this.dict = str.dict; + } + readBlock() { + const repeatHeader = this.str.getBytes(2); + if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) { + this.eof = true; + return; + } + let buffer2; + let bufferLength = this.bufferLength; + let n = repeatHeader[0]; + if (n < 128) { + buffer2 = this.ensureBuffer(bufferLength + n + 1); + buffer2[bufferLength++] = repeatHeader[1]; + if (n > 0) { + const source = this.str.getBytes(n); + buffer2.set(source, bufferLength); + bufferLength += n; + } + } else { + n = 257 - n; + buffer2 = this.ensureBuffer(bufferLength + n + 1); + buffer2.fill(repeatHeader[1], bufferLength, bufferLength + n); + bufferLength += n; + } + this.bufferLength = bufferLength; + } + }; + MAX_LENGTH_TO_CACHE = 1e3; + Parser = class { + constructor({ + lexer, + xref, + allowStreams = false, + recoveryMode = false + }) { + this.lexer = lexer; + this.xref = xref; + this.allowStreams = allowStreams; + this.recoveryMode = recoveryMode; + this.imageCache = /* @__PURE__ */ Object.create(null); + this._imageId = 0; + this.refill(); + } + refill() { + this.buf1 = this.lexer.getObj(); + this.buf2 = this.lexer.getObj(); + } + shift() { + if (this.buf2 instanceof Cmd && this.buf2.cmd === "ID") { + this.buf1 = this.buf2; + this.buf2 = null; + } else { + this.buf1 = this.buf2; + this.buf2 = this.lexer.getObj(); + } + } + tryShift() { + try { + this.shift(); + return true; + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + return false; + } + } + getObj(cipherTransform = null) { + const buf1 = this.buf1; + this.shift(); + if (buf1 instanceof Cmd) { + switch (buf1.cmd) { + case "BI": + return this.makeInlineImage(cipherTransform); + case "[": + const array2 = []; + while (!isCmd(this.buf1, "]") && this.buf1 !== EOF) { + array2.push(this.getObj(cipherTransform)); + } + if (this.buf1 === EOF) { + if (this.recoveryMode) { + return array2; + } + throw new ParserEOFException("End of file inside array."); + } + this.shift(); + return array2; + case "<<": + const dict = new Dict(this.xref); + while (!isCmd(this.buf1, ">>") && this.buf1 !== EOF) { + if (!(this.buf1 instanceof Name2)) { + info2("Malformed dictionary: key must be a name object"); + this.shift(); + continue; + } + const key = this.buf1.name; + this.shift(); + if (this.buf1 === EOF) { + break; + } + dict.set(key, this.getObj(cipherTransform)); + } + if (this.buf1 === EOF) { + if (this.recoveryMode) { + return dict; + } + throw new ParserEOFException("End of file inside dictionary."); + } + if (isCmd(this.buf2, "stream")) { + return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict; + } + this.shift(); + return dict; + default: + return buf1; + } + } + if (Number.isInteger(buf1)) { + if (Number.isInteger(this.buf1) && isCmd(this.buf2, "R")) { + const ref = Ref.get(buf1, this.buf1); + this.shift(); + this.shift(); + return ref; + } + return buf1; + } + if (typeof buf1 === "string") { + if (cipherTransform) { + return cipherTransform.decryptString(buf1); + } + return buf1; + } + return buf1; + } + findDefaultInlineStreamEnd(stream) { + const E = 69, I2 = 73, SPACE = 32, LF = 10, CR = 13, NUL = 0; + const { + knownCommands + } = this.lexer, startPos = stream.pos, n = 15; + let state = 0, ch2, maybeEIPos; + while ((ch2 = stream.getByte()) !== -1) { + if (state === 0) { + state = ch2 === E ? 1 : 0; + } else if (state === 1) { + state = ch2 === I2 ? 2 : 0; + } else { + if (ch2 === SPACE || ch2 === LF || ch2 === CR) { + maybeEIPos = stream.pos; + const followingBytes = stream.peekBytes(n); + const ii = followingBytes.length; + if (ii === 0) { + break; + } + for (let i = 0; i < ii; i++) { + ch2 = followingBytes[i]; + if (ch2 === NUL && followingBytes[i + 1] !== NUL) { + continue; + } + if (ch2 !== LF && ch2 !== CR && (ch2 < SPACE || ch2 > 127)) { + state = 0; + break; + } + } + if (state !== 2) { + continue; + } + if (!knownCommands) { + warn2("findDefaultInlineStreamEnd - `lexer.knownCommands` is undefined."); + continue; + } + const tmpLexer = new Lexer(new Stream3(stream.peekBytes(5 * n)), knownCommands); + tmpLexer._hexStringWarn = () => { + }; + let numArgs = 0; + while (true) { + const nextObj = tmpLexer.getObj(); + if (nextObj === EOF) { + state = 0; + break; + } + if (nextObj instanceof Cmd) { + const knownCommand = knownCommands[nextObj.cmd]; + if (!knownCommand) { + state = 0; + break; + } else if (knownCommand.variableArgs ? numArgs <= knownCommand.numArgs : numArgs === knownCommand.numArgs) { + break; + } + numArgs = 0; + continue; + } + numArgs++; + } + if (state === 2) { + break; + } + } else { + state = 0; + } + } + } + if (ch2 === -1) { + warn2("findDefaultInlineStreamEnd: Reached the end of the stream without finding a valid EI marker"); + if (maybeEIPos) { + warn2('... trying to recover by using the last "EI" occurrence.'); + stream.skip(-(stream.pos - maybeEIPos)); + } + } + let endOffset = 4; + stream.skip(-endOffset); + ch2 = stream.peekByte(); + stream.skip(endOffset); + if (!isWhiteSpace(ch2)) { + endOffset--; + } + return stream.pos - endOffset - startPos; + } + findDCTDecodeInlineStreamEnd(stream) { + const startPos = stream.pos; + let foundEOI = false, b2, markerLength; + while ((b2 = stream.getByte()) !== -1) { + if (b2 !== 255) { + continue; + } + switch (stream.getByte()) { + case 0: + break; + case 255: + stream.skip(-1); + break; + case 217: + foundEOI = true; + break; + case 192: + case 193: + case 194: + case 195: + case 197: + case 198: + case 199: + case 201: + case 202: + case 203: + case 205: + case 206: + case 207: + case 196: + case 204: + case 218: + case 219: + case 220: + case 221: + case 222: + case 223: + case 224: + case 225: + case 226: + case 227: + case 228: + case 229: + case 230: + case 231: + case 232: + case 233: + case 234: + case 235: + case 236: + case 237: + case 238: + case 239: + case 254: + markerLength = stream.getUint16(); + if (markerLength > 2) { + stream.skip(markerLength - 2); + } else { + stream.skip(-2); + } + break; + } + if (foundEOI) { + break; + } + } + const length = stream.pos - startPos; + if (b2 === -1) { + warn2("Inline DCTDecode image stream: EOI marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + findASCII85DecodeInlineStreamEnd(stream) { + const TILDE = 126, GT = 62; + const startPos = stream.pos; + let ch2; + while ((ch2 = stream.getByte()) !== -1) { + if (ch2 === TILDE) { + const tildePos = stream.pos; + ch2 = stream.peekByte(); + while (isWhiteSpace(ch2)) { + stream.skip(); + ch2 = stream.peekByte(); + } + if (ch2 === GT) { + stream.skip(); + break; + } + if (stream.pos > tildePos) { + const maybeEI = stream.peekBytes(2); + if (maybeEI[0] === 69 && maybeEI[1] === 73) { + break; + } + } + } + } + const length = stream.pos - startPos; + if (ch2 === -1) { + warn2("Inline ASCII85Decode image stream: EOD marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + findASCIIHexDecodeInlineStreamEnd(stream) { + const GT = 62; + const startPos = stream.pos; + let ch2; + while ((ch2 = stream.getByte()) !== -1) { + if (ch2 === GT) { + break; + } + } + const length = stream.pos - startPos; + if (ch2 === -1) { + warn2("Inline ASCIIHexDecode image stream: EOD marker not found, searching for /EI/ instead."); + stream.skip(-length); + return this.findDefaultInlineStreamEnd(stream); + } + this.inlineStreamSkipEI(stream); + return length; + } + inlineStreamSkipEI(stream) { + const E = 69, I2 = 73; + let state = 0, ch2; + while ((ch2 = stream.getByte()) !== -1) { + if (state === 0) { + state = ch2 === E ? 1 : 0; + } else if (state === 1) { + state = ch2 === I2 ? 2 : 0; + } else if (state === 2) { + break; + } + } + } + makeInlineImage(cipherTransform) { + const lexer = this.lexer; + const stream = lexer.stream; + const dictMap = /* @__PURE__ */ Object.create(null); + let dictLength; + while (!isCmd(this.buf1, "ID") && this.buf1 !== EOF) { + if (!(this.buf1 instanceof Name2)) { + throw new FormatError3("Dictionary key must be a name object"); + } + const key = this.buf1.name; + this.shift(); + if (this.buf1 === EOF) { + break; + } + dictMap[key] = this.getObj(cipherTransform); + } + if (lexer.beginInlineImagePos !== -1) { + dictLength = stream.pos - lexer.beginInlineImagePos; + } + const filter2 = this.xref.fetchIfRef(dictMap.F || dictMap.Filter); + let filterName; + if (filter2 instanceof Name2) { + filterName = filter2.name; + } else if (Array.isArray(filter2)) { + const filterZero = this.xref.fetchIfRef(filter2[0]); + if (filterZero instanceof Name2) { + filterName = filterZero.name; + } + } + const startPos = stream.pos; + let length; + switch (filterName) { + case "DCT": + case "DCTDecode": + length = this.findDCTDecodeInlineStreamEnd(stream); + break; + case "A85": + case "ASCII85Decode": + length = this.findASCII85DecodeInlineStreamEnd(stream); + break; + case "AHx": + case "ASCIIHexDecode": + length = this.findASCIIHexDecodeInlineStreamEnd(stream); + break; + default: + length = this.findDefaultInlineStreamEnd(stream); + } + let cacheKey; + if (length < MAX_LENGTH_TO_CACHE && dictLength > 0) { + const initialStreamPos = stream.pos; + stream.pos = lexer.beginInlineImagePos; + cacheKey = getInlineImageCacheKey(stream.getBytes(dictLength + length)); + stream.pos = initialStreamPos; + const cacheEntry = this.imageCache[cacheKey]; + if (cacheEntry !== void 0) { + this.buf2 = Cmd.get("EI"); + this.shift(); + cacheEntry.reset(); + return cacheEntry; + } + } + const dict = new Dict(this.xref); + for (const key in dictMap) { + dict.set(key, dictMap[key]); + } + let imageStream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) { + imageStream = cipherTransform.createStream(imageStream, length); + } + imageStream = this.filter(imageStream, dict, length); + imageStream.dict = dict; + if (cacheKey !== void 0) { + imageStream.cacheKey = `inline_img_${++this._imageId}`; + this.imageCache[cacheKey] = imageStream; + } + this.buf2 = Cmd.get("EI"); + this.shift(); + return imageStream; + } + #findStreamLength(startPos) { + const { + stream + } = this.lexer; + stream.pos = startPos; + const SCAN_BLOCK_LENGTH = 2048; + const signatureLength = "endstream".length; + const END_SIGNATURE = new Uint8Array([101, 110, 100]); + const endLength = END_SIGNATURE.length; + const PARTIAL_SIGNATURE = [new Uint8Array([115, 116, 114, 101, 97, 109]), new Uint8Array([115, 116, 101, 97, 109]), new Uint8Array([115, 116, 114, 101, 97])]; + const normalLength = signatureLength - endLength; + while (stream.pos < stream.end) { + const scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH); + const scanLength = scanBytes.length - signatureLength; + if (scanLength <= 0) { + break; + } + let pos = 0; + while (pos < scanLength) { + let j = 0; + while (j < endLength && scanBytes[pos + j] === END_SIGNATURE[j]) { + j++; + } + if (j >= endLength) { + let found = false; + for (const part of PARTIAL_SIGNATURE) { + const partLen = part.length; + let k = 0; + while (k < partLen && scanBytes[pos + j + k] === part[k]) { + k++; + } + if (k >= normalLength) { + found = true; + break; + } + if (k >= partLen) { + const lastByte = scanBytes[pos + j + k]; + if (isWhiteSpace(lastByte)) { + info2(`Found "${bytesToString2([...END_SIGNATURE, ...part])}" when searching for endstream command.`); + found = true; + } + break; + } + } + if (found) { + stream.pos += pos; + return stream.pos - startPos; + } + } + pos++; + } + stream.pos += scanLength; + } + return -1; + } + makeStream(dict, cipherTransform) { + const lexer = this.lexer; + let stream = lexer.stream; + lexer.skipToNextLine(); + const startPos = stream.pos - 1; + let length = dict.get("Length"); + if (!Number.isInteger(length)) { + info2(`Bad length "${length && length.toString()}" in stream.`); + length = 0; + } + stream.pos = startPos + length; + lexer.nextChar(); + if (this.tryShift() && isCmd(this.buf2, "endstream")) { + this.shift(); + } else { + length = this.#findStreamLength(startPos); + if (length < 0) { + throw new FormatError3("Missing endstream command."); + } + lexer.nextChar(); + this.shift(); + this.shift(); + } + this.shift(); + stream = stream.makeSubStream(startPos, length, dict); + if (cipherTransform) { + stream = cipherTransform.createStream(stream, length); + } + stream = this.filter(stream, dict, length); + stream.dict = dict; + return stream; + } + filter(stream, dict, length) { + let filter2 = dict.get("F", "Filter"); + let params = dict.get("DP", "DecodeParms"); + if (filter2 instanceof Name2) { + if (Array.isArray(params)) { + warn2("/DecodeParms should not be an Array, when /Filter is a Name."); + } + return this.makeFilter(stream, filter2.name, length, params); + } + let maybeLength = length; + if (Array.isArray(filter2)) { + const filterArray = filter2; + const paramsArray = params; + for (let i = 0, ii = filterArray.length; i < ii; ++i) { + filter2 = this.xref.fetchIfRef(filterArray[i]); + if (!(filter2 instanceof Name2)) { + throw new FormatError3(`Bad filter name "${filter2}"`); + } + params = null; + if (Array.isArray(paramsArray) && i in paramsArray) { + params = this.xref.fetchIfRef(paramsArray[i]); + } + stream = this.makeFilter(stream, filter2.name, maybeLength, params); + maybeLength = null; + } + } + return stream; + } + makeFilter(stream, name, maybeLength, params) { + if (maybeLength === 0) { + warn2(`Empty "${name}" stream.`); + return new NullStream(); + } + try { + switch (name) { + case "Fl": + case "FlateDecode": + if (params) { + return new PredictorStream(new FlateStream(stream, maybeLength), maybeLength, params); + } + return new FlateStream(stream, maybeLength); + case "LZW": + case "LZWDecode": + let earlyChange = 1; + if (params) { + if (params.has("EarlyChange")) { + earlyChange = params.get("EarlyChange"); + } + return new PredictorStream(new LZWStream(stream, maybeLength, earlyChange), maybeLength, params); + } + return new LZWStream(stream, maybeLength, earlyChange); + case "DCT": + case "DCTDecode": + return new JpegStream(stream, maybeLength, params); + case "JPX": + case "JPXDecode": + return new JpxStream(stream, maybeLength, params); + case "A85": + case "ASCII85Decode": + return new Ascii85Stream(stream, maybeLength); + case "AHx": + case "ASCIIHexDecode": + return new AsciiHexStream(stream, maybeLength); + case "CCF": + case "CCITTFaxDecode": + return new CCITTFaxStream(stream, maybeLength, params); + case "RL": + case "RunLengthDecode": + return new RunLengthStream(stream, maybeLength); + case "JBIG2Decode": + return new Jbig2Stream(stream, maybeLength, params); + } + warn2(`Filter "${name}" is not supported.`); + return stream; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`Invalid stream: "${ex}"`); + return new NullStream(); + } + } + }; + specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + Lexer = class { + constructor(stream, knownCommands = null) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + this.knownCommands = knownCommands; + this._hexStringNumWarn = 0; + this.beginInlineImagePos = -1; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + peekChar() { + return this.stream.peekByte(); + } + getNumber() { + let ch2 = this.currentChar; + let eNotation = false; + let divideBy = 0; + let sign = 1; + if (ch2 === 45) { + sign = -1; + ch2 = this.nextChar(); + if (ch2 === 45) { + ch2 = this.nextChar(); + } + } else if (ch2 === 43) { + ch2 = this.nextChar(); + } + if (ch2 === 10 || ch2 === 13) { + do { + ch2 = this.nextChar(); + } while (ch2 === 10 || ch2 === 13); + } + if (ch2 === 46) { + divideBy = 10; + ch2 = this.nextChar(); + } + if (ch2 < 48 || ch2 > 57) { + const msg = `Invalid number: ${String.fromCharCode(ch2)} (charCode ${ch2})`; + if (isWhiteSpace(ch2) || ch2 === 40 || ch2 === 60 || ch2 === -1) { + info2(`Lexer.getNumber - "${msg}".`); + return 0; + } + throw new FormatError3(msg); + } + let baseValue = ch2 - 48; + let powerValue = 0; + let powerValueSign = 1; + while ((ch2 = this.nextChar()) >= 0) { + if (ch2 >= 48 && ch2 <= 57) { + const currentDigit = ch2 - 48; + if (eNotation) { + powerValue = powerValue * 10 + currentDigit; + } else { + if (divideBy !== 0) { + divideBy *= 10; + } + baseValue = baseValue * 10 + currentDigit; + } + } else if (ch2 === 46) { + if (divideBy === 0) { + divideBy = 1; + } else { + break; + } + } else if (ch2 === 45) { + warn2("Badly formatted number: minus sign in the middle"); + } else if (ch2 === 69 || ch2 === 101) { + ch2 = this.peekChar(); + if (ch2 === 43 || ch2 === 45) { + powerValueSign = ch2 === 45 ? -1 : 1; + this.nextChar(); + } else if (ch2 < 48 || ch2 > 57) { + break; + } + eNotation = true; + } else { + break; + } + } + if (divideBy !== 0) { + baseValue /= divideBy; + } + if (eNotation) { + baseValue *= 10 ** (powerValueSign * powerValue); + } + return sign * baseValue; + } + getString() { + let numParen = 1; + let done = false; + const strBuf = this.strBuf; + strBuf.length = 0; + let ch2 = this.nextChar(); + while (true) { + let charBuffered = false; + switch (ch2 | 0) { + case -1: + warn2("Unterminated string"); + done = true; + break; + case 40: + ++numParen; + strBuf.push("("); + break; + case 41: + if (--numParen === 0) { + this.nextChar(); + done = true; + } else { + strBuf.push(")"); + } + break; + case 92: + ch2 = this.nextChar(); + switch (ch2) { + case -1: + warn2("Unterminated string"); + done = true; + break; + case 110: + strBuf.push("\n"); + break; + case 114: + strBuf.push("\r"); + break; + case 116: + strBuf.push(" "); + break; + case 98: + strBuf.push("\b"); + break; + case 102: + strBuf.push("\f"); + break; + case 92: + case 40: + case 41: + strBuf.push(String.fromCharCode(ch2)); + break; + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + let x = ch2 & 15; + ch2 = this.nextChar(); + charBuffered = true; + if (ch2 >= 48 && ch2 <= 55) { + x = (x << 3) + (ch2 & 15); + ch2 = this.nextChar(); + if (ch2 >= 48 && ch2 <= 55) { + charBuffered = false; + x = (x << 3) + (ch2 & 15); + } + } + strBuf.push(String.fromCharCode(x)); + break; + case 13: + if (this.peekChar() === 10) { + this.nextChar(); + } + break; + case 10: + break; + default: + strBuf.push(String.fromCharCode(ch2)); + break; + } + break; + default: + strBuf.push(String.fromCharCode(ch2)); + break; + } + if (done) { + break; + } + if (!charBuffered) { + ch2 = this.nextChar(); + } + } + return strBuf.join(""); + } + getName() { + let ch2, previousCh; + const strBuf = this.strBuf; + strBuf.length = 0; + while ((ch2 = this.nextChar()) >= 0 && !specialChars[ch2]) { + if (ch2 === 35) { + ch2 = this.nextChar(); + if (specialChars[ch2]) { + warn2("Lexer_getName: NUMBER SIGN (#) should be followed by a hexadecimal number."); + strBuf.push("#"); + break; + } + const x = toHexDigit(ch2); + if (x !== -1) { + previousCh = ch2; + ch2 = this.nextChar(); + const x2 = toHexDigit(ch2); + if (x2 === -1) { + warn2(`Lexer_getName: Illegal digit (${String.fromCharCode(ch2)}) in hexadecimal number.`); + strBuf.push("#", String.fromCharCode(previousCh)); + if (specialChars[ch2]) { + break; + } + strBuf.push(String.fromCharCode(ch2)); + continue; + } + strBuf.push(String.fromCharCode(x << 4 | x2)); + } else { + strBuf.push("#", String.fromCharCode(ch2)); + } + } else { + strBuf.push(String.fromCharCode(ch2)); + } + } + if (strBuf.length > 127) { + warn2(`Name token is longer than allowed by the spec: ${strBuf.length}`); + } + return Name2.get(strBuf.join("")); + } + _hexStringWarn(ch2) { + const MAX_HEX_STRING_NUM_WARN = 5; + if (this._hexStringNumWarn++ === MAX_HEX_STRING_NUM_WARN) { + warn2("getHexString - ignoring additional invalid characters."); + return; + } + if (this._hexStringNumWarn > MAX_HEX_STRING_NUM_WARN) { + return; + } + warn2(`getHexString - ignoring invalid character: ${ch2}`); + } + getHexString() { + const strBuf = this.strBuf; + strBuf.length = 0; + let ch2 = this.currentChar; + let firstDigit = -1, digit = -1; + this._hexStringNumWarn = 0; + while (true) { + if (ch2 < 0) { + warn2("Unterminated hex string"); + break; + } else if (ch2 === 62) { + this.nextChar(); + break; + } else if (specialChars[ch2] === 1) { + ch2 = this.nextChar(); + continue; + } else { + digit = toHexDigit(ch2); + if (digit === -1) { + this._hexStringWarn(ch2); + } else if (firstDigit === -1) { + firstDigit = digit; + } else { + strBuf.push(String.fromCharCode(firstDigit << 4 | digit)); + firstDigit = -1; + } + ch2 = this.nextChar(); + } + } + if (firstDigit !== -1) { + strBuf.push(String.fromCharCode(firstDigit << 4)); + } + return strBuf.join(""); + } + getObj() { + let comment = false; + let ch2 = this.currentChar; + while (true) { + if (ch2 < 0) { + return EOF; + } + if (comment) { + if (ch2 === 10 || ch2 === 13) { + comment = false; + } + } else if (ch2 === 37) { + comment = true; + } else if (specialChars[ch2] !== 1) { + break; + } + ch2 = this.nextChar(); + } + switch (ch2 | 0) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 43: + case 45: + case 46: + return this.getNumber(); + case 40: + return this.getString(); + case 47: + return this.getName(); + case 91: + this.nextChar(); + return Cmd.get("["); + case 93: + this.nextChar(); + return Cmd.get("]"); + case 60: + ch2 = this.nextChar(); + if (ch2 === 60) { + this.nextChar(); + return Cmd.get("<<"); + } + return this.getHexString(); + case 62: + ch2 = this.nextChar(); + if (ch2 === 62) { + this.nextChar(); + return Cmd.get(">>"); + } + return Cmd.get(">"); + case 123: + this.nextChar(); + return Cmd.get("{"); + case 125: + this.nextChar(); + return Cmd.get("}"); + case 41: + this.nextChar(); + throw new FormatError3(`Illegal character: ${ch2}`); + } + let str = String.fromCharCode(ch2); + if (ch2 < 32 || ch2 > 127) { + const nextCh = this.peekChar(); + if (nextCh >= 32 && nextCh <= 127) { + this.nextChar(); + return Cmd.get(str); + } + } + const knownCommands = this.knownCommands; + let knownCommandFound = knownCommands?.[str] !== void 0; + while ((ch2 = this.nextChar()) >= 0 && !specialChars[ch2]) { + const possibleCommand = str + String.fromCharCode(ch2); + if (knownCommandFound && knownCommands[possibleCommand] === void 0) { + break; + } + if (str.length === 128) { + throw new FormatError3(`Command token too long: ${str.length}`); + } + str = possibleCommand; + knownCommandFound = knownCommands?.[str] !== void 0; + } + if (str === "true") { + return true; + } + if (str === "false") { + return false; + } + if (str === "null") { + return null; + } + if (str === "BI") { + this.beginInlineImagePos = this.stream.pos; + } + return Cmd.get(str); + } + skipToNextLine() { + let ch2 = this.currentChar; + while (ch2 >= 0) { + if (ch2 === 13) { + ch2 = this.nextChar(); + if (ch2 === 10) { + this.nextChar(); + } + break; + } else if (ch2 === 10) { + this.nextChar(); + break; + } + ch2 = this.nextChar(); + } + } + }; + Linearization = class { + static create(stream) { + function getInt(linDict2, name, allowZeroValue = false) { + const obj5 = linDict2.get(name); + if (Number.isInteger(obj5) && (allowZeroValue ? obj5 >= 0 : obj5 > 0)) { + return obj5; + } + throw new Error(`The "${name}" parameter in the linearization dictionary is invalid.`); + } + function getHints(linDict2) { + const hints = linDict2.get("H"); + let hintsLength; + if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) { + for (let index2 = 0; index2 < hintsLength; index2++) { + const hint = hints[index2]; + if (!(Number.isInteger(hint) && hint > 0)) { + throw new Error(`Hint (${index2}) in the linearization dictionary is invalid.`); + } + } + return hints; + } + throw new Error("Hint array in the linearization dictionary is invalid."); + } + const parser = new Parser({ + lexer: new Lexer(stream), + xref: null + }); + const obj1 = parser.getObj(); + const obj2 = parser.getObj(); + const obj3 = parser.getObj(); + const linDict = parser.getObj(); + let obj4, length; + if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && isCmd(obj3, "obj") && linDict instanceof Dict && typeof (obj4 = linDict.get("Linearized")) === "number" && obj4 > 0)) { + return null; + } else if ((length = getInt(linDict, "L")) !== stream.length) { + throw new Error('The "L" parameter in the linearization dictionary does not equal the stream length.'); + } + return { + length, + hints: getHints(linDict), + objectNumberFirst: getInt(linDict, "O"), + endFirst: getInt(linDict, "E"), + numPages: getInt(linDict, "N"), + mainXRefEntriesOffset: getInt(linDict, "T"), + pageFirst: linDict.has("P") ? getInt(linDict, "P", true) : 0 + }; + } + }; + BUILT_IN_CMAPS = ["Adobe-GB1-UCS2", "Adobe-CNS1-UCS2", "Adobe-Japan1-UCS2", "Adobe-Korea1-UCS2", "78-EUC-H", "78-EUC-V", "78-H", "78-RKSJ-H", "78-RKSJ-V", "78-V", "78ms-RKSJ-H", "78ms-RKSJ-V", "83pv-RKSJ-H", "90ms-RKSJ-H", "90ms-RKSJ-V", "90msp-RKSJ-H", "90msp-RKSJ-V", "90pv-RKSJ-H", "90pv-RKSJ-V", "Add-H", "Add-RKSJ-H", "Add-RKSJ-V", "Add-V", "Adobe-CNS1-0", "Adobe-CNS1-1", "Adobe-CNS1-2", "Adobe-CNS1-3", "Adobe-CNS1-4", "Adobe-CNS1-5", "Adobe-CNS1-6", "Adobe-GB1-0", "Adobe-GB1-1", "Adobe-GB1-2", "Adobe-GB1-3", "Adobe-GB1-4", "Adobe-GB1-5", "Adobe-Japan1-0", "Adobe-Japan1-1", "Adobe-Japan1-2", "Adobe-Japan1-3", "Adobe-Japan1-4", "Adobe-Japan1-5", "Adobe-Japan1-6", "Adobe-Korea1-0", "Adobe-Korea1-1", "Adobe-Korea1-2", "B5-H", "B5-V", "B5pc-H", "B5pc-V", "CNS-EUC-H", "CNS-EUC-V", "CNS1-H", "CNS1-V", "CNS2-H", "CNS2-V", "ETHK-B5-H", "ETHK-B5-V", "ETen-B5-H", "ETen-B5-V", "ETenms-B5-H", "ETenms-B5-V", "EUC-H", "EUC-V", "Ext-H", "Ext-RKSJ-H", "Ext-RKSJ-V", "Ext-V", "GB-EUC-H", "GB-EUC-V", "GB-H", "GB-V", "GBK-EUC-H", "GBK-EUC-V", "GBK2K-H", "GBK2K-V", "GBKp-EUC-H", "GBKp-EUC-V", "GBT-EUC-H", "GBT-EUC-V", "GBT-H", "GBT-V", "GBTpc-EUC-H", "GBTpc-EUC-V", "GBpc-EUC-H", "GBpc-EUC-V", "H", "HKdla-B5-H", "HKdla-B5-V", "HKdlb-B5-H", "HKdlb-B5-V", "HKgccs-B5-H", "HKgccs-B5-V", "HKm314-B5-H", "HKm314-B5-V", "HKm471-B5-H", "HKm471-B5-V", "HKscs-B5-H", "HKscs-B5-V", "Hankaku", "Hiragana", "KSC-EUC-H", "KSC-EUC-V", "KSC-H", "KSC-Johab-H", "KSC-Johab-V", "KSC-V", "KSCms-UHC-H", "KSCms-UHC-HW-H", "KSCms-UHC-HW-V", "KSCms-UHC-V", "KSCpc-EUC-H", "KSCpc-EUC-V", "Katakana", "NWP-H", "NWP-V", "RKSJ-H", "RKSJ-V", "Roman", "UniCNS-UCS2-H", "UniCNS-UCS2-V", "UniCNS-UTF16-H", "UniCNS-UTF16-V", "UniCNS-UTF32-H", "UniCNS-UTF32-V", "UniCNS-UTF8-H", "UniCNS-UTF8-V", "UniGB-UCS2-H", "UniGB-UCS2-V", "UniGB-UTF16-H", "UniGB-UTF16-V", "UniGB-UTF32-H", "UniGB-UTF32-V", "UniGB-UTF8-H", "UniGB-UTF8-V", "UniJIS-UCS2-H", "UniJIS-UCS2-HW-H", "UniJIS-UCS2-HW-V", "UniJIS-UCS2-V", "UniJIS-UTF16-H", "UniJIS-UTF16-V", "UniJIS-UTF32-H", "UniJIS-UTF32-V", "UniJIS-UTF8-H", "UniJIS-UTF8-V", "UniJIS2004-UTF16-H", "UniJIS2004-UTF16-V", "UniJIS2004-UTF32-H", "UniJIS2004-UTF32-V", "UniJIS2004-UTF8-H", "UniJIS2004-UTF8-V", "UniJISPro-UCS2-HW-V", "UniJISPro-UCS2-V", "UniJISPro-UTF8-V", "UniJISX0213-UTF32-H", "UniJISX0213-UTF32-V", "UniJISX02132004-UTF32-H", "UniJISX02132004-UTF32-V", "UniKS-UCS2-H", "UniKS-UCS2-V", "UniKS-UTF16-H", "UniKS-UTF16-V", "UniKS-UTF32-H", "UniKS-UTF32-V", "UniKS-UTF8-H", "UniKS-UTF8-V", "V", "WP-Symbol"]; + MAX_MAP_RANGE = 2 ** 24 - 1; + CMap = class { + constructor(builtInCMap = false) { + this.codespaceRanges = [[], [], [], []]; + this.numCodespaceRanges = 0; + this._map = []; + this.name = ""; + this.vertical = false; + this.useCMap = null; + this.builtInCMap = builtInCMap; + } + addCodespaceRange(n, low, high) { + this.codespaceRanges[n - 1].push(low, high); + this.numCodespaceRanges++; + } + mapCidRange(low, high, dstLow) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapCidRange - ignoring data above MAX_MAP_RANGE."); + } + while (low <= high) { + this._map[low++] = dstLow++; + } + } + mapBfRange(low, high, dstLow) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapBfRange - ignoring data above MAX_MAP_RANGE."); + } + const lastByte = dstLow.length - 1; + while (low <= high) { + this._map[low++] = dstLow; + const nextCharCode = dstLow.charCodeAt(lastByte) + 1; + if (nextCharCode > 255) { + dstLow = dstLow.substring(0, lastByte - 1) + String.fromCharCode(dstLow.charCodeAt(lastByte - 1) + 1) + "\0"; + continue; + } + dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(nextCharCode); + } + } + mapBfRangeToArray(low, high, array2) { + if (high - low > MAX_MAP_RANGE) { + throw new Error("mapBfRangeToArray - ignoring data above MAX_MAP_RANGE."); + } + const ii = array2.length; + let i = 0; + while (low <= high && i < ii) { + this._map[low] = array2[i++]; + ++low; + } + } + mapOne(src, dst) { + this._map[src] = dst; + } + lookup(code) { + return this._map[code]; + } + contains(code) { + return this._map[code] !== void 0; + } + forEach(callback) { + const map3 = this._map; + const length = map3.length; + if (length <= 65536) { + for (let i = 0; i < length; i++) { + if (map3[i] !== void 0) { + callback(i, map3[i]); + } + } + } else { + for (const i in map3) { + callback(i, map3[i]); + } + } + } + charCodeOf(value) { + const map3 = this._map; + if (map3.length <= 65536) { + return map3.indexOf(value); + } + for (const charCode in map3) { + if (map3[charCode] === value) { + return charCode | 0; + } + } + return -1; + } + getMap() { + return this._map; + } + readCharCode(str, offset, out) { + let c = 0; + const codespaceRanges = this.codespaceRanges; + for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { + c = (c << 8 | str.charCodeAt(offset + n)) >>> 0; + const codespaceRange = codespaceRanges[n]; + for (let k = 0, kk = codespaceRange.length; k < kk; ) { + const low = codespaceRange[k++]; + const high = codespaceRange[k++]; + if (c >= low && c <= high) { + out.charcode = c; + out.length = n + 1; + return; + } + } + } + out.charcode = 0; + out.length = 1; + } + getCharCodeLength(charCode) { + const codespaceRanges = this.codespaceRanges; + for (let n = 0, nn = codespaceRanges.length; n < nn; n++) { + const codespaceRange = codespaceRanges[n]; + for (let k = 0, kk = codespaceRange.length; k < kk; ) { + const low = codespaceRange[k++]; + const high = codespaceRange[k++]; + if (charCode >= low && charCode <= high) { + return n + 1; + } + } + } + return 1; + } + get length() { + return this._map.length; + } + get isIdentityCMap() { + if (!(this.name === "Identity-H" || this.name === "Identity-V")) { + return false; + } + if (this._map.length !== 65536) { + return false; + } + for (let i = 0; i < 65536; i++) { + if (this._map[i] !== i) { + return false; + } + } + return true; + } + }; + IdentityCMap = class extends CMap { + constructor(vertical, n) { + super(); + this.vertical = vertical; + this.addCodespaceRange(n, 0, 65535); + } + mapCidRange(low, high, dstLow) { + unreachable2("should not call mapCidRange"); + } + mapBfRange(low, high, dstLow) { + unreachable2("should not call mapBfRange"); + } + mapBfRangeToArray(low, high, array2) { + unreachable2("should not call mapBfRangeToArray"); + } + mapOne(src, dst) { + unreachable2("should not call mapCidOne"); + } + lookup(code) { + return Number.isInteger(code) && code <= 65535 ? code : void 0; + } + contains(code) { + return Number.isInteger(code) && code <= 65535; + } + forEach(callback) { + for (let i = 0; i <= 65535; i++) { + callback(i, i); + } + } + charCodeOf(value) { + return Number.isInteger(value) && value <= 65535 ? value : -1; + } + getMap() { + const map3 = new Array(65536); + for (let i = 0; i <= 65535; i++) { + map3[i] = i; + } + return map3; + } + get length() { + return 65536; + } + get isIdentityCMap() { + unreachable2("should not access .isIdentityCMap"); + } + }; + CMapFactory = class { + static async create({ + encoding, + fetchBuiltInCMap, + useCMap + }) { + if (encoding instanceof Name2) { + return createBuiltInCMap(encoding.name, fetchBuiltInCMap); + } else if (encoding instanceof BaseStream) { + const parsedCMap = await parseCMap(new CMap(), new Lexer(encoding), fetchBuiltInCMap, useCMap); + if (parsedCMap.isIdentityCMap) { + return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap); + } + return parsedCMap; + } + throw new Error("Encoding required."); + } + }; + ExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "", "", "", "isuperior", "", "", "lsuperior", "msuperior", "nsuperior", "osuperior", "", "", "rsuperior", "ssuperior", "tsuperior", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdownsmall", "centoldstyle", "Lslashsmall", "", "", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "", "Dotaccentsmall", "", "", "Macronsmall", "", "", "figuredash", "hypheninferior", "", "", "Ogoneksmall", "Ringsmall", "Cedillasmall", "", "", "", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"]; + MacExpertEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclamsmall", "Hungarumlautsmall", "centoldstyle", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "", "threequartersemdash", "", "questionsmall", "", "", "", "", "Ethsmall", "", "", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "", "", "", "", "", "", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior", "Circumflexsmall", "hypheninferior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "", "", "asuperior", "centsuperior", "", "", "", "", "Aacutesmall", "Agravesmall", "Acircumflexsmall", "Adieresissmall", "Atildesmall", "Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall", "Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall", "Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall", "Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall", "Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall", "", "eightsuperior", "fourinferior", "threeinferior", "sixinferior", "eightinferior", "seveninferior", "Scaronsmall", "", "centinferior", "twoinferior", "", "Dieresissmall", "", "Caronsmall", "osuperior", "fiveinferior", "", "commainferior", "periodinferior", "Yacutesmall", "", "dollarinferior", "", "", "Thornsmall", "", "nineinferior", "zeroinferior", "Zcaronsmall", "AEsmall", "Oslashsmall", "questiondownsmall", "oneinferior", "Lslashsmall", "", "", "", "", "", "", "Cedillasmall", "", "", "", "", "", "OEsmall", "figuredash", "hyphensuperior", "", "", "", "", "exclamdownsmall", "", "Ydieresissmall", "", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "ninesuperior", "zerosuperior", "", "esuperior", "rsuperior", "tsuperior", "", "", "isuperior", "ssuperior", "dsuperior", "", "", "", "", "", "lsuperior", "Ogoneksmall", "Brevesmall", "Macronsmall", "bsuperior", "nsuperior", "msuperior", "commasuperior", "periodsuperior", "Dotaccentsmall", "Ringsmall", "", "", "", ""]; + MacRomanEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron"]; + StandardEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "", "endash", "dagger", "daggerdbl", "periodcentered", "", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "", "questiondown", "", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "", "ring", "cedilla", "", "hungarumlaut", "ogonek", "caron", "emdash", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "AE", "", "ordfeminine", "", "", "", "", "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "", "", "ae", "", "", "", "dotlessi", "", "", "lslash", "oslash", "oe", "germandbls", "", "", "", ""]; + WinAnsiEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase", "ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron", "guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft", "quoteright", "quotedblleft", "quotedblright", "bullet", "endash", "emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet", "zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling", "currency", "yen", "brokenbar", "section", "dieresis", "copyright", "ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered", "macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute", "mu", "paragraph", "periodcentered", "cedilla", "onesuperior", "ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis", "Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn", "germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis", "aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis", "igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve", "oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash", "ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn", "ydieresis"]; + SymbolSetEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "exclam", "universal", "numbersign", "existential", "percent", "ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus", "comma", "minus", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi", "Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa", "Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau", "Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft", "therefore", "bracketright", "perpendicular", "underscore", "radicalex", "alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota", "phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho", "sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta", "braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal", "fraction", "infinity", "florin", "club", "diamond", "heart", "spade", "arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree", "plusminus", "second", "greaterequal", "multiply", "proportional", "partialdiff", "bullet", "divide", "notequal", "equivalence", "approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn", "aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply", "circleplus", "emptyset", "intersection", "union", "propersuperset", "reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element", "notelement", "angle", "gradient", "registerserif", "copyrightserif", "trademarkserif", "product", "radical", "dotmath", "logicalnot", "logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup", "arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans", "copyrightsans", "trademarksans", "summation", "parenlefttp", "parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex", "bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex", "", "angleright", "integral", "integraltp", "integralex", "integralbt", "parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp", "bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid", "bracerightbt", ""]; + ZapfDingbatsEncoding = ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117", "a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19", "a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7", "a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36", "a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46", "a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56", "a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75", "a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97", "a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205", "a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103", "a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120", "a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129", "a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138", "a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147", "a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156", "a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165", "a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173", "a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180", "a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185", "a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""]; + getGlyphsUnicode = getLookupTableFactory(function(t) { + t.A = 65; + t.AE = 198; + t.AEacute = 508; + t.AEmacron = 482; + t.AEsmall = 63462; + t.Aacute = 193; + t.Aacutesmall = 63457; + t.Abreve = 258; + t.Abreveacute = 7854; + t.Abrevecyrillic = 1232; + t.Abrevedotbelow = 7862; + t.Abrevegrave = 7856; + t.Abrevehookabove = 7858; + t.Abrevetilde = 7860; + t.Acaron = 461; + t.Acircle = 9398; + t.Acircumflex = 194; + t.Acircumflexacute = 7844; + t.Acircumflexdotbelow = 7852; + t.Acircumflexgrave = 7846; + t.Acircumflexhookabove = 7848; + t.Acircumflexsmall = 63458; + t.Acircumflextilde = 7850; + t.Acute = 63177; + t.Acutesmall = 63412; + t.Acyrillic = 1040; + t.Adblgrave = 512; + t.Adieresis = 196; + t.Adieresiscyrillic = 1234; + t.Adieresismacron = 478; + t.Adieresissmall = 63460; + t.Adotbelow = 7840; + t.Adotmacron = 480; + t.Agrave = 192; + t.Agravesmall = 63456; + t.Ahookabove = 7842; + t.Aiecyrillic = 1236; + t.Ainvertedbreve = 514; + t.Alpha = 913; + t.Alphatonos = 902; + t.Amacron = 256; + t.Amonospace = 65313; + t.Aogonek = 260; + t.Aring = 197; + t.Aringacute = 506; + t.Aringbelow = 7680; + t.Aringsmall = 63461; + t.Asmall = 63329; + t.Atilde = 195; + t.Atildesmall = 63459; + t.Aybarmenian = 1329; + t.B = 66; + t.Bcircle = 9399; + t.Bdotaccent = 7682; + t.Bdotbelow = 7684; + t.Becyrillic = 1041; + t.Benarmenian = 1330; + t.Beta = 914; + t.Bhook = 385; + t.Blinebelow = 7686; + t.Bmonospace = 65314; + t.Brevesmall = 63220; + t.Bsmall = 63330; + t.Btopbar = 386; + t.C = 67; + t.Caarmenian = 1342; + t.Cacute = 262; + t.Caron = 63178; + t.Caronsmall = 63221; + t.Ccaron = 268; + t.Ccedilla = 199; + t.Ccedillaacute = 7688; + t.Ccedillasmall = 63463; + t.Ccircle = 9400; + t.Ccircumflex = 264; + t.Cdot = 266; + t.Cdotaccent = 266; + t.Cedillasmall = 63416; + t.Chaarmenian = 1353; + t.Cheabkhasiancyrillic = 1212; + t.Checyrillic = 1063; + t.Chedescenderabkhasiancyrillic = 1214; + t.Chedescendercyrillic = 1206; + t.Chedieresiscyrillic = 1268; + t.Cheharmenian = 1347; + t.Chekhakassiancyrillic = 1227; + t.Cheverticalstrokecyrillic = 1208; + t.Chi = 935; + t.Chook = 391; + t.Circumflexsmall = 63222; + t.Cmonospace = 65315; + t.Coarmenian = 1361; + t.Csmall = 63331; + t.D = 68; + t.DZ = 497; + t.DZcaron = 452; + t.Daarmenian = 1332; + t.Dafrican = 393; + t.Dcaron = 270; + t.Dcedilla = 7696; + t.Dcircle = 9401; + t.Dcircumflexbelow = 7698; + t.Dcroat = 272; + t.Ddotaccent = 7690; + t.Ddotbelow = 7692; + t.Decyrillic = 1044; + t.Deicoptic = 1006; + t.Delta = 8710; + t.Deltagreek = 916; + t.Dhook = 394; + t.Dieresis = 63179; + t.DieresisAcute = 63180; + t.DieresisGrave = 63181; + t.Dieresissmall = 63400; + t.Digammagreek = 988; + t.Djecyrillic = 1026; + t.Dlinebelow = 7694; + t.Dmonospace = 65316; + t.Dotaccentsmall = 63223; + t.Dslash = 272; + t.Dsmall = 63332; + t.Dtopbar = 395; + t.Dz = 498; + t.Dzcaron = 453; + t.Dzeabkhasiancyrillic = 1248; + t.Dzecyrillic = 1029; + t.Dzhecyrillic = 1039; + t.E = 69; + t.Eacute = 201; + t.Eacutesmall = 63465; + t.Ebreve = 276; + t.Ecaron = 282; + t.Ecedillabreve = 7708; + t.Echarmenian = 1333; + t.Ecircle = 9402; + t.Ecircumflex = 202; + t.Ecircumflexacute = 7870; + t.Ecircumflexbelow = 7704; + t.Ecircumflexdotbelow = 7878; + t.Ecircumflexgrave = 7872; + t.Ecircumflexhookabove = 7874; + t.Ecircumflexsmall = 63466; + t.Ecircumflextilde = 7876; + t.Ecyrillic = 1028; + t.Edblgrave = 516; + t.Edieresis = 203; + t.Edieresissmall = 63467; + t.Edot = 278; + t.Edotaccent = 278; + t.Edotbelow = 7864; + t.Efcyrillic = 1060; + t.Egrave = 200; + t.Egravesmall = 63464; + t.Eharmenian = 1335; + t.Ehookabove = 7866; + t.Eightroman = 8551; + t.Einvertedbreve = 518; + t.Eiotifiedcyrillic = 1124; + t.Elcyrillic = 1051; + t.Elevenroman = 8554; + t.Emacron = 274; + t.Emacronacute = 7702; + t.Emacrongrave = 7700; + t.Emcyrillic = 1052; + t.Emonospace = 65317; + t.Encyrillic = 1053; + t.Endescendercyrillic = 1186; + t.Eng = 330; + t.Enghecyrillic = 1188; + t.Enhookcyrillic = 1223; + t.Eogonek = 280; + t.Eopen = 400; + t.Epsilon = 917; + t.Epsilontonos = 904; + t.Ercyrillic = 1056; + t.Ereversed = 398; + t.Ereversedcyrillic = 1069; + t.Escyrillic = 1057; + t.Esdescendercyrillic = 1194; + t.Esh = 425; + t.Esmall = 63333; + t.Eta = 919; + t.Etarmenian = 1336; + t.Etatonos = 905; + t.Eth = 208; + t.Ethsmall = 63472; + t.Etilde = 7868; + t.Etildebelow = 7706; + t.Euro = 8364; + t.Ezh = 439; + t.Ezhcaron = 494; + t.Ezhreversed = 440; + t.F = 70; + t.Fcircle = 9403; + t.Fdotaccent = 7710; + t.Feharmenian = 1366; + t.Feicoptic = 996; + t.Fhook = 401; + t.Fitacyrillic = 1138; + t.Fiveroman = 8548; + t.Fmonospace = 65318; + t.Fourroman = 8547; + t.Fsmall = 63334; + t.G = 71; + t.GBsquare = 13191; + t.Gacute = 500; + t.Gamma = 915; + t.Gammaafrican = 404; + t.Gangiacoptic = 1002; + t.Gbreve = 286; + t.Gcaron = 486; + t.Gcedilla = 290; + t.Gcircle = 9404; + t.Gcircumflex = 284; + t.Gcommaaccent = 290; + t.Gdot = 288; + t.Gdotaccent = 288; + t.Gecyrillic = 1043; + t.Ghadarmenian = 1346; + t.Ghemiddlehookcyrillic = 1172; + t.Ghestrokecyrillic = 1170; + t.Gheupturncyrillic = 1168; + t.Ghook = 403; + t.Gimarmenian = 1331; + t.Gjecyrillic = 1027; + t.Gmacron = 7712; + t.Gmonospace = 65319; + t.Grave = 63182; + t.Gravesmall = 63328; + t.Gsmall = 63335; + t.Gsmallhook = 667; + t.Gstroke = 484; + t.H = 72; + t.H18533 = 9679; + t.H18543 = 9642; + t.H18551 = 9643; + t.H22073 = 9633; + t.HPsquare = 13259; + t.Haabkhasiancyrillic = 1192; + t.Hadescendercyrillic = 1202; + t.Hardsigncyrillic = 1066; + t.Hbar = 294; + t.Hbrevebelow = 7722; + t.Hcedilla = 7720; + t.Hcircle = 9405; + t.Hcircumflex = 292; + t.Hdieresis = 7718; + t.Hdotaccent = 7714; + t.Hdotbelow = 7716; + t.Hmonospace = 65320; + t.Hoarmenian = 1344; + t.Horicoptic = 1e3; + t.Hsmall = 63336; + t.Hungarumlaut = 63183; + t.Hungarumlautsmall = 63224; + t.Hzsquare = 13200; + t.I = 73; + t.IAcyrillic = 1071; + t.IJ = 306; + t.IUcyrillic = 1070; + t.Iacute = 205; + t.Iacutesmall = 63469; + t.Ibreve = 300; + t.Icaron = 463; + t.Icircle = 9406; + t.Icircumflex = 206; + t.Icircumflexsmall = 63470; + t.Icyrillic = 1030; + t.Idblgrave = 520; + t.Idieresis = 207; + t.Idieresisacute = 7726; + t.Idieresiscyrillic = 1252; + t.Idieresissmall = 63471; + t.Idot = 304; + t.Idotaccent = 304; + t.Idotbelow = 7882; + t.Iebrevecyrillic = 1238; + t.Iecyrillic = 1045; + t.Ifraktur = 8465; + t.Igrave = 204; + t.Igravesmall = 63468; + t.Ihookabove = 7880; + t.Iicyrillic = 1048; + t.Iinvertedbreve = 522; + t.Iishortcyrillic = 1049; + t.Imacron = 298; + t.Imacroncyrillic = 1250; + t.Imonospace = 65321; + t.Iniarmenian = 1339; + t.Iocyrillic = 1025; + t.Iogonek = 302; + t.Iota = 921; + t.Iotaafrican = 406; + t.Iotadieresis = 938; + t.Iotatonos = 906; + t.Ismall = 63337; + t.Istroke = 407; + t.Itilde = 296; + t.Itildebelow = 7724; + t.Izhitsacyrillic = 1140; + t.Izhitsadblgravecyrillic = 1142; + t.J = 74; + t.Jaarmenian = 1345; + t.Jcircle = 9407; + t.Jcircumflex = 308; + t.Jecyrillic = 1032; + t.Jheharmenian = 1355; + t.Jmonospace = 65322; + t.Jsmall = 63338; + t.K = 75; + t.KBsquare = 13189; + t.KKsquare = 13261; + t.Kabashkircyrillic = 1184; + t.Kacute = 7728; + t.Kacyrillic = 1050; + t.Kadescendercyrillic = 1178; + t.Kahookcyrillic = 1219; + t.Kappa = 922; + t.Kastrokecyrillic = 1182; + t.Kaverticalstrokecyrillic = 1180; + t.Kcaron = 488; + t.Kcedilla = 310; + t.Kcircle = 9408; + t.Kcommaaccent = 310; + t.Kdotbelow = 7730; + t.Keharmenian = 1364; + t.Kenarmenian = 1343; + t.Khacyrillic = 1061; + t.Kheicoptic = 998; + t.Khook = 408; + t.Kjecyrillic = 1036; + t.Klinebelow = 7732; + t.Kmonospace = 65323; + t.Koppacyrillic = 1152; + t.Koppagreek = 990; + t.Ksicyrillic = 1134; + t.Ksmall = 63339; + t.L = 76; + t.LJ = 455; + t.LL = 63167; + t.Lacute = 313; + t.Lambda = 923; + t.Lcaron = 317; + t.Lcedilla = 315; + t.Lcircle = 9409; + t.Lcircumflexbelow = 7740; + t.Lcommaaccent = 315; + t.Ldot = 319; + t.Ldotaccent = 319; + t.Ldotbelow = 7734; + t.Ldotbelowmacron = 7736; + t.Liwnarmenian = 1340; + t.Lj = 456; + t.Ljecyrillic = 1033; + t.Llinebelow = 7738; + t.Lmonospace = 65324; + t.Lslash = 321; + t.Lslashsmall = 63225; + t.Lsmall = 63340; + t.M = 77; + t.MBsquare = 13190; + t.Macron = 63184; + t.Macronsmall = 63407; + t.Macute = 7742; + t.Mcircle = 9410; + t.Mdotaccent = 7744; + t.Mdotbelow = 7746; + t.Menarmenian = 1348; + t.Mmonospace = 65325; + t.Msmall = 63341; + t.Mturned = 412; + t.Mu = 924; + t.N = 78; + t.NJ = 458; + t.Nacute = 323; + t.Ncaron = 327; + t.Ncedilla = 325; + t.Ncircle = 9411; + t.Ncircumflexbelow = 7754; + t.Ncommaaccent = 325; + t.Ndotaccent = 7748; + t.Ndotbelow = 7750; + t.Nhookleft = 413; + t.Nineroman = 8552; + t.Nj = 459; + t.Njecyrillic = 1034; + t.Nlinebelow = 7752; + t.Nmonospace = 65326; + t.Nowarmenian = 1350; + t.Nsmall = 63342; + t.Ntilde = 209; + t.Ntildesmall = 63473; + t.Nu = 925; + t.O = 79; + t.OE = 338; + t.OEsmall = 63226; + t.Oacute = 211; + t.Oacutesmall = 63475; + t.Obarredcyrillic = 1256; + t.Obarreddieresiscyrillic = 1258; + t.Obreve = 334; + t.Ocaron = 465; + t.Ocenteredtilde = 415; + t.Ocircle = 9412; + t.Ocircumflex = 212; + t.Ocircumflexacute = 7888; + t.Ocircumflexdotbelow = 7896; + t.Ocircumflexgrave = 7890; + t.Ocircumflexhookabove = 7892; + t.Ocircumflexsmall = 63476; + t.Ocircumflextilde = 7894; + t.Ocyrillic = 1054; + t.Odblacute = 336; + t.Odblgrave = 524; + t.Odieresis = 214; + t.Odieresiscyrillic = 1254; + t.Odieresissmall = 63478; + t.Odotbelow = 7884; + t.Ogoneksmall = 63227; + t.Ograve = 210; + t.Ogravesmall = 63474; + t.Oharmenian = 1365; + t.Ohm = 8486; + t.Ohookabove = 7886; + t.Ohorn = 416; + t.Ohornacute = 7898; + t.Ohorndotbelow = 7906; + t.Ohorngrave = 7900; + t.Ohornhookabove = 7902; + t.Ohorntilde = 7904; + t.Ohungarumlaut = 336; + t.Oi = 418; + t.Oinvertedbreve = 526; + t.Omacron = 332; + t.Omacronacute = 7762; + t.Omacrongrave = 7760; + t.Omega = 8486; + t.Omegacyrillic = 1120; + t.Omegagreek = 937; + t.Omegaroundcyrillic = 1146; + t.Omegatitlocyrillic = 1148; + t.Omegatonos = 911; + t.Omicron = 927; + t.Omicrontonos = 908; + t.Omonospace = 65327; + t.Oneroman = 8544; + t.Oogonek = 490; + t.Oogonekmacron = 492; + t.Oopen = 390; + t.Oslash = 216; + t.Oslashacute = 510; + t.Oslashsmall = 63480; + t.Osmall = 63343; + t.Ostrokeacute = 510; + t.Otcyrillic = 1150; + t.Otilde = 213; + t.Otildeacute = 7756; + t.Otildedieresis = 7758; + t.Otildesmall = 63477; + t.P = 80; + t.Pacute = 7764; + t.Pcircle = 9413; + t.Pdotaccent = 7766; + t.Pecyrillic = 1055; + t.Peharmenian = 1354; + t.Pemiddlehookcyrillic = 1190; + t.Phi = 934; + t.Phook = 420; + t.Pi = 928; + t.Piwrarmenian = 1363; + t.Pmonospace = 65328; + t.Psi = 936; + t.Psicyrillic = 1136; + t.Psmall = 63344; + t.Q = 81; + t.Qcircle = 9414; + t.Qmonospace = 65329; + t.Qsmall = 63345; + t.R = 82; + t.Raarmenian = 1356; + t.Racute = 340; + t.Rcaron = 344; + t.Rcedilla = 342; + t.Rcircle = 9415; + t.Rcommaaccent = 342; + t.Rdblgrave = 528; + t.Rdotaccent = 7768; + t.Rdotbelow = 7770; + t.Rdotbelowmacron = 7772; + t.Reharmenian = 1360; + t.Rfraktur = 8476; + t.Rho = 929; + t.Ringsmall = 63228; + t.Rinvertedbreve = 530; + t.Rlinebelow = 7774; + t.Rmonospace = 65330; + t.Rsmall = 63346; + t.Rsmallinverted = 641; + t.Rsmallinvertedsuperior = 694; + t.S = 83; + t.SF010000 = 9484; + t.SF020000 = 9492; + t.SF030000 = 9488; + t.SF040000 = 9496; + t.SF050000 = 9532; + t.SF060000 = 9516; + t.SF070000 = 9524; + t.SF080000 = 9500; + t.SF090000 = 9508; + t.SF100000 = 9472; + t.SF110000 = 9474; + t.SF190000 = 9569; + t.SF200000 = 9570; + t.SF210000 = 9558; + t.SF220000 = 9557; + t.SF230000 = 9571; + t.SF240000 = 9553; + t.SF250000 = 9559; + t.SF260000 = 9565; + t.SF270000 = 9564; + t.SF280000 = 9563; + t.SF360000 = 9566; + t.SF370000 = 9567; + t.SF380000 = 9562; + t.SF390000 = 9556; + t.SF400000 = 9577; + t.SF410000 = 9574; + t.SF420000 = 9568; + t.SF430000 = 9552; + t.SF440000 = 9580; + t.SF450000 = 9575; + t.SF460000 = 9576; + t.SF470000 = 9572; + t.SF480000 = 9573; + t.SF490000 = 9561; + t.SF500000 = 9560; + t.SF510000 = 9554; + t.SF520000 = 9555; + t.SF530000 = 9579; + t.SF540000 = 9578; + t.Sacute = 346; + t.Sacutedotaccent = 7780; + t.Sampigreek = 992; + t.Scaron = 352; + t.Scarondotaccent = 7782; + t.Scaronsmall = 63229; + t.Scedilla = 350; + t.Schwa = 399; + t.Schwacyrillic = 1240; + t.Schwadieresiscyrillic = 1242; + t.Scircle = 9416; + t.Scircumflex = 348; + t.Scommaaccent = 536; + t.Sdotaccent = 7776; + t.Sdotbelow = 7778; + t.Sdotbelowdotaccent = 7784; + t.Seharmenian = 1357; + t.Sevenroman = 8550; + t.Shaarmenian = 1351; + t.Shacyrillic = 1064; + t.Shchacyrillic = 1065; + t.Sheicoptic = 994; + t.Shhacyrillic = 1210; + t.Shimacoptic = 1004; + t.Sigma = 931; + t.Sixroman = 8549; + t.Smonospace = 65331; + t.Softsigncyrillic = 1068; + t.Ssmall = 63347; + t.Stigmagreek = 986; + t.T = 84; + t.Tau = 932; + t.Tbar = 358; + t.Tcaron = 356; + t.Tcedilla = 354; + t.Tcircle = 9417; + t.Tcircumflexbelow = 7792; + t.Tcommaaccent = 354; + t.Tdotaccent = 7786; + t.Tdotbelow = 7788; + t.Tecyrillic = 1058; + t.Tedescendercyrillic = 1196; + t.Tenroman = 8553; + t.Tetsecyrillic = 1204; + t.Theta = 920; + t.Thook = 428; + t.Thorn = 222; + t.Thornsmall = 63486; + t.Threeroman = 8546; + t.Tildesmall = 63230; + t.Tiwnarmenian = 1359; + t.Tlinebelow = 7790; + t.Tmonospace = 65332; + t.Toarmenian = 1337; + t.Tonefive = 444; + t.Tonesix = 388; + t.Tonetwo = 423; + t.Tretroflexhook = 430; + t.Tsecyrillic = 1062; + t.Tshecyrillic = 1035; + t.Tsmall = 63348; + t.Twelveroman = 8555; + t.Tworoman = 8545; + t.U = 85; + t.Uacute = 218; + t.Uacutesmall = 63482; + t.Ubreve = 364; + t.Ucaron = 467; + t.Ucircle = 9418; + t.Ucircumflex = 219; + t.Ucircumflexbelow = 7798; + t.Ucircumflexsmall = 63483; + t.Ucyrillic = 1059; + t.Udblacute = 368; + t.Udblgrave = 532; + t.Udieresis = 220; + t.Udieresisacute = 471; + t.Udieresisbelow = 7794; + t.Udieresiscaron = 473; + t.Udieresiscyrillic = 1264; + t.Udieresisgrave = 475; + t.Udieresismacron = 469; + t.Udieresissmall = 63484; + t.Udotbelow = 7908; + t.Ugrave = 217; + t.Ugravesmall = 63481; + t.Uhookabove = 7910; + t.Uhorn = 431; + t.Uhornacute = 7912; + t.Uhorndotbelow = 7920; + t.Uhorngrave = 7914; + t.Uhornhookabove = 7916; + t.Uhorntilde = 7918; + t.Uhungarumlaut = 368; + t.Uhungarumlautcyrillic = 1266; + t.Uinvertedbreve = 534; + t.Ukcyrillic = 1144; + t.Umacron = 362; + t.Umacroncyrillic = 1262; + t.Umacrondieresis = 7802; + t.Umonospace = 65333; + t.Uogonek = 370; + t.Upsilon = 933; + t.Upsilon1 = 978; + t.Upsilonacutehooksymbolgreek = 979; + t.Upsilonafrican = 433; + t.Upsilondieresis = 939; + t.Upsilondieresishooksymbolgreek = 980; + t.Upsilonhooksymbol = 978; + t.Upsilontonos = 910; + t.Uring = 366; + t.Ushortcyrillic = 1038; + t.Usmall = 63349; + t.Ustraightcyrillic = 1198; + t.Ustraightstrokecyrillic = 1200; + t.Utilde = 360; + t.Utildeacute = 7800; + t.Utildebelow = 7796; + t.V = 86; + t.Vcircle = 9419; + t.Vdotbelow = 7806; + t.Vecyrillic = 1042; + t.Vewarmenian = 1358; + t.Vhook = 434; + t.Vmonospace = 65334; + t.Voarmenian = 1352; + t.Vsmall = 63350; + t.Vtilde = 7804; + t.W = 87; + t.Wacute = 7810; + t.Wcircle = 9420; + t.Wcircumflex = 372; + t.Wdieresis = 7812; + t.Wdotaccent = 7814; + t.Wdotbelow = 7816; + t.Wgrave = 7808; + t.Wmonospace = 65335; + t.Wsmall = 63351; + t.X = 88; + t.Xcircle = 9421; + t.Xdieresis = 7820; + t.Xdotaccent = 7818; + t.Xeharmenian = 1341; + t.Xi = 926; + t.Xmonospace = 65336; + t.Xsmall = 63352; + t.Y = 89; + t.Yacute = 221; + t.Yacutesmall = 63485; + t.Yatcyrillic = 1122; + t.Ycircle = 9422; + t.Ycircumflex = 374; + t.Ydieresis = 376; + t.Ydieresissmall = 63487; + t.Ydotaccent = 7822; + t.Ydotbelow = 7924; + t.Yericyrillic = 1067; + t.Yerudieresiscyrillic = 1272; + t.Ygrave = 7922; + t.Yhook = 435; + t.Yhookabove = 7926; + t.Yiarmenian = 1349; + t.Yicyrillic = 1031; + t.Yiwnarmenian = 1362; + t.Ymonospace = 65337; + t.Ysmall = 63353; + t.Ytilde = 7928; + t.Yusbigcyrillic = 1130; + t.Yusbigiotifiedcyrillic = 1132; + t.Yuslittlecyrillic = 1126; + t.Yuslittleiotifiedcyrillic = 1128; + t.Z = 90; + t.Zaarmenian = 1334; + t.Zacute = 377; + t.Zcaron = 381; + t.Zcaronsmall = 63231; + t.Zcircle = 9423; + t.Zcircumflex = 7824; + t.Zdot = 379; + t.Zdotaccent = 379; + t.Zdotbelow = 7826; + t.Zecyrillic = 1047; + t.Zedescendercyrillic = 1176; + t.Zedieresiscyrillic = 1246; + t.Zeta = 918; + t.Zhearmenian = 1338; + t.Zhebrevecyrillic = 1217; + t.Zhecyrillic = 1046; + t.Zhedescendercyrillic = 1174; + t.Zhedieresiscyrillic = 1244; + t.Zlinebelow = 7828; + t.Zmonospace = 65338; + t.Zsmall = 63354; + t.Zstroke = 437; + t.a = 97; + t.aabengali = 2438; + t.aacute = 225; + t.aadeva = 2310; + t.aagujarati = 2694; + t.aagurmukhi = 2566; + t.aamatragurmukhi = 2622; + t.aarusquare = 13059; + t.aavowelsignbengali = 2494; + t.aavowelsigndeva = 2366; + t.aavowelsigngujarati = 2750; + t.abbreviationmarkarmenian = 1375; + t.abbreviationsigndeva = 2416; + t.abengali = 2437; + t.abopomofo = 12570; + t.abreve = 259; + t.abreveacute = 7855; + t.abrevecyrillic = 1233; + t.abrevedotbelow = 7863; + t.abrevegrave = 7857; + t.abrevehookabove = 7859; + t.abrevetilde = 7861; + t.acaron = 462; + t.acircle = 9424; + t.acircumflex = 226; + t.acircumflexacute = 7845; + t.acircumflexdotbelow = 7853; + t.acircumflexgrave = 7847; + t.acircumflexhookabove = 7849; + t.acircumflextilde = 7851; + t.acute = 180; + t.acutebelowcmb = 791; + t.acutecmb = 769; + t.acutecomb = 769; + t.acutedeva = 2388; + t.acutelowmod = 719; + t.acutetonecmb = 833; + t.acyrillic = 1072; + t.adblgrave = 513; + t.addakgurmukhi = 2673; + t.adeva = 2309; + t.adieresis = 228; + t.adieresiscyrillic = 1235; + t.adieresismacron = 479; + t.adotbelow = 7841; + t.adotmacron = 481; + t.ae = 230; + t.aeacute = 509; + t.aekorean = 12624; + t.aemacron = 483; + t.afii00208 = 8213; + t.afii08941 = 8356; + t.afii10017 = 1040; + t.afii10018 = 1041; + t.afii10019 = 1042; + t.afii10020 = 1043; + t.afii10021 = 1044; + t.afii10022 = 1045; + t.afii10023 = 1025; + t.afii10024 = 1046; + t.afii10025 = 1047; + t.afii10026 = 1048; + t.afii10027 = 1049; + t.afii10028 = 1050; + t.afii10029 = 1051; + t.afii10030 = 1052; + t.afii10031 = 1053; + t.afii10032 = 1054; + t.afii10033 = 1055; + t.afii10034 = 1056; + t.afii10035 = 1057; + t.afii10036 = 1058; + t.afii10037 = 1059; + t.afii10038 = 1060; + t.afii10039 = 1061; + t.afii10040 = 1062; + t.afii10041 = 1063; + t.afii10042 = 1064; + t.afii10043 = 1065; + t.afii10044 = 1066; + t.afii10045 = 1067; + t.afii10046 = 1068; + t.afii10047 = 1069; + t.afii10048 = 1070; + t.afii10049 = 1071; + t.afii10050 = 1168; + t.afii10051 = 1026; + t.afii10052 = 1027; + t.afii10053 = 1028; + t.afii10054 = 1029; + t.afii10055 = 1030; + t.afii10056 = 1031; + t.afii10057 = 1032; + t.afii10058 = 1033; + t.afii10059 = 1034; + t.afii10060 = 1035; + t.afii10061 = 1036; + t.afii10062 = 1038; + t.afii10063 = 63172; + t.afii10064 = 63173; + t.afii10065 = 1072; + t.afii10066 = 1073; + t.afii10067 = 1074; + t.afii10068 = 1075; + t.afii10069 = 1076; + t.afii10070 = 1077; + t.afii10071 = 1105; + t.afii10072 = 1078; + t.afii10073 = 1079; + t.afii10074 = 1080; + t.afii10075 = 1081; + t.afii10076 = 1082; + t.afii10077 = 1083; + t.afii10078 = 1084; + t.afii10079 = 1085; + t.afii10080 = 1086; + t.afii10081 = 1087; + t.afii10082 = 1088; + t.afii10083 = 1089; + t.afii10084 = 1090; + t.afii10085 = 1091; + t.afii10086 = 1092; + t.afii10087 = 1093; + t.afii10088 = 1094; + t.afii10089 = 1095; + t.afii10090 = 1096; + t.afii10091 = 1097; + t.afii10092 = 1098; + t.afii10093 = 1099; + t.afii10094 = 1100; + t.afii10095 = 1101; + t.afii10096 = 1102; + t.afii10097 = 1103; + t.afii10098 = 1169; + t.afii10099 = 1106; + t.afii10100 = 1107; + t.afii10101 = 1108; + t.afii10102 = 1109; + t.afii10103 = 1110; + t.afii10104 = 1111; + t.afii10105 = 1112; + t.afii10106 = 1113; + t.afii10107 = 1114; + t.afii10108 = 1115; + t.afii10109 = 1116; + t.afii10110 = 1118; + t.afii10145 = 1039; + t.afii10146 = 1122; + t.afii10147 = 1138; + t.afii10148 = 1140; + t.afii10192 = 63174; + t.afii10193 = 1119; + t.afii10194 = 1123; + t.afii10195 = 1139; + t.afii10196 = 1141; + t.afii10831 = 63175; + t.afii10832 = 63176; + t.afii10846 = 1241; + t.afii299 = 8206; + t.afii300 = 8207; + t.afii301 = 8205; + t.afii57381 = 1642; + t.afii57388 = 1548; + t.afii57392 = 1632; + t.afii57393 = 1633; + t.afii57394 = 1634; + t.afii57395 = 1635; + t.afii57396 = 1636; + t.afii57397 = 1637; + t.afii57398 = 1638; + t.afii57399 = 1639; + t.afii57400 = 1640; + t.afii57401 = 1641; + t.afii57403 = 1563; + t.afii57407 = 1567; + t.afii57409 = 1569; + t.afii57410 = 1570; + t.afii57411 = 1571; + t.afii57412 = 1572; + t.afii57413 = 1573; + t.afii57414 = 1574; + t.afii57415 = 1575; + t.afii57416 = 1576; + t.afii57417 = 1577; + t.afii57418 = 1578; + t.afii57419 = 1579; + t.afii57420 = 1580; + t.afii57421 = 1581; + t.afii57422 = 1582; + t.afii57423 = 1583; + t.afii57424 = 1584; + t.afii57425 = 1585; + t.afii57426 = 1586; + t.afii57427 = 1587; + t.afii57428 = 1588; + t.afii57429 = 1589; + t.afii57430 = 1590; + t.afii57431 = 1591; + t.afii57432 = 1592; + t.afii57433 = 1593; + t.afii57434 = 1594; + t.afii57440 = 1600; + t.afii57441 = 1601; + t.afii57442 = 1602; + t.afii57443 = 1603; + t.afii57444 = 1604; + t.afii57445 = 1605; + t.afii57446 = 1606; + t.afii57448 = 1608; + t.afii57449 = 1609; + t.afii57450 = 1610; + t.afii57451 = 1611; + t.afii57452 = 1612; + t.afii57453 = 1613; + t.afii57454 = 1614; + t.afii57455 = 1615; + t.afii57456 = 1616; + t.afii57457 = 1617; + t.afii57458 = 1618; + t.afii57470 = 1607; + t.afii57505 = 1700; + t.afii57506 = 1662; + t.afii57507 = 1670; + t.afii57508 = 1688; + t.afii57509 = 1711; + t.afii57511 = 1657; + t.afii57512 = 1672; + t.afii57513 = 1681; + t.afii57514 = 1722; + t.afii57519 = 1746; + t.afii57534 = 1749; + t.afii57636 = 8362; + t.afii57645 = 1470; + t.afii57658 = 1475; + t.afii57664 = 1488; + t.afii57665 = 1489; + t.afii57666 = 1490; + t.afii57667 = 1491; + t.afii57668 = 1492; + t.afii57669 = 1493; + t.afii57670 = 1494; + t.afii57671 = 1495; + t.afii57672 = 1496; + t.afii57673 = 1497; + t.afii57674 = 1498; + t.afii57675 = 1499; + t.afii57676 = 1500; + t.afii57677 = 1501; + t.afii57678 = 1502; + t.afii57679 = 1503; + t.afii57680 = 1504; + t.afii57681 = 1505; + t.afii57682 = 1506; + t.afii57683 = 1507; + t.afii57684 = 1508; + t.afii57685 = 1509; + t.afii57686 = 1510; + t.afii57687 = 1511; + t.afii57688 = 1512; + t.afii57689 = 1513; + t.afii57690 = 1514; + t.afii57694 = 64298; + t.afii57695 = 64299; + t.afii57700 = 64331; + t.afii57705 = 64287; + t.afii57716 = 1520; + t.afii57717 = 1521; + t.afii57718 = 1522; + t.afii57723 = 64309; + t.afii57793 = 1460; + t.afii57794 = 1461; + t.afii57795 = 1462; + t.afii57796 = 1467; + t.afii57797 = 1464; + t.afii57798 = 1463; + t.afii57799 = 1456; + t.afii57800 = 1458; + t.afii57801 = 1457; + t.afii57802 = 1459; + t.afii57803 = 1474; + t.afii57804 = 1473; + t.afii57806 = 1465; + t.afii57807 = 1468; + t.afii57839 = 1469; + t.afii57841 = 1471; + t.afii57842 = 1472; + t.afii57929 = 700; + t.afii61248 = 8453; + t.afii61289 = 8467; + t.afii61352 = 8470; + t.afii61573 = 8236; + t.afii61574 = 8237; + t.afii61575 = 8238; + t.afii61664 = 8204; + t.afii63167 = 1645; + t.afii64937 = 701; + t.agrave = 224; + t.agujarati = 2693; + t.agurmukhi = 2565; + t.ahiragana = 12354; + t.ahookabove = 7843; + t.aibengali = 2448; + t.aibopomofo = 12574; + t.aideva = 2320; + t.aiecyrillic = 1237; + t.aigujarati = 2704; + t.aigurmukhi = 2576; + t.aimatragurmukhi = 2632; + t.ainarabic = 1593; + t.ainfinalarabic = 65226; + t.aininitialarabic = 65227; + t.ainmedialarabic = 65228; + t.ainvertedbreve = 515; + t.aivowelsignbengali = 2504; + t.aivowelsigndeva = 2376; + t.aivowelsigngujarati = 2760; + t.akatakana = 12450; + t.akatakanahalfwidth = 65393; + t.akorean = 12623; + t.alef = 1488; + t.alefarabic = 1575; + t.alefdageshhebrew = 64304; + t.aleffinalarabic = 65166; + t.alefhamzaabovearabic = 1571; + t.alefhamzaabovefinalarabic = 65156; + t.alefhamzabelowarabic = 1573; + t.alefhamzabelowfinalarabic = 65160; + t.alefhebrew = 1488; + t.aleflamedhebrew = 64335; + t.alefmaddaabovearabic = 1570; + t.alefmaddaabovefinalarabic = 65154; + t.alefmaksuraarabic = 1609; + t.alefmaksurafinalarabic = 65264; + t.alefmaksurainitialarabic = 65267; + t.alefmaksuramedialarabic = 65268; + t.alefpatahhebrew = 64302; + t.alefqamatshebrew = 64303; + t.aleph = 8501; + t.allequal = 8780; + t.alpha = 945; + t.alphatonos = 940; + t.amacron = 257; + t.amonospace = 65345; + t.ampersand = 38; + t.ampersandmonospace = 65286; + t.ampersandsmall = 63270; + t.amsquare = 13250; + t.anbopomofo = 12578; + t.angbopomofo = 12580; + t.angbracketleft = 12296; + t.angbracketright = 12297; + t.angkhankhuthai = 3674; + t.angle = 8736; + t.anglebracketleft = 12296; + t.anglebracketleftvertical = 65087; + t.anglebracketright = 12297; + t.anglebracketrightvertical = 65088; + t.angleleft = 9001; + t.angleright = 9002; + t.angstrom = 8491; + t.anoteleia = 903; + t.anudattadeva = 2386; + t.anusvarabengali = 2434; + t.anusvaradeva = 2306; + t.anusvaragujarati = 2690; + t.aogonek = 261; + t.apaatosquare = 13056; + t.aparen = 9372; + t.apostrophearmenian = 1370; + t.apostrophemod = 700; + t.apple = 63743; + t.approaches = 8784; + t.approxequal = 8776; + t.approxequalorimage = 8786; + t.approximatelyequal = 8773; + t.araeaekorean = 12686; + t.araeakorean = 12685; + t.arc = 8978; + t.arighthalfring = 7834; + t.aring = 229; + t.aringacute = 507; + t.aringbelow = 7681; + t.arrowboth = 8596; + t.arrowdashdown = 8675; + t.arrowdashleft = 8672; + t.arrowdashright = 8674; + t.arrowdashup = 8673; + t.arrowdblboth = 8660; + t.arrowdbldown = 8659; + t.arrowdblleft = 8656; + t.arrowdblright = 8658; + t.arrowdblup = 8657; + t.arrowdown = 8595; + t.arrowdownleft = 8601; + t.arrowdownright = 8600; + t.arrowdownwhite = 8681; + t.arrowheaddownmod = 709; + t.arrowheadleftmod = 706; + t.arrowheadrightmod = 707; + t.arrowheadupmod = 708; + t.arrowhorizex = 63719; + t.arrowleft = 8592; + t.arrowleftdbl = 8656; + t.arrowleftdblstroke = 8653; + t.arrowleftoverright = 8646; + t.arrowleftwhite = 8678; + t.arrowright = 8594; + t.arrowrightdblstroke = 8655; + t.arrowrightheavy = 10142; + t.arrowrightoverleft = 8644; + t.arrowrightwhite = 8680; + t.arrowtableft = 8676; + t.arrowtabright = 8677; + t.arrowup = 8593; + t.arrowupdn = 8597; + t.arrowupdnbse = 8616; + t.arrowupdownbase = 8616; + t.arrowupleft = 8598; + t.arrowupleftofdown = 8645; + t.arrowupright = 8599; + t.arrowupwhite = 8679; + t.arrowvertex = 63718; + t.asciicircum = 94; + t.asciicircummonospace = 65342; + t.asciitilde = 126; + t.asciitildemonospace = 65374; + t.ascript = 593; + t.ascriptturned = 594; + t.asmallhiragana = 12353; + t.asmallkatakana = 12449; + t.asmallkatakanahalfwidth = 65383; + t.asterisk = 42; + t.asteriskaltonearabic = 1645; + t.asteriskarabic = 1645; + t.asteriskmath = 8727; + t.asteriskmonospace = 65290; + t.asterisksmall = 65121; + t.asterism = 8258; + t.asuperior = 63209; + t.asymptoticallyequal = 8771; + t.at = 64; + t.atilde = 227; + t.atmonospace = 65312; + t.atsmall = 65131; + t.aturned = 592; + t.aubengali = 2452; + t.aubopomofo = 12576; + t.audeva = 2324; + t.augujarati = 2708; + t.augurmukhi = 2580; + t.aulengthmarkbengali = 2519; + t.aumatragurmukhi = 2636; + t.auvowelsignbengali = 2508; + t.auvowelsigndeva = 2380; + t.auvowelsigngujarati = 2764; + t.avagrahadeva = 2365; + t.aybarmenian = 1377; + t.ayin = 1506; + t.ayinaltonehebrew = 64288; + t.ayinhebrew = 1506; + t.b = 98; + t.babengali = 2476; + t.backslash = 92; + t.backslashmonospace = 65340; + t.badeva = 2348; + t.bagujarati = 2732; + t.bagurmukhi = 2604; + t.bahiragana = 12400; + t.bahtthai = 3647; + t.bakatakana = 12496; + t.bar = 124; + t.barmonospace = 65372; + t.bbopomofo = 12549; + t.bcircle = 9425; + t.bdotaccent = 7683; + t.bdotbelow = 7685; + t.beamedsixteenthnotes = 9836; + t.because = 8757; + t.becyrillic = 1073; + t.beharabic = 1576; + t.behfinalarabic = 65168; + t.behinitialarabic = 65169; + t.behiragana = 12409; + t.behmedialarabic = 65170; + t.behmeeminitialarabic = 64671; + t.behmeemisolatedarabic = 64520; + t.behnoonfinalarabic = 64621; + t.bekatakana = 12505; + t.benarmenian = 1378; + t.bet = 1489; + t.beta = 946; + t.betasymbolgreek = 976; + t.betdagesh = 64305; + t.betdageshhebrew = 64305; + t.bethebrew = 1489; + t.betrafehebrew = 64332; + t.bhabengali = 2477; + t.bhadeva = 2349; + t.bhagujarati = 2733; + t.bhagurmukhi = 2605; + t.bhook = 595; + t.bihiragana = 12403; + t.bikatakana = 12499; + t.bilabialclick = 664; + t.bindigurmukhi = 2562; + t.birusquare = 13105; + t.blackcircle = 9679; + t.blackdiamond = 9670; + t.blackdownpointingtriangle = 9660; + t.blackleftpointingpointer = 9668; + t.blackleftpointingtriangle = 9664; + t.blacklenticularbracketleft = 12304; + t.blacklenticularbracketleftvertical = 65083; + t.blacklenticularbracketright = 12305; + t.blacklenticularbracketrightvertical = 65084; + t.blacklowerlefttriangle = 9699; + t.blacklowerrighttriangle = 9698; + t.blackrectangle = 9644; + t.blackrightpointingpointer = 9658; + t.blackrightpointingtriangle = 9654; + t.blacksmallsquare = 9642; + t.blacksmilingface = 9787; + t.blacksquare = 9632; + t.blackstar = 9733; + t.blackupperlefttriangle = 9700; + t.blackupperrighttriangle = 9701; + t.blackuppointingsmalltriangle = 9652; + t.blackuppointingtriangle = 9650; + t.blank = 9251; + t.blinebelow = 7687; + t.block = 9608; + t.bmonospace = 65346; + t.bobaimaithai = 3610; + t.bohiragana = 12412; + t.bokatakana = 12508; + t.bparen = 9373; + t.bqsquare = 13251; + t.braceex = 63732; + t.braceleft = 123; + t.braceleftbt = 63731; + t.braceleftmid = 63730; + t.braceleftmonospace = 65371; + t.braceleftsmall = 65115; + t.bracelefttp = 63729; + t.braceleftvertical = 65079; + t.braceright = 125; + t.bracerightbt = 63742; + t.bracerightmid = 63741; + t.bracerightmonospace = 65373; + t.bracerightsmall = 65116; + t.bracerighttp = 63740; + t.bracerightvertical = 65080; + t.bracketleft = 91; + t.bracketleftbt = 63728; + t.bracketleftex = 63727; + t.bracketleftmonospace = 65339; + t.bracketlefttp = 63726; + t.bracketright = 93; + t.bracketrightbt = 63739; + t.bracketrightex = 63738; + t.bracketrightmonospace = 65341; + t.bracketrighttp = 63737; + t.breve = 728; + t.brevebelowcmb = 814; + t.brevecmb = 774; + t.breveinvertedbelowcmb = 815; + t.breveinvertedcmb = 785; + t.breveinverteddoublecmb = 865; + t.bridgebelowcmb = 810; + t.bridgeinvertedbelowcmb = 826; + t.brokenbar = 166; + t.bstroke = 384; + t.bsuperior = 63210; + t.btopbar = 387; + t.buhiragana = 12406; + t.bukatakana = 12502; + t.bullet = 8226; + t.bulletinverse = 9688; + t.bulletoperator = 8729; + t.bullseye = 9678; + t.c = 99; + t.caarmenian = 1390; + t.cabengali = 2458; + t.cacute = 263; + t.cadeva = 2330; + t.cagujarati = 2714; + t.cagurmukhi = 2586; + t.calsquare = 13192; + t.candrabindubengali = 2433; + t.candrabinducmb = 784; + t.candrabindudeva = 2305; + t.candrabindugujarati = 2689; + t.capslock = 8682; + t.careof = 8453; + t.caron = 711; + t.caronbelowcmb = 812; + t.caroncmb = 780; + t.carriagereturn = 8629; + t.cbopomofo = 12568; + t.ccaron = 269; + t.ccedilla = 231; + t.ccedillaacute = 7689; + t.ccircle = 9426; + t.ccircumflex = 265; + t.ccurl = 597; + t.cdot = 267; + t.cdotaccent = 267; + t.cdsquare = 13253; + t.cedilla = 184; + t.cedillacmb = 807; + t.cent = 162; + t.centigrade = 8451; + t.centinferior = 63199; + t.centmonospace = 65504; + t.centoldstyle = 63394; + t.centsuperior = 63200; + t.chaarmenian = 1401; + t.chabengali = 2459; + t.chadeva = 2331; + t.chagujarati = 2715; + t.chagurmukhi = 2587; + t.chbopomofo = 12564; + t.cheabkhasiancyrillic = 1213; + t.checkmark = 10003; + t.checyrillic = 1095; + t.chedescenderabkhasiancyrillic = 1215; + t.chedescendercyrillic = 1207; + t.chedieresiscyrillic = 1269; + t.cheharmenian = 1395; + t.chekhakassiancyrillic = 1228; + t.cheverticalstrokecyrillic = 1209; + t.chi = 967; + t.chieuchacirclekorean = 12919; + t.chieuchaparenkorean = 12823; + t.chieuchcirclekorean = 12905; + t.chieuchkorean = 12618; + t.chieuchparenkorean = 12809; + t.chochangthai = 3594; + t.chochanthai = 3592; + t.chochingthai = 3593; + t.chochoethai = 3596; + t.chook = 392; + t.cieucacirclekorean = 12918; + t.cieucaparenkorean = 12822; + t.cieuccirclekorean = 12904; + t.cieuckorean = 12616; + t.cieucparenkorean = 12808; + t.cieucuparenkorean = 12828; + t.circle = 9675; + t.circlecopyrt = 169; + t.circlemultiply = 8855; + t.circleot = 8857; + t.circleplus = 8853; + t.circlepostalmark = 12342; + t.circlewithlefthalfblack = 9680; + t.circlewithrighthalfblack = 9681; + t.circumflex = 710; + t.circumflexbelowcmb = 813; + t.circumflexcmb = 770; + t.clear = 8999; + t.clickalveolar = 450; + t.clickdental = 448; + t.clicklateral = 449; + t.clickretroflex = 451; + t.club = 9827; + t.clubsuitblack = 9827; + t.clubsuitwhite = 9831; + t.cmcubedsquare = 13220; + t.cmonospace = 65347; + t.cmsquaredsquare = 13216; + t.coarmenian = 1409; + t.colon = 58; + t.colonmonetary = 8353; + t.colonmonospace = 65306; + t.colonsign = 8353; + t.colonsmall = 65109; + t.colontriangularhalfmod = 721; + t.colontriangularmod = 720; + t.comma = 44; + t.commaabovecmb = 787; + t.commaaboverightcmb = 789; + t.commaaccent = 63171; + t.commaarabic = 1548; + t.commaarmenian = 1373; + t.commainferior = 63201; + t.commamonospace = 65292; + t.commareversedabovecmb = 788; + t.commareversedmod = 701; + t.commasmall = 65104; + t.commasuperior = 63202; + t.commaturnedabovecmb = 786; + t.commaturnedmod = 699; + t.compass = 9788; + t.congruent = 8773; + t.contourintegral = 8750; + t.control = 8963; + t.controlACK = 6; + t.controlBEL = 7; + t.controlBS = 8; + t.controlCAN = 24; + t.controlCR = 13; + t.controlDC1 = 17; + t.controlDC2 = 18; + t.controlDC3 = 19; + t.controlDC4 = 20; + t.controlDEL = 127; + t.controlDLE = 16; + t.controlEM = 25; + t.controlENQ = 5; + t.controlEOT = 4; + t.controlESC = 27; + t.controlETB = 23; + t.controlETX = 3; + t.controlFF = 12; + t.controlFS = 28; + t.controlGS = 29; + t.controlHT = 9; + t.controlLF = 10; + t.controlNAK = 21; + t.controlNULL = 0; + t.controlRS = 30; + t.controlSI = 15; + t.controlSO = 14; + t.controlSOT = 2; + t.controlSTX = 1; + t.controlSUB = 26; + t.controlSYN = 22; + t.controlUS = 31; + t.controlVT = 11; + t.copyright = 169; + t.copyrightsans = 63721; + t.copyrightserif = 63193; + t.cornerbracketleft = 12300; + t.cornerbracketlefthalfwidth = 65378; + t.cornerbracketleftvertical = 65089; + t.cornerbracketright = 12301; + t.cornerbracketrighthalfwidth = 65379; + t.cornerbracketrightvertical = 65090; + t.corporationsquare = 13183; + t.cosquare = 13255; + t.coverkgsquare = 13254; + t.cparen = 9374; + t.cruzeiro = 8354; + t.cstretched = 663; + t.curlyand = 8911; + t.curlyor = 8910; + t.currency = 164; + t.cyrBreve = 63185; + t.cyrFlex = 63186; + t.cyrbreve = 63188; + t.cyrflex = 63189; + t.d = 100; + t.daarmenian = 1380; + t.dabengali = 2470; + t.dadarabic = 1590; + t.dadeva = 2342; + t.dadfinalarabic = 65214; + t.dadinitialarabic = 65215; + t.dadmedialarabic = 65216; + t.dagesh = 1468; + t.dageshhebrew = 1468; + t.dagger = 8224; + t.daggerdbl = 8225; + t.dagujarati = 2726; + t.dagurmukhi = 2598; + t.dahiragana = 12384; + t.dakatakana = 12480; + t.dalarabic = 1583; + t.dalet = 1491; + t.daletdagesh = 64307; + t.daletdageshhebrew = 64307; + t.dalethebrew = 1491; + t.dalfinalarabic = 65194; + t.dammaarabic = 1615; + t.dammalowarabic = 1615; + t.dammatanaltonearabic = 1612; + t.dammatanarabic = 1612; + t.danda = 2404; + t.dargahebrew = 1447; + t.dargalefthebrew = 1447; + t.dasiapneumatacyrilliccmb = 1157; + t.dblGrave = 63187; + t.dblanglebracketleft = 12298; + t.dblanglebracketleftvertical = 65085; + t.dblanglebracketright = 12299; + t.dblanglebracketrightvertical = 65086; + t.dblarchinvertedbelowcmb = 811; + t.dblarrowleft = 8660; + t.dblarrowright = 8658; + t.dbldanda = 2405; + t.dblgrave = 63190; + t.dblgravecmb = 783; + t.dblintegral = 8748; + t.dbllowline = 8215; + t.dbllowlinecmb = 819; + t.dbloverlinecmb = 831; + t.dblprimemod = 698; + t.dblverticalbar = 8214; + t.dblverticallineabovecmb = 782; + t.dbopomofo = 12553; + t.dbsquare = 13256; + t.dcaron = 271; + t.dcedilla = 7697; + t.dcircle = 9427; + t.dcircumflexbelow = 7699; + t.dcroat = 273; + t.ddabengali = 2465; + t.ddadeva = 2337; + t.ddagujarati = 2721; + t.ddagurmukhi = 2593; + t.ddalarabic = 1672; + t.ddalfinalarabic = 64393; + t.dddhadeva = 2396; + t.ddhabengali = 2466; + t.ddhadeva = 2338; + t.ddhagujarati = 2722; + t.ddhagurmukhi = 2594; + t.ddotaccent = 7691; + t.ddotbelow = 7693; + t.decimalseparatorarabic = 1643; + t.decimalseparatorpersian = 1643; + t.decyrillic = 1076; + t.degree = 176; + t.dehihebrew = 1453; + t.dehiragana = 12391; + t.deicoptic = 1007; + t.dekatakana = 12487; + t.deleteleft = 9003; + t.deleteright = 8998; + t.delta = 948; + t.deltaturned = 397; + t.denominatorminusonenumeratorbengali = 2552; + t.dezh = 676; + t.dhabengali = 2471; + t.dhadeva = 2343; + t.dhagujarati = 2727; + t.dhagurmukhi = 2599; + t.dhook = 599; + t.dialytikatonos = 901; + t.dialytikatonoscmb = 836; + t.diamond = 9830; + t.diamondsuitwhite = 9826; + t.dieresis = 168; + t.dieresisacute = 63191; + t.dieresisbelowcmb = 804; + t.dieresiscmb = 776; + t.dieresisgrave = 63192; + t.dieresistonos = 901; + t.dihiragana = 12386; + t.dikatakana = 12482; + t.dittomark = 12291; + t.divide = 247; + t.divides = 8739; + t.divisionslash = 8725; + t.djecyrillic = 1106; + t.dkshade = 9619; + t.dlinebelow = 7695; + t.dlsquare = 13207; + t.dmacron = 273; + t.dmonospace = 65348; + t.dnblock = 9604; + t.dochadathai = 3598; + t.dodekthai = 3604; + t.dohiragana = 12393; + t.dokatakana = 12489; + t.dollar = 36; + t.dollarinferior = 63203; + t.dollarmonospace = 65284; + t.dollaroldstyle = 63268; + t.dollarsmall = 65129; + t.dollarsuperior = 63204; + t.dong = 8363; + t.dorusquare = 13094; + t.dotaccent = 729; + t.dotaccentcmb = 775; + t.dotbelowcmb = 803; + t.dotbelowcomb = 803; + t.dotkatakana = 12539; + t.dotlessi = 305; + t.dotlessj = 63166; + t.dotlessjstrokehook = 644; + t.dotmath = 8901; + t.dottedcircle = 9676; + t.doubleyodpatah = 64287; + t.doubleyodpatahhebrew = 64287; + t.downtackbelowcmb = 798; + t.downtackmod = 725; + t.dparen = 9375; + t.dsuperior = 63211; + t.dtail = 598; + t.dtopbar = 396; + t.duhiragana = 12389; + t.dukatakana = 12485; + t.dz = 499; + t.dzaltone = 675; + t.dzcaron = 454; + t.dzcurl = 677; + t.dzeabkhasiancyrillic = 1249; + t.dzecyrillic = 1109; + t.dzhecyrillic = 1119; + t.e = 101; + t.eacute = 233; + t.earth = 9793; + t.ebengali = 2447; + t.ebopomofo = 12572; + t.ebreve = 277; + t.ecandradeva = 2317; + t.ecandragujarati = 2701; + t.ecandravowelsigndeva = 2373; + t.ecandravowelsigngujarati = 2757; + t.ecaron = 283; + t.ecedillabreve = 7709; + t.echarmenian = 1381; + t.echyiwnarmenian = 1415; + t.ecircle = 9428; + t.ecircumflex = 234; + t.ecircumflexacute = 7871; + t.ecircumflexbelow = 7705; + t.ecircumflexdotbelow = 7879; + t.ecircumflexgrave = 7873; + t.ecircumflexhookabove = 7875; + t.ecircumflextilde = 7877; + t.ecyrillic = 1108; + t.edblgrave = 517; + t.edeva = 2319; + t.edieresis = 235; + t.edot = 279; + t.edotaccent = 279; + t.edotbelow = 7865; + t.eegurmukhi = 2575; + t.eematragurmukhi = 2631; + t.efcyrillic = 1092; + t.egrave = 232; + t.egujarati = 2703; + t.eharmenian = 1383; + t.ehbopomofo = 12573; + t.ehiragana = 12360; + t.ehookabove = 7867; + t.eibopomofo = 12575; + t.eight = 56; + t.eightarabic = 1640; + t.eightbengali = 2542; + t.eightcircle = 9319; + t.eightcircleinversesansserif = 10129; + t.eightdeva = 2414; + t.eighteencircle = 9329; + t.eighteenparen = 9349; + t.eighteenperiod = 9369; + t.eightgujarati = 2798; + t.eightgurmukhi = 2670; + t.eighthackarabic = 1640; + t.eighthangzhou = 12328; + t.eighthnotebeamed = 9835; + t.eightideographicparen = 12839; + t.eightinferior = 8328; + t.eightmonospace = 65304; + t.eightoldstyle = 63288; + t.eightparen = 9339; + t.eightperiod = 9359; + t.eightpersian = 1784; + t.eightroman = 8567; + t.eightsuperior = 8312; + t.eightthai = 3672; + t.einvertedbreve = 519; + t.eiotifiedcyrillic = 1125; + t.ekatakana = 12456; + t.ekatakanahalfwidth = 65396; + t.ekonkargurmukhi = 2676; + t.ekorean = 12628; + t.elcyrillic = 1083; + t.element = 8712; + t.elevencircle = 9322; + t.elevenparen = 9342; + t.elevenperiod = 9362; + t.elevenroman = 8570; + t.ellipsis = 8230; + t.ellipsisvertical = 8942; + t.emacron = 275; + t.emacronacute = 7703; + t.emacrongrave = 7701; + t.emcyrillic = 1084; + t.emdash = 8212; + t.emdashvertical = 65073; + t.emonospace = 65349; + t.emphasismarkarmenian = 1371; + t.emptyset = 8709; + t.enbopomofo = 12579; + t.encyrillic = 1085; + t.endash = 8211; + t.endashvertical = 65074; + t.endescendercyrillic = 1187; + t.eng = 331; + t.engbopomofo = 12581; + t.enghecyrillic = 1189; + t.enhookcyrillic = 1224; + t.enspace = 8194; + t.eogonek = 281; + t.eokorean = 12627; + t.eopen = 603; + t.eopenclosed = 666; + t.eopenreversed = 604; + t.eopenreversedclosed = 606; + t.eopenreversedhook = 605; + t.eparen = 9376; + t.epsilon = 949; + t.epsilontonos = 941; + t.equal = 61; + t.equalmonospace = 65309; + t.equalsmall = 65126; + t.equalsuperior = 8316; + t.equivalence = 8801; + t.erbopomofo = 12582; + t.ercyrillic = 1088; + t.ereversed = 600; + t.ereversedcyrillic = 1101; + t.escyrillic = 1089; + t.esdescendercyrillic = 1195; + t.esh = 643; + t.eshcurl = 646; + t.eshortdeva = 2318; + t.eshortvowelsigndeva = 2374; + t.eshreversedloop = 426; + t.eshsquatreversed = 645; + t.esmallhiragana = 12359; + t.esmallkatakana = 12455; + t.esmallkatakanahalfwidth = 65386; + t.estimated = 8494; + t.esuperior = 63212; + t.eta = 951; + t.etarmenian = 1384; + t.etatonos = 942; + t.eth = 240; + t.etilde = 7869; + t.etildebelow = 7707; + t.etnahtafoukhhebrew = 1425; + t.etnahtafoukhlefthebrew = 1425; + t.etnahtahebrew = 1425; + t.etnahtalefthebrew = 1425; + t.eturned = 477; + t.eukorean = 12641; + t.euro = 8364; + t.evowelsignbengali = 2503; + t.evowelsigndeva = 2375; + t.evowelsigngujarati = 2759; + t.exclam = 33; + t.exclamarmenian = 1372; + t.exclamdbl = 8252; + t.exclamdown = 161; + t.exclamdownsmall = 63393; + t.exclammonospace = 65281; + t.exclamsmall = 63265; + t.existential = 8707; + t.ezh = 658; + t.ezhcaron = 495; + t.ezhcurl = 659; + t.ezhreversed = 441; + t.ezhtail = 442; + t.f = 102; + t.fadeva = 2398; + t.fagurmukhi = 2654; + t.fahrenheit = 8457; + t.fathaarabic = 1614; + t.fathalowarabic = 1614; + t.fathatanarabic = 1611; + t.fbopomofo = 12552; + t.fcircle = 9429; + t.fdotaccent = 7711; + t.feharabic = 1601; + t.feharmenian = 1414; + t.fehfinalarabic = 65234; + t.fehinitialarabic = 65235; + t.fehmedialarabic = 65236; + t.feicoptic = 997; + t.female = 9792; + t.ff = 64256; + t.f_f = 64256; + t.ffi = 64259; + t.f_f_i = 64259; + t.ffl = 64260; + t.f_f_l = 64260; + t.fi = 64257; + t.f_i = 64257; + t.fifteencircle = 9326; + t.fifteenparen = 9346; + t.fifteenperiod = 9366; + t.figuredash = 8210; + t.filledbox = 9632; + t.filledrect = 9644; + t.finalkaf = 1498; + t.finalkafdagesh = 64314; + t.finalkafdageshhebrew = 64314; + t.finalkafhebrew = 1498; + t.finalmem = 1501; + t.finalmemhebrew = 1501; + t.finalnun = 1503; + t.finalnunhebrew = 1503; + t.finalpe = 1507; + t.finalpehebrew = 1507; + t.finaltsadi = 1509; + t.finaltsadihebrew = 1509; + t.firsttonechinese = 713; + t.fisheye = 9673; + t.fitacyrillic = 1139; + t.five = 53; + t.fivearabic = 1637; + t.fivebengali = 2539; + t.fivecircle = 9316; + t.fivecircleinversesansserif = 10126; + t.fivedeva = 2411; + t.fiveeighths = 8541; + t.fivegujarati = 2795; + t.fivegurmukhi = 2667; + t.fivehackarabic = 1637; + t.fivehangzhou = 12325; + t.fiveideographicparen = 12836; + t.fiveinferior = 8325; + t.fivemonospace = 65301; + t.fiveoldstyle = 63285; + t.fiveparen = 9336; + t.fiveperiod = 9356; + t.fivepersian = 1781; + t.fiveroman = 8564; + t.fivesuperior = 8309; + t.fivethai = 3669; + t.fl = 64258; + t.f_l = 64258; + t.florin = 402; + t.fmonospace = 65350; + t.fmsquare = 13209; + t.fofanthai = 3615; + t.fofathai = 3613; + t.fongmanthai = 3663; + t.forall = 8704; + t.four = 52; + t.fourarabic = 1636; + t.fourbengali = 2538; + t.fourcircle = 9315; + t.fourcircleinversesansserif = 10125; + t.fourdeva = 2410; + t.fourgujarati = 2794; + t.fourgurmukhi = 2666; + t.fourhackarabic = 1636; + t.fourhangzhou = 12324; + t.fourideographicparen = 12835; + t.fourinferior = 8324; + t.fourmonospace = 65300; + t.fournumeratorbengali = 2551; + t.fouroldstyle = 63284; + t.fourparen = 9335; + t.fourperiod = 9355; + t.fourpersian = 1780; + t.fourroman = 8563; + t.foursuperior = 8308; + t.fourteencircle = 9325; + t.fourteenparen = 9345; + t.fourteenperiod = 9365; + t.fourthai = 3668; + t.fourthtonechinese = 715; + t.fparen = 9377; + t.fraction = 8260; + t.franc = 8355; + t.g = 103; + t.gabengali = 2455; + t.gacute = 501; + t.gadeva = 2327; + t.gafarabic = 1711; + t.gaffinalarabic = 64403; + t.gafinitialarabic = 64404; + t.gafmedialarabic = 64405; + t.gagujarati = 2711; + t.gagurmukhi = 2583; + t.gahiragana = 12364; + t.gakatakana = 12460; + t.gamma = 947; + t.gammalatinsmall = 611; + t.gammasuperior = 736; + t.gangiacoptic = 1003; + t.gbopomofo = 12557; + t.gbreve = 287; + t.gcaron = 487; + t.gcedilla = 291; + t.gcircle = 9430; + t.gcircumflex = 285; + t.gcommaaccent = 291; + t.gdot = 289; + t.gdotaccent = 289; + t.gecyrillic = 1075; + t.gehiragana = 12370; + t.gekatakana = 12466; + t.geometricallyequal = 8785; + t.gereshaccenthebrew = 1436; + t.gereshhebrew = 1523; + t.gereshmuqdamhebrew = 1437; + t.germandbls = 223; + t.gershayimaccenthebrew = 1438; + t.gershayimhebrew = 1524; + t.getamark = 12307; + t.ghabengali = 2456; + t.ghadarmenian = 1394; + t.ghadeva = 2328; + t.ghagujarati = 2712; + t.ghagurmukhi = 2584; + t.ghainarabic = 1594; + t.ghainfinalarabic = 65230; + t.ghaininitialarabic = 65231; + t.ghainmedialarabic = 65232; + t.ghemiddlehookcyrillic = 1173; + t.ghestrokecyrillic = 1171; + t.gheupturncyrillic = 1169; + t.ghhadeva = 2394; + t.ghhagurmukhi = 2650; + t.ghook = 608; + t.ghzsquare = 13203; + t.gihiragana = 12366; + t.gikatakana = 12462; + t.gimarmenian = 1379; + t.gimel = 1490; + t.gimeldagesh = 64306; + t.gimeldageshhebrew = 64306; + t.gimelhebrew = 1490; + t.gjecyrillic = 1107; + t.glottalinvertedstroke = 446; + t.glottalstop = 660; + t.glottalstopinverted = 662; + t.glottalstopmod = 704; + t.glottalstopreversed = 661; + t.glottalstopreversedmod = 705; + t.glottalstopreversedsuperior = 740; + t.glottalstopstroke = 673; + t.glottalstopstrokereversed = 674; + t.gmacron = 7713; + t.gmonospace = 65351; + t.gohiragana = 12372; + t.gokatakana = 12468; + t.gparen = 9378; + t.gpasquare = 13228; + t.gradient = 8711; + t.grave = 96; + t.gravebelowcmb = 790; + t.gravecmb = 768; + t.gravecomb = 768; + t.gravedeva = 2387; + t.gravelowmod = 718; + t.gravemonospace = 65344; + t.gravetonecmb = 832; + t.greater = 62; + t.greaterequal = 8805; + t.greaterequalorless = 8923; + t.greatermonospace = 65310; + t.greaterorequivalent = 8819; + t.greaterorless = 8823; + t.greateroverequal = 8807; + t.greatersmall = 65125; + t.gscript = 609; + t.gstroke = 485; + t.guhiragana = 12368; + t.guillemotleft = 171; + t.guillemotright = 187; + t.guilsinglleft = 8249; + t.guilsinglright = 8250; + t.gukatakana = 12464; + t.guramusquare = 13080; + t.gysquare = 13257; + t.h = 104; + t.haabkhasiancyrillic = 1193; + t.haaltonearabic = 1729; + t.habengali = 2489; + t.hadescendercyrillic = 1203; + t.hadeva = 2361; + t.hagujarati = 2745; + t.hagurmukhi = 2617; + t.haharabic = 1581; + t.hahfinalarabic = 65186; + t.hahinitialarabic = 65187; + t.hahiragana = 12399; + t.hahmedialarabic = 65188; + t.haitusquare = 13098; + t.hakatakana = 12495; + t.hakatakanahalfwidth = 65418; + t.halantgurmukhi = 2637; + t.hamzaarabic = 1569; + t.hamzalowarabic = 1569; + t.hangulfiller = 12644; + t.hardsigncyrillic = 1098; + t.harpoonleftbarbup = 8636; + t.harpoonrightbarbup = 8640; + t.hasquare = 13258; + t.hatafpatah = 1458; + t.hatafpatah16 = 1458; + t.hatafpatah23 = 1458; + t.hatafpatah2f = 1458; + t.hatafpatahhebrew = 1458; + t.hatafpatahnarrowhebrew = 1458; + t.hatafpatahquarterhebrew = 1458; + t.hatafpatahwidehebrew = 1458; + t.hatafqamats = 1459; + t.hatafqamats1b = 1459; + t.hatafqamats28 = 1459; + t.hatafqamats34 = 1459; + t.hatafqamatshebrew = 1459; + t.hatafqamatsnarrowhebrew = 1459; + t.hatafqamatsquarterhebrew = 1459; + t.hatafqamatswidehebrew = 1459; + t.hatafsegol = 1457; + t.hatafsegol17 = 1457; + t.hatafsegol24 = 1457; + t.hatafsegol30 = 1457; + t.hatafsegolhebrew = 1457; + t.hatafsegolnarrowhebrew = 1457; + t.hatafsegolquarterhebrew = 1457; + t.hatafsegolwidehebrew = 1457; + t.hbar = 295; + t.hbopomofo = 12559; + t.hbrevebelow = 7723; + t.hcedilla = 7721; + t.hcircle = 9431; + t.hcircumflex = 293; + t.hdieresis = 7719; + t.hdotaccent = 7715; + t.hdotbelow = 7717; + t.he = 1492; + t.heart = 9829; + t.heartsuitblack = 9829; + t.heartsuitwhite = 9825; + t.hedagesh = 64308; + t.hedageshhebrew = 64308; + t.hehaltonearabic = 1729; + t.heharabic = 1607; + t.hehebrew = 1492; + t.hehfinalaltonearabic = 64423; + t.hehfinalalttwoarabic = 65258; + t.hehfinalarabic = 65258; + t.hehhamzaabovefinalarabic = 64421; + t.hehhamzaaboveisolatedarabic = 64420; + t.hehinitialaltonearabic = 64424; + t.hehinitialarabic = 65259; + t.hehiragana = 12408; + t.hehmedialaltonearabic = 64425; + t.hehmedialarabic = 65260; + t.heiseierasquare = 13179; + t.hekatakana = 12504; + t.hekatakanahalfwidth = 65421; + t.hekutaarusquare = 13110; + t.henghook = 615; + t.herutusquare = 13113; + t.het = 1495; + t.hethebrew = 1495; + t.hhook = 614; + t.hhooksuperior = 689; + t.hieuhacirclekorean = 12923; + t.hieuhaparenkorean = 12827; + t.hieuhcirclekorean = 12909; + t.hieuhkorean = 12622; + t.hieuhparenkorean = 12813; + t.hihiragana = 12402; + t.hikatakana = 12498; + t.hikatakanahalfwidth = 65419; + t.hiriq = 1460; + t.hiriq14 = 1460; + t.hiriq21 = 1460; + t.hiriq2d = 1460; + t.hiriqhebrew = 1460; + t.hiriqnarrowhebrew = 1460; + t.hiriqquarterhebrew = 1460; + t.hiriqwidehebrew = 1460; + t.hlinebelow = 7830; + t.hmonospace = 65352; + t.hoarmenian = 1392; + t.hohipthai = 3627; + t.hohiragana = 12411; + t.hokatakana = 12507; + t.hokatakanahalfwidth = 65422; + t.holam = 1465; + t.holam19 = 1465; + t.holam26 = 1465; + t.holam32 = 1465; + t.holamhebrew = 1465; + t.holamnarrowhebrew = 1465; + t.holamquarterhebrew = 1465; + t.holamwidehebrew = 1465; + t.honokhukthai = 3630; + t.hookabovecomb = 777; + t.hookcmb = 777; + t.hookpalatalizedbelowcmb = 801; + t.hookretroflexbelowcmb = 802; + t.hoonsquare = 13122; + t.horicoptic = 1001; + t.horizontalbar = 8213; + t.horncmb = 795; + t.hotsprings = 9832; + t.house = 8962; + t.hparen = 9379; + t.hsuperior = 688; + t.hturned = 613; + t.huhiragana = 12405; + t.huiitosquare = 13107; + t.hukatakana = 12501; + t.hukatakanahalfwidth = 65420; + t.hungarumlaut = 733; + t.hungarumlautcmb = 779; + t.hv = 405; + t.hyphen = 45; + t.hypheninferior = 63205; + t.hyphenmonospace = 65293; + t.hyphensmall = 65123; + t.hyphensuperior = 63206; + t.hyphentwo = 8208; + t.i = 105; + t.iacute = 237; + t.iacyrillic = 1103; + t.ibengali = 2439; + t.ibopomofo = 12583; + t.ibreve = 301; + t.icaron = 464; + t.icircle = 9432; + t.icircumflex = 238; + t.icyrillic = 1110; + t.idblgrave = 521; + t.ideographearthcircle = 12943; + t.ideographfirecircle = 12939; + t.ideographicallianceparen = 12863; + t.ideographiccallparen = 12858; + t.ideographiccentrecircle = 12965; + t.ideographicclose = 12294; + t.ideographiccomma = 12289; + t.ideographiccommaleft = 65380; + t.ideographiccongratulationparen = 12855; + t.ideographiccorrectcircle = 12963; + t.ideographicearthparen = 12847; + t.ideographicenterpriseparen = 12861; + t.ideographicexcellentcircle = 12957; + t.ideographicfestivalparen = 12864; + t.ideographicfinancialcircle = 12950; + t.ideographicfinancialparen = 12854; + t.ideographicfireparen = 12843; + t.ideographichaveparen = 12850; + t.ideographichighcircle = 12964; + t.ideographiciterationmark = 12293; + t.ideographiclaborcircle = 12952; + t.ideographiclaborparen = 12856; + t.ideographicleftcircle = 12967; + t.ideographiclowcircle = 12966; + t.ideographicmedicinecircle = 12969; + t.ideographicmetalparen = 12846; + t.ideographicmoonparen = 12842; + t.ideographicnameparen = 12852; + t.ideographicperiod = 12290; + t.ideographicprintcircle = 12958; + t.ideographicreachparen = 12867; + t.ideographicrepresentparen = 12857; + t.ideographicresourceparen = 12862; + t.ideographicrightcircle = 12968; + t.ideographicsecretcircle = 12953; + t.ideographicselfparen = 12866; + t.ideographicsocietyparen = 12851; + t.ideographicspace = 12288; + t.ideographicspecialparen = 12853; + t.ideographicstockparen = 12849; + t.ideographicstudyparen = 12859; + t.ideographicsunparen = 12848; + t.ideographicsuperviseparen = 12860; + t.ideographicwaterparen = 12844; + t.ideographicwoodparen = 12845; + t.ideographiczero = 12295; + t.ideographmetalcircle = 12942; + t.ideographmooncircle = 12938; + t.ideographnamecircle = 12948; + t.ideographsuncircle = 12944; + t.ideographwatercircle = 12940; + t.ideographwoodcircle = 12941; + t.ideva = 2311; + t.idieresis = 239; + t.idieresisacute = 7727; + t.idieresiscyrillic = 1253; + t.idotbelow = 7883; + t.iebrevecyrillic = 1239; + t.iecyrillic = 1077; + t.ieungacirclekorean = 12917; + t.ieungaparenkorean = 12821; + t.ieungcirclekorean = 12903; + t.ieungkorean = 12615; + t.ieungparenkorean = 12807; + t.igrave = 236; + t.igujarati = 2695; + t.igurmukhi = 2567; + t.ihiragana = 12356; + t.ihookabove = 7881; + t.iibengali = 2440; + t.iicyrillic = 1080; + t.iideva = 2312; + t.iigujarati = 2696; + t.iigurmukhi = 2568; + t.iimatragurmukhi = 2624; + t.iinvertedbreve = 523; + t.iishortcyrillic = 1081; + t.iivowelsignbengali = 2496; + t.iivowelsigndeva = 2368; + t.iivowelsigngujarati = 2752; + t.ij = 307; + t.ikatakana = 12452; + t.ikatakanahalfwidth = 65394; + t.ikorean = 12643; + t.ilde = 732; + t.iluyhebrew = 1452; + t.imacron = 299; + t.imacroncyrillic = 1251; + t.imageorapproximatelyequal = 8787; + t.imatragurmukhi = 2623; + t.imonospace = 65353; + t.increment = 8710; + t.infinity = 8734; + t.iniarmenian = 1387; + t.integral = 8747; + t.integralbottom = 8993; + t.integralbt = 8993; + t.integralex = 63733; + t.integraltop = 8992; + t.integraltp = 8992; + t.intersection = 8745; + t.intisquare = 13061; + t.invbullet = 9688; + t.invcircle = 9689; + t.invsmileface = 9787; + t.iocyrillic = 1105; + t.iogonek = 303; + t.iota = 953; + t.iotadieresis = 970; + t.iotadieresistonos = 912; + t.iotalatin = 617; + t.iotatonos = 943; + t.iparen = 9380; + t.irigurmukhi = 2674; + t.ismallhiragana = 12355; + t.ismallkatakana = 12451; + t.ismallkatakanahalfwidth = 65384; + t.issharbengali = 2554; + t.istroke = 616; + t.isuperior = 63213; + t.iterationhiragana = 12445; + t.iterationkatakana = 12541; + t.itilde = 297; + t.itildebelow = 7725; + t.iubopomofo = 12585; + t.iucyrillic = 1102; + t.ivowelsignbengali = 2495; + t.ivowelsigndeva = 2367; + t.ivowelsigngujarati = 2751; + t.izhitsacyrillic = 1141; + t.izhitsadblgravecyrillic = 1143; + t.j = 106; + t.jaarmenian = 1393; + t.jabengali = 2460; + t.jadeva = 2332; + t.jagujarati = 2716; + t.jagurmukhi = 2588; + t.jbopomofo = 12560; + t.jcaron = 496; + t.jcircle = 9433; + t.jcircumflex = 309; + t.jcrossedtail = 669; + t.jdotlessstroke = 607; + t.jecyrillic = 1112; + t.jeemarabic = 1580; + t.jeemfinalarabic = 65182; + t.jeeminitialarabic = 65183; + t.jeemmedialarabic = 65184; + t.jeharabic = 1688; + t.jehfinalarabic = 64395; + t.jhabengali = 2461; + t.jhadeva = 2333; + t.jhagujarati = 2717; + t.jhagurmukhi = 2589; + t.jheharmenian = 1403; + t.jis = 12292; + t.jmonospace = 65354; + t.jparen = 9381; + t.jsuperior = 690; + t.k = 107; + t.kabashkircyrillic = 1185; + t.kabengali = 2453; + t.kacute = 7729; + t.kacyrillic = 1082; + t.kadescendercyrillic = 1179; + t.kadeva = 2325; + t.kaf = 1499; + t.kafarabic = 1603; + t.kafdagesh = 64315; + t.kafdageshhebrew = 64315; + t.kaffinalarabic = 65242; + t.kafhebrew = 1499; + t.kafinitialarabic = 65243; + t.kafmedialarabic = 65244; + t.kafrafehebrew = 64333; + t.kagujarati = 2709; + t.kagurmukhi = 2581; + t.kahiragana = 12363; + t.kahookcyrillic = 1220; + t.kakatakana = 12459; + t.kakatakanahalfwidth = 65398; + t.kappa = 954; + t.kappasymbolgreek = 1008; + t.kapyeounmieumkorean = 12657; + t.kapyeounphieuphkorean = 12676; + t.kapyeounpieupkorean = 12664; + t.kapyeounssangpieupkorean = 12665; + t.karoriisquare = 13069; + t.kashidaautoarabic = 1600; + t.kashidaautonosidebearingarabic = 1600; + t.kasmallkatakana = 12533; + t.kasquare = 13188; + t.kasraarabic = 1616; + t.kasratanarabic = 1613; + t.kastrokecyrillic = 1183; + t.katahiraprolongmarkhalfwidth = 65392; + t.kaverticalstrokecyrillic = 1181; + t.kbopomofo = 12558; + t.kcalsquare = 13193; + t.kcaron = 489; + t.kcedilla = 311; + t.kcircle = 9434; + t.kcommaaccent = 311; + t.kdotbelow = 7731; + t.keharmenian = 1412; + t.kehiragana = 12369; + t.kekatakana = 12465; + t.kekatakanahalfwidth = 65401; + t.kenarmenian = 1391; + t.kesmallkatakana = 12534; + t.kgreenlandic = 312; + t.khabengali = 2454; + t.khacyrillic = 1093; + t.khadeva = 2326; + t.khagujarati = 2710; + t.khagurmukhi = 2582; + t.khaharabic = 1582; + t.khahfinalarabic = 65190; + t.khahinitialarabic = 65191; + t.khahmedialarabic = 65192; + t.kheicoptic = 999; + t.khhadeva = 2393; + t.khhagurmukhi = 2649; + t.khieukhacirclekorean = 12920; + t.khieukhaparenkorean = 12824; + t.khieukhcirclekorean = 12906; + t.khieukhkorean = 12619; + t.khieukhparenkorean = 12810; + t.khokhaithai = 3586; + t.khokhonthai = 3589; + t.khokhuatthai = 3587; + t.khokhwaithai = 3588; + t.khomutthai = 3675; + t.khook = 409; + t.khorakhangthai = 3590; + t.khzsquare = 13201; + t.kihiragana = 12365; + t.kikatakana = 12461; + t.kikatakanahalfwidth = 65399; + t.kiroguramusquare = 13077; + t.kiromeetorusquare = 13078; + t.kirosquare = 13076; + t.kiyeokacirclekorean = 12910; + t.kiyeokaparenkorean = 12814; + t.kiyeokcirclekorean = 12896; + t.kiyeokkorean = 12593; + t.kiyeokparenkorean = 12800; + t.kiyeoksioskorean = 12595; + t.kjecyrillic = 1116; + t.klinebelow = 7733; + t.klsquare = 13208; + t.kmcubedsquare = 13222; + t.kmonospace = 65355; + t.kmsquaredsquare = 13218; + t.kohiragana = 12371; + t.kohmsquare = 13248; + t.kokaithai = 3585; + t.kokatakana = 12467; + t.kokatakanahalfwidth = 65402; + t.kooposquare = 13086; + t.koppacyrillic = 1153; + t.koreanstandardsymbol = 12927; + t.koroniscmb = 835; + t.kparen = 9382; + t.kpasquare = 13226; + t.ksicyrillic = 1135; + t.ktsquare = 13263; + t.kturned = 670; + t.kuhiragana = 12367; + t.kukatakana = 12463; + t.kukatakanahalfwidth = 65400; + t.kvsquare = 13240; + t.kwsquare = 13246; + t.l = 108; + t.labengali = 2482; + t.lacute = 314; + t.ladeva = 2354; + t.lagujarati = 2738; + t.lagurmukhi = 2610; + t.lakkhangyaothai = 3653; + t.lamaleffinalarabic = 65276; + t.lamalefhamzaabovefinalarabic = 65272; + t.lamalefhamzaaboveisolatedarabic = 65271; + t.lamalefhamzabelowfinalarabic = 65274; + t.lamalefhamzabelowisolatedarabic = 65273; + t.lamalefisolatedarabic = 65275; + t.lamalefmaddaabovefinalarabic = 65270; + t.lamalefmaddaaboveisolatedarabic = 65269; + t.lamarabic = 1604; + t.lambda = 955; + t.lambdastroke = 411; + t.lamed = 1500; + t.lameddagesh = 64316; + t.lameddageshhebrew = 64316; + t.lamedhebrew = 1500; + t.lamfinalarabic = 65246; + t.lamhahinitialarabic = 64714; + t.laminitialarabic = 65247; + t.lamjeeminitialarabic = 64713; + t.lamkhahinitialarabic = 64715; + t.lamlamhehisolatedarabic = 65010; + t.lammedialarabic = 65248; + t.lammeemhahinitialarabic = 64904; + t.lammeeminitialarabic = 64716; + t.largecircle = 9711; + t.lbar = 410; + t.lbelt = 620; + t.lbopomofo = 12556; + t.lcaron = 318; + t.lcedilla = 316; + t.lcircle = 9435; + t.lcircumflexbelow = 7741; + t.lcommaaccent = 316; + t.ldot = 320; + t.ldotaccent = 320; + t.ldotbelow = 7735; + t.ldotbelowmacron = 7737; + t.leftangleabovecmb = 794; + t.lefttackbelowcmb = 792; + t.less = 60; + t.lessequal = 8804; + t.lessequalorgreater = 8922; + t.lessmonospace = 65308; + t.lessorequivalent = 8818; + t.lessorgreater = 8822; + t.lessoverequal = 8806; + t.lesssmall = 65124; + t.lezh = 622; + t.lfblock = 9612; + t.lhookretroflex = 621; + t.lira = 8356; + t.liwnarmenian = 1388; + t.lj = 457; + t.ljecyrillic = 1113; + t.ll = 63168; + t.lladeva = 2355; + t.llagujarati = 2739; + t.llinebelow = 7739; + t.llladeva = 2356; + t.llvocalicbengali = 2529; + t.llvocalicdeva = 2401; + t.llvocalicvowelsignbengali = 2531; + t.llvocalicvowelsigndeva = 2403; + t.lmiddletilde = 619; + t.lmonospace = 65356; + t.lmsquare = 13264; + t.lochulathai = 3628; + t.logicaland = 8743; + t.logicalnot = 172; + t.logicalnotreversed = 8976; + t.logicalor = 8744; + t.lolingthai = 3621; + t.longs = 383; + t.lowlinecenterline = 65102; + t.lowlinecmb = 818; + t.lowlinedashed = 65101; + t.lozenge = 9674; + t.lparen = 9383; + t.lslash = 322; + t.lsquare = 8467; + t.lsuperior = 63214; + t.ltshade = 9617; + t.luthai = 3622; + t.lvocalicbengali = 2444; + t.lvocalicdeva = 2316; + t.lvocalicvowelsignbengali = 2530; + t.lvocalicvowelsigndeva = 2402; + t.lxsquare = 13267; + t.m = 109; + t.mabengali = 2478; + t.macron = 175; + t.macronbelowcmb = 817; + t.macroncmb = 772; + t.macronlowmod = 717; + t.macronmonospace = 65507; + t.macute = 7743; + t.madeva = 2350; + t.magujarati = 2734; + t.magurmukhi = 2606; + t.mahapakhhebrew = 1444; + t.mahapakhlefthebrew = 1444; + t.mahiragana = 12414; + t.maichattawalowleftthai = 63637; + t.maichattawalowrightthai = 63636; + t.maichattawathai = 3659; + t.maichattawaupperleftthai = 63635; + t.maieklowleftthai = 63628; + t.maieklowrightthai = 63627; + t.maiekthai = 3656; + t.maiekupperleftthai = 63626; + t.maihanakatleftthai = 63620; + t.maihanakatthai = 3633; + t.maitaikhuleftthai = 63625; + t.maitaikhuthai = 3655; + t.maitholowleftthai = 63631; + t.maitholowrightthai = 63630; + t.maithothai = 3657; + t.maithoupperleftthai = 63629; + t.maitrilowleftthai = 63634; + t.maitrilowrightthai = 63633; + t.maitrithai = 3658; + t.maitriupperleftthai = 63632; + t.maiyamokthai = 3654; + t.makatakana = 12510; + t.makatakanahalfwidth = 65423; + t.male = 9794; + t.mansyonsquare = 13127; + t.maqafhebrew = 1470; + t.mars = 9794; + t.masoracirclehebrew = 1455; + t.masquare = 13187; + t.mbopomofo = 12551; + t.mbsquare = 13268; + t.mcircle = 9436; + t.mcubedsquare = 13221; + t.mdotaccent = 7745; + t.mdotbelow = 7747; + t.meemarabic = 1605; + t.meemfinalarabic = 65250; + t.meeminitialarabic = 65251; + t.meemmedialarabic = 65252; + t.meemmeeminitialarabic = 64721; + t.meemmeemisolatedarabic = 64584; + t.meetorusquare = 13133; + t.mehiragana = 12417; + t.meizierasquare = 13182; + t.mekatakana = 12513; + t.mekatakanahalfwidth = 65426; + t.mem = 1502; + t.memdagesh = 64318; + t.memdageshhebrew = 64318; + t.memhebrew = 1502; + t.menarmenian = 1396; + t.merkhahebrew = 1445; + t.merkhakefulahebrew = 1446; + t.merkhakefulalefthebrew = 1446; + t.merkhalefthebrew = 1445; + t.mhook = 625; + t.mhzsquare = 13202; + t.middledotkatakanahalfwidth = 65381; + t.middot = 183; + t.mieumacirclekorean = 12914; + t.mieumaparenkorean = 12818; + t.mieumcirclekorean = 12900; + t.mieumkorean = 12609; + t.mieumpansioskorean = 12656; + t.mieumparenkorean = 12804; + t.mieumpieupkorean = 12654; + t.mieumsioskorean = 12655; + t.mihiragana = 12415; + t.mikatakana = 12511; + t.mikatakanahalfwidth = 65424; + t.minus = 8722; + t.minusbelowcmb = 800; + t.minuscircle = 8854; + t.minusmod = 727; + t.minusplus = 8723; + t.minute = 8242; + t.miribaarusquare = 13130; + t.mirisquare = 13129; + t.mlonglegturned = 624; + t.mlsquare = 13206; + t.mmcubedsquare = 13219; + t.mmonospace = 65357; + t.mmsquaredsquare = 13215; + t.mohiragana = 12418; + t.mohmsquare = 13249; + t.mokatakana = 12514; + t.mokatakanahalfwidth = 65427; + t.molsquare = 13270; + t.momathai = 3617; + t.moverssquare = 13223; + t.moverssquaredsquare = 13224; + t.mparen = 9384; + t.mpasquare = 13227; + t.mssquare = 13235; + t.msuperior = 63215; + t.mturned = 623; + t.mu = 181; + t.mu1 = 181; + t.muasquare = 13186; + t.muchgreater = 8811; + t.muchless = 8810; + t.mufsquare = 13196; + t.mugreek = 956; + t.mugsquare = 13197; + t.muhiragana = 12416; + t.mukatakana = 12512; + t.mukatakanahalfwidth = 65425; + t.mulsquare = 13205; + t.multiply = 215; + t.mumsquare = 13211; + t.munahhebrew = 1443; + t.munahlefthebrew = 1443; + t.musicalnote = 9834; + t.musicalnotedbl = 9835; + t.musicflatsign = 9837; + t.musicsharpsign = 9839; + t.mussquare = 13234; + t.muvsquare = 13238; + t.muwsquare = 13244; + t.mvmegasquare = 13241; + t.mvsquare = 13239; + t.mwmegasquare = 13247; + t.mwsquare = 13245; + t.n = 110; + t.nabengali = 2472; + t.nabla = 8711; + t.nacute = 324; + t.nadeva = 2344; + t.nagujarati = 2728; + t.nagurmukhi = 2600; + t.nahiragana = 12394; + t.nakatakana = 12490; + t.nakatakanahalfwidth = 65413; + t.napostrophe = 329; + t.nasquare = 13185; + t.nbopomofo = 12555; + t.nbspace = 160; + t.ncaron = 328; + t.ncedilla = 326; + t.ncircle = 9437; + t.ncircumflexbelow = 7755; + t.ncommaaccent = 326; + t.ndotaccent = 7749; + t.ndotbelow = 7751; + t.nehiragana = 12397; + t.nekatakana = 12493; + t.nekatakanahalfwidth = 65416; + t.newsheqelsign = 8362; + t.nfsquare = 13195; + t.ngabengali = 2457; + t.ngadeva = 2329; + t.ngagujarati = 2713; + t.ngagurmukhi = 2585; + t.ngonguthai = 3591; + t.nhiragana = 12435; + t.nhookleft = 626; + t.nhookretroflex = 627; + t.nieunacirclekorean = 12911; + t.nieunaparenkorean = 12815; + t.nieuncieuckorean = 12597; + t.nieuncirclekorean = 12897; + t.nieunhieuhkorean = 12598; + t.nieunkorean = 12596; + t.nieunpansioskorean = 12648; + t.nieunparenkorean = 12801; + t.nieunsioskorean = 12647; + t.nieuntikeutkorean = 12646; + t.nihiragana = 12395; + t.nikatakana = 12491; + t.nikatakanahalfwidth = 65414; + t.nikhahitleftthai = 63641; + t.nikhahitthai = 3661; + t.nine = 57; + t.ninearabic = 1641; + t.ninebengali = 2543; + t.ninecircle = 9320; + t.ninecircleinversesansserif = 10130; + t.ninedeva = 2415; + t.ninegujarati = 2799; + t.ninegurmukhi = 2671; + t.ninehackarabic = 1641; + t.ninehangzhou = 12329; + t.nineideographicparen = 12840; + t.nineinferior = 8329; + t.ninemonospace = 65305; + t.nineoldstyle = 63289; + t.nineparen = 9340; + t.nineperiod = 9360; + t.ninepersian = 1785; + t.nineroman = 8568; + t.ninesuperior = 8313; + t.nineteencircle = 9330; + t.nineteenparen = 9350; + t.nineteenperiod = 9370; + t.ninethai = 3673; + t.nj = 460; + t.njecyrillic = 1114; + t.nkatakana = 12531; + t.nkatakanahalfwidth = 65437; + t.nlegrightlong = 414; + t.nlinebelow = 7753; + t.nmonospace = 65358; + t.nmsquare = 13210; + t.nnabengali = 2467; + t.nnadeva = 2339; + t.nnagujarati = 2723; + t.nnagurmukhi = 2595; + t.nnnadeva = 2345; + t.nohiragana = 12398; + t.nokatakana = 12494; + t.nokatakanahalfwidth = 65417; + t.nonbreakingspace = 160; + t.nonenthai = 3603; + t.nonuthai = 3609; + t.noonarabic = 1606; + t.noonfinalarabic = 65254; + t.noonghunnaarabic = 1722; + t.noonghunnafinalarabic = 64415; + t.nooninitialarabic = 65255; + t.noonjeeminitialarabic = 64722; + t.noonjeemisolatedarabic = 64587; + t.noonmedialarabic = 65256; + t.noonmeeminitialarabic = 64725; + t.noonmeemisolatedarabic = 64590; + t.noonnoonfinalarabic = 64653; + t.notcontains = 8716; + t.notelement = 8713; + t.notelementof = 8713; + t.notequal = 8800; + t.notgreater = 8815; + t.notgreaternorequal = 8817; + t.notgreaternorless = 8825; + t.notidentical = 8802; + t.notless = 8814; + t.notlessnorequal = 8816; + t.notparallel = 8742; + t.notprecedes = 8832; + t.notsubset = 8836; + t.notsucceeds = 8833; + t.notsuperset = 8837; + t.nowarmenian = 1398; + t.nparen = 9385; + t.nssquare = 13233; + t.nsuperior = 8319; + t.ntilde = 241; + t.nu = 957; + t.nuhiragana = 12396; + t.nukatakana = 12492; + t.nukatakanahalfwidth = 65415; + t.nuktabengali = 2492; + t.nuktadeva = 2364; + t.nuktagujarati = 2748; + t.nuktagurmukhi = 2620; + t.numbersign = 35; + t.numbersignmonospace = 65283; + t.numbersignsmall = 65119; + t.numeralsigngreek = 884; + t.numeralsignlowergreek = 885; + t.numero = 8470; + t.nun = 1504; + t.nundagesh = 64320; + t.nundageshhebrew = 64320; + t.nunhebrew = 1504; + t.nvsquare = 13237; + t.nwsquare = 13243; + t.nyabengali = 2462; + t.nyadeva = 2334; + t.nyagujarati = 2718; + t.nyagurmukhi = 2590; + t.o = 111; + t.oacute = 243; + t.oangthai = 3629; + t.obarred = 629; + t.obarredcyrillic = 1257; + t.obarreddieresiscyrillic = 1259; + t.obengali = 2451; + t.obopomofo = 12571; + t.obreve = 335; + t.ocandradeva = 2321; + t.ocandragujarati = 2705; + t.ocandravowelsigndeva = 2377; + t.ocandravowelsigngujarati = 2761; + t.ocaron = 466; + t.ocircle = 9438; + t.ocircumflex = 244; + t.ocircumflexacute = 7889; + t.ocircumflexdotbelow = 7897; + t.ocircumflexgrave = 7891; + t.ocircumflexhookabove = 7893; + t.ocircumflextilde = 7895; + t.ocyrillic = 1086; + t.odblacute = 337; + t.odblgrave = 525; + t.odeva = 2323; + t.odieresis = 246; + t.odieresiscyrillic = 1255; + t.odotbelow = 7885; + t.oe = 339; + t.oekorean = 12634; + t.ogonek = 731; + t.ogonekcmb = 808; + t.ograve = 242; + t.ogujarati = 2707; + t.oharmenian = 1413; + t.ohiragana = 12362; + t.ohookabove = 7887; + t.ohorn = 417; + t.ohornacute = 7899; + t.ohorndotbelow = 7907; + t.ohorngrave = 7901; + t.ohornhookabove = 7903; + t.ohorntilde = 7905; + t.ohungarumlaut = 337; + t.oi = 419; + t.oinvertedbreve = 527; + t.okatakana = 12458; + t.okatakanahalfwidth = 65397; + t.okorean = 12631; + t.olehebrew = 1451; + t.omacron = 333; + t.omacronacute = 7763; + t.omacrongrave = 7761; + t.omdeva = 2384; + t.omega = 969; + t.omega1 = 982; + t.omegacyrillic = 1121; + t.omegalatinclosed = 631; + t.omegaroundcyrillic = 1147; + t.omegatitlocyrillic = 1149; + t.omegatonos = 974; + t.omgujarati = 2768; + t.omicron = 959; + t.omicrontonos = 972; + t.omonospace = 65359; + t.one = 49; + t.onearabic = 1633; + t.onebengali = 2535; + t.onecircle = 9312; + t.onecircleinversesansserif = 10122; + t.onedeva = 2407; + t.onedotenleader = 8228; + t.oneeighth = 8539; + t.onefitted = 63196; + t.onegujarati = 2791; + t.onegurmukhi = 2663; + t.onehackarabic = 1633; + t.onehalf = 189; + t.onehangzhou = 12321; + t.oneideographicparen = 12832; + t.oneinferior = 8321; + t.onemonospace = 65297; + t.onenumeratorbengali = 2548; + t.oneoldstyle = 63281; + t.oneparen = 9332; + t.oneperiod = 9352; + t.onepersian = 1777; + t.onequarter = 188; + t.oneroman = 8560; + t.onesuperior = 185; + t.onethai = 3665; + t.onethird = 8531; + t.oogonek = 491; + t.oogonekmacron = 493; + t.oogurmukhi = 2579; + t.oomatragurmukhi = 2635; + t.oopen = 596; + t.oparen = 9386; + t.openbullet = 9702; + t.option = 8997; + t.ordfeminine = 170; + t.ordmasculine = 186; + t.orthogonal = 8735; + t.oshortdeva = 2322; + t.oshortvowelsigndeva = 2378; + t.oslash = 248; + t.oslashacute = 511; + t.osmallhiragana = 12361; + t.osmallkatakana = 12457; + t.osmallkatakanahalfwidth = 65387; + t.ostrokeacute = 511; + t.osuperior = 63216; + t.otcyrillic = 1151; + t.otilde = 245; + t.otildeacute = 7757; + t.otildedieresis = 7759; + t.oubopomofo = 12577; + t.overline = 8254; + t.overlinecenterline = 65098; + t.overlinecmb = 773; + t.overlinedashed = 65097; + t.overlinedblwavy = 65100; + t.overlinewavy = 65099; + t.overscore = 175; + t.ovowelsignbengali = 2507; + t.ovowelsigndeva = 2379; + t.ovowelsigngujarati = 2763; + t.p = 112; + t.paampssquare = 13184; + t.paasentosquare = 13099; + t.pabengali = 2474; + t.pacute = 7765; + t.padeva = 2346; + t.pagedown = 8671; + t.pageup = 8670; + t.pagujarati = 2730; + t.pagurmukhi = 2602; + t.pahiragana = 12401; + t.paiyannoithai = 3631; + t.pakatakana = 12497; + t.palatalizationcyrilliccmb = 1156; + t.palochkacyrillic = 1216; + t.pansioskorean = 12671; + t.paragraph = 182; + t.parallel = 8741; + t.parenleft = 40; + t.parenleftaltonearabic = 64830; + t.parenleftbt = 63725; + t.parenleftex = 63724; + t.parenleftinferior = 8333; + t.parenleftmonospace = 65288; + t.parenleftsmall = 65113; + t.parenleftsuperior = 8317; + t.parenlefttp = 63723; + t.parenleftvertical = 65077; + t.parenright = 41; + t.parenrightaltonearabic = 64831; + t.parenrightbt = 63736; + t.parenrightex = 63735; + t.parenrightinferior = 8334; + t.parenrightmonospace = 65289; + t.parenrightsmall = 65114; + t.parenrightsuperior = 8318; + t.parenrighttp = 63734; + t.parenrightvertical = 65078; + t.partialdiff = 8706; + t.paseqhebrew = 1472; + t.pashtahebrew = 1433; + t.pasquare = 13225; + t.patah = 1463; + t.patah11 = 1463; + t.patah1d = 1463; + t.patah2a = 1463; + t.patahhebrew = 1463; + t.patahnarrowhebrew = 1463; + t.patahquarterhebrew = 1463; + t.patahwidehebrew = 1463; + t.pazerhebrew = 1441; + t.pbopomofo = 12550; + t.pcircle = 9439; + t.pdotaccent = 7767; + t.pe = 1508; + t.pecyrillic = 1087; + t.pedagesh = 64324; + t.pedageshhebrew = 64324; + t.peezisquare = 13115; + t.pefinaldageshhebrew = 64323; + t.peharabic = 1662; + t.peharmenian = 1402; + t.pehebrew = 1508; + t.pehfinalarabic = 64343; + t.pehinitialarabic = 64344; + t.pehiragana = 12410; + t.pehmedialarabic = 64345; + t.pekatakana = 12506; + t.pemiddlehookcyrillic = 1191; + t.perafehebrew = 64334; + t.percent = 37; + t.percentarabic = 1642; + t.percentmonospace = 65285; + t.percentsmall = 65130; + t.period = 46; + t.periodarmenian = 1417; + t.periodcentered = 183; + t.periodhalfwidth = 65377; + t.periodinferior = 63207; + t.periodmonospace = 65294; + t.periodsmall = 65106; + t.periodsuperior = 63208; + t.perispomenigreekcmb = 834; + t.perpendicular = 8869; + t.perthousand = 8240; + t.peseta = 8359; + t.pfsquare = 13194; + t.phabengali = 2475; + t.phadeva = 2347; + t.phagujarati = 2731; + t.phagurmukhi = 2603; + t.phi = 966; + t.phi1 = 981; + t.phieuphacirclekorean = 12922; + t.phieuphaparenkorean = 12826; + t.phieuphcirclekorean = 12908; + t.phieuphkorean = 12621; + t.phieuphparenkorean = 12812; + t.philatin = 632; + t.phinthuthai = 3642; + t.phisymbolgreek = 981; + t.phook = 421; + t.phophanthai = 3614; + t.phophungthai = 3612; + t.phosamphaothai = 3616; + t.pi = 960; + t.pieupacirclekorean = 12915; + t.pieupaparenkorean = 12819; + t.pieupcieuckorean = 12662; + t.pieupcirclekorean = 12901; + t.pieupkiyeokkorean = 12658; + t.pieupkorean = 12610; + t.pieupparenkorean = 12805; + t.pieupsioskiyeokkorean = 12660; + t.pieupsioskorean = 12612; + t.pieupsiostikeutkorean = 12661; + t.pieupthieuthkorean = 12663; + t.pieuptikeutkorean = 12659; + t.pihiragana = 12404; + t.pikatakana = 12500; + t.pisymbolgreek = 982; + t.piwrarmenian = 1411; + t.planckover2pi = 8463; + t.planckover2pi1 = 8463; + t.plus = 43; + t.plusbelowcmb = 799; + t.pluscircle = 8853; + t.plusminus = 177; + t.plusmod = 726; + t.plusmonospace = 65291; + t.plussmall = 65122; + t.plussuperior = 8314; + t.pmonospace = 65360; + t.pmsquare = 13272; + t.pohiragana = 12413; + t.pointingindexdownwhite = 9759; + t.pointingindexleftwhite = 9756; + t.pointingindexrightwhite = 9758; + t.pointingindexupwhite = 9757; + t.pokatakana = 12509; + t.poplathai = 3611; + t.postalmark = 12306; + t.postalmarkface = 12320; + t.pparen = 9387; + t.precedes = 8826; + t.prescription = 8478; + t.primemod = 697; + t.primereversed = 8245; + t.product = 8719; + t.projective = 8965; + t.prolongedkana = 12540; + t.propellor = 8984; + t.propersubset = 8834; + t.propersuperset = 8835; + t.proportion = 8759; + t.proportional = 8733; + t.psi = 968; + t.psicyrillic = 1137; + t.psilipneumatacyrilliccmb = 1158; + t.pssquare = 13232; + t.puhiragana = 12407; + t.pukatakana = 12503; + t.pvsquare = 13236; + t.pwsquare = 13242; + t.q = 113; + t.qadeva = 2392; + t.qadmahebrew = 1448; + t.qafarabic = 1602; + t.qaffinalarabic = 65238; + t.qafinitialarabic = 65239; + t.qafmedialarabic = 65240; + t.qamats = 1464; + t.qamats10 = 1464; + t.qamats1a = 1464; + t.qamats1c = 1464; + t.qamats27 = 1464; + t.qamats29 = 1464; + t.qamats33 = 1464; + t.qamatsde = 1464; + t.qamatshebrew = 1464; + t.qamatsnarrowhebrew = 1464; + t.qamatsqatanhebrew = 1464; + t.qamatsqatannarrowhebrew = 1464; + t.qamatsqatanquarterhebrew = 1464; + t.qamatsqatanwidehebrew = 1464; + t.qamatsquarterhebrew = 1464; + t.qamatswidehebrew = 1464; + t.qarneyparahebrew = 1439; + t.qbopomofo = 12561; + t.qcircle = 9440; + t.qhook = 672; + t.qmonospace = 65361; + t.qof = 1511; + t.qofdagesh = 64327; + t.qofdageshhebrew = 64327; + t.qofhebrew = 1511; + t.qparen = 9388; + t.quarternote = 9833; + t.qubuts = 1467; + t.qubuts18 = 1467; + t.qubuts25 = 1467; + t.qubuts31 = 1467; + t.qubutshebrew = 1467; + t.qubutsnarrowhebrew = 1467; + t.qubutsquarterhebrew = 1467; + t.qubutswidehebrew = 1467; + t.question = 63; + t.questionarabic = 1567; + t.questionarmenian = 1374; + t.questiondown = 191; + t.questiondownsmall = 63423; + t.questiongreek = 894; + t.questionmonospace = 65311; + t.questionsmall = 63295; + t.quotedbl = 34; + t.quotedblbase = 8222; + t.quotedblleft = 8220; + t.quotedblmonospace = 65282; + t.quotedblprime = 12318; + t.quotedblprimereversed = 12317; + t.quotedblright = 8221; + t.quoteleft = 8216; + t.quoteleftreversed = 8219; + t.quotereversed = 8219; + t.quoteright = 8217; + t.quoterightn = 329; + t.quotesinglbase = 8218; + t.quotesingle = 39; + t.quotesinglemonospace = 65287; + t.r = 114; + t.raarmenian = 1404; + t.rabengali = 2480; + t.racute = 341; + t.radeva = 2352; + t.radical = 8730; + t.radicalex = 63717; + t.radoverssquare = 13230; + t.radoverssquaredsquare = 13231; + t.radsquare = 13229; + t.rafe = 1471; + t.rafehebrew = 1471; + t.ragujarati = 2736; + t.ragurmukhi = 2608; + t.rahiragana = 12425; + t.rakatakana = 12521; + t.rakatakanahalfwidth = 65431; + t.ralowerdiagonalbengali = 2545; + t.ramiddlediagonalbengali = 2544; + t.ramshorn = 612; + t.ratio = 8758; + t.rbopomofo = 12566; + t.rcaron = 345; + t.rcedilla = 343; + t.rcircle = 9441; + t.rcommaaccent = 343; + t.rdblgrave = 529; + t.rdotaccent = 7769; + t.rdotbelow = 7771; + t.rdotbelowmacron = 7773; + t.referencemark = 8251; + t.reflexsubset = 8838; + t.reflexsuperset = 8839; + t.registered = 174; + t.registersans = 63720; + t.registerserif = 63194; + t.reharabic = 1585; + t.reharmenian = 1408; + t.rehfinalarabic = 65198; + t.rehiragana = 12428; + t.rekatakana = 12524; + t.rekatakanahalfwidth = 65434; + t.resh = 1512; + t.reshdageshhebrew = 64328; + t.reshhebrew = 1512; + t.reversedtilde = 8765; + t.reviahebrew = 1431; + t.reviamugrashhebrew = 1431; + t.revlogicalnot = 8976; + t.rfishhook = 638; + t.rfishhookreversed = 639; + t.rhabengali = 2525; + t.rhadeva = 2397; + t.rho = 961; + t.rhook = 637; + t.rhookturned = 635; + t.rhookturnedsuperior = 693; + t.rhosymbolgreek = 1009; + t.rhotichookmod = 734; + t.rieulacirclekorean = 12913; + t.rieulaparenkorean = 12817; + t.rieulcirclekorean = 12899; + t.rieulhieuhkorean = 12608; + t.rieulkiyeokkorean = 12602; + t.rieulkiyeoksioskorean = 12649; + t.rieulkorean = 12601; + t.rieulmieumkorean = 12603; + t.rieulpansioskorean = 12652; + t.rieulparenkorean = 12803; + t.rieulphieuphkorean = 12607; + t.rieulpieupkorean = 12604; + t.rieulpieupsioskorean = 12651; + t.rieulsioskorean = 12605; + t.rieulthieuthkorean = 12606; + t.rieultikeutkorean = 12650; + t.rieulyeorinhieuhkorean = 12653; + t.rightangle = 8735; + t.righttackbelowcmb = 793; + t.righttriangle = 8895; + t.rihiragana = 12426; + t.rikatakana = 12522; + t.rikatakanahalfwidth = 65432; + t.ring = 730; + t.ringbelowcmb = 805; + t.ringcmb = 778; + t.ringhalfleft = 703; + t.ringhalfleftarmenian = 1369; + t.ringhalfleftbelowcmb = 796; + t.ringhalfleftcentered = 723; + t.ringhalfright = 702; + t.ringhalfrightbelowcmb = 825; + t.ringhalfrightcentered = 722; + t.rinvertedbreve = 531; + t.rittorusquare = 13137; + t.rlinebelow = 7775; + t.rlongleg = 636; + t.rlonglegturned = 634; + t.rmonospace = 65362; + t.rohiragana = 12429; + t.rokatakana = 12525; + t.rokatakanahalfwidth = 65435; + t.roruathai = 3619; + t.rparen = 9389; + t.rrabengali = 2524; + t.rradeva = 2353; + t.rragurmukhi = 2652; + t.rreharabic = 1681; + t.rrehfinalarabic = 64397; + t.rrvocalicbengali = 2528; + t.rrvocalicdeva = 2400; + t.rrvocalicgujarati = 2784; + t.rrvocalicvowelsignbengali = 2500; + t.rrvocalicvowelsigndeva = 2372; + t.rrvocalicvowelsigngujarati = 2756; + t.rsuperior = 63217; + t.rtblock = 9616; + t.rturned = 633; + t.rturnedsuperior = 692; + t.ruhiragana = 12427; + t.rukatakana = 12523; + t.rukatakanahalfwidth = 65433; + t.rupeemarkbengali = 2546; + t.rupeesignbengali = 2547; + t.rupiah = 63197; + t.ruthai = 3620; + t.rvocalicbengali = 2443; + t.rvocalicdeva = 2315; + t.rvocalicgujarati = 2699; + t.rvocalicvowelsignbengali = 2499; + t.rvocalicvowelsigndeva = 2371; + t.rvocalicvowelsigngujarati = 2755; + t.s = 115; + t.sabengali = 2488; + t.sacute = 347; + t.sacutedotaccent = 7781; + t.sadarabic = 1589; + t.sadeva = 2360; + t.sadfinalarabic = 65210; + t.sadinitialarabic = 65211; + t.sadmedialarabic = 65212; + t.sagujarati = 2744; + t.sagurmukhi = 2616; + t.sahiragana = 12373; + t.sakatakana = 12469; + t.sakatakanahalfwidth = 65403; + t.sallallahoualayhewasallamarabic = 65018; + t.samekh = 1505; + t.samekhdagesh = 64321; + t.samekhdageshhebrew = 64321; + t.samekhhebrew = 1505; + t.saraaathai = 3634; + t.saraaethai = 3649; + t.saraaimaimalaithai = 3652; + t.saraaimaimuanthai = 3651; + t.saraamthai = 3635; + t.saraathai = 3632; + t.saraethai = 3648; + t.saraiileftthai = 63622; + t.saraiithai = 3637; + t.saraileftthai = 63621; + t.saraithai = 3636; + t.saraothai = 3650; + t.saraueeleftthai = 63624; + t.saraueethai = 3639; + t.saraueleftthai = 63623; + t.sarauethai = 3638; + t.sarauthai = 3640; + t.sarauuthai = 3641; + t.sbopomofo = 12569; + t.scaron = 353; + t.scarondotaccent = 7783; + t.scedilla = 351; + t.schwa = 601; + t.schwacyrillic = 1241; + t.schwadieresiscyrillic = 1243; + t.schwahook = 602; + t.scircle = 9442; + t.scircumflex = 349; + t.scommaaccent = 537; + t.sdotaccent = 7777; + t.sdotbelow = 7779; + t.sdotbelowdotaccent = 7785; + t.seagullbelowcmb = 828; + t.second = 8243; + t.secondtonechinese = 714; + t.section = 167; + t.seenarabic = 1587; + t.seenfinalarabic = 65202; + t.seeninitialarabic = 65203; + t.seenmedialarabic = 65204; + t.segol = 1462; + t.segol13 = 1462; + t.segol1f = 1462; + t.segol2c = 1462; + t.segolhebrew = 1462; + t.segolnarrowhebrew = 1462; + t.segolquarterhebrew = 1462; + t.segoltahebrew = 1426; + t.segolwidehebrew = 1462; + t.seharmenian = 1405; + t.sehiragana = 12379; + t.sekatakana = 12475; + t.sekatakanahalfwidth = 65406; + t.semicolon = 59; + t.semicolonarabic = 1563; + t.semicolonmonospace = 65307; + t.semicolonsmall = 65108; + t.semivoicedmarkkana = 12444; + t.semivoicedmarkkanahalfwidth = 65439; + t.sentisquare = 13090; + t.sentosquare = 13091; + t.seven = 55; + t.sevenarabic = 1639; + t.sevenbengali = 2541; + t.sevencircle = 9318; + t.sevencircleinversesansserif = 10128; + t.sevendeva = 2413; + t.seveneighths = 8542; + t.sevengujarati = 2797; + t.sevengurmukhi = 2669; + t.sevenhackarabic = 1639; + t.sevenhangzhou = 12327; + t.sevenideographicparen = 12838; + t.seveninferior = 8327; + t.sevenmonospace = 65303; + t.sevenoldstyle = 63287; + t.sevenparen = 9338; + t.sevenperiod = 9358; + t.sevenpersian = 1783; + t.sevenroman = 8566; + t.sevensuperior = 8311; + t.seventeencircle = 9328; + t.seventeenparen = 9348; + t.seventeenperiod = 9368; + t.seventhai = 3671; + t.sfthyphen = 173; + t.shaarmenian = 1399; + t.shabengali = 2486; + t.shacyrillic = 1096; + t.shaddaarabic = 1617; + t.shaddadammaarabic = 64609; + t.shaddadammatanarabic = 64606; + t.shaddafathaarabic = 64608; + t.shaddakasraarabic = 64610; + t.shaddakasratanarabic = 64607; + t.shade = 9618; + t.shadedark = 9619; + t.shadelight = 9617; + t.shademedium = 9618; + t.shadeva = 2358; + t.shagujarati = 2742; + t.shagurmukhi = 2614; + t.shalshelethebrew = 1427; + t.shbopomofo = 12565; + t.shchacyrillic = 1097; + t.sheenarabic = 1588; + t.sheenfinalarabic = 65206; + t.sheeninitialarabic = 65207; + t.sheenmedialarabic = 65208; + t.sheicoptic = 995; + t.sheqel = 8362; + t.sheqelhebrew = 8362; + t.sheva = 1456; + t.sheva115 = 1456; + t.sheva15 = 1456; + t.sheva22 = 1456; + t.sheva2e = 1456; + t.shevahebrew = 1456; + t.shevanarrowhebrew = 1456; + t.shevaquarterhebrew = 1456; + t.shevawidehebrew = 1456; + t.shhacyrillic = 1211; + t.shimacoptic = 1005; + t.shin = 1513; + t.shindagesh = 64329; + t.shindageshhebrew = 64329; + t.shindageshshindot = 64300; + t.shindageshshindothebrew = 64300; + t.shindageshsindot = 64301; + t.shindageshsindothebrew = 64301; + t.shindothebrew = 1473; + t.shinhebrew = 1513; + t.shinshindot = 64298; + t.shinshindothebrew = 64298; + t.shinsindot = 64299; + t.shinsindothebrew = 64299; + t.shook = 642; + t.sigma = 963; + t.sigma1 = 962; + t.sigmafinal = 962; + t.sigmalunatesymbolgreek = 1010; + t.sihiragana = 12375; + t.sikatakana = 12471; + t.sikatakanahalfwidth = 65404; + t.siluqhebrew = 1469; + t.siluqlefthebrew = 1469; + t.similar = 8764; + t.sindothebrew = 1474; + t.siosacirclekorean = 12916; + t.siosaparenkorean = 12820; + t.sioscieuckorean = 12670; + t.sioscirclekorean = 12902; + t.sioskiyeokkorean = 12666; + t.sioskorean = 12613; + t.siosnieunkorean = 12667; + t.siosparenkorean = 12806; + t.siospieupkorean = 12669; + t.siostikeutkorean = 12668; + t.six = 54; + t.sixarabic = 1638; + t.sixbengali = 2540; + t.sixcircle = 9317; + t.sixcircleinversesansserif = 10127; + t.sixdeva = 2412; + t.sixgujarati = 2796; + t.sixgurmukhi = 2668; + t.sixhackarabic = 1638; + t.sixhangzhou = 12326; + t.sixideographicparen = 12837; + t.sixinferior = 8326; + t.sixmonospace = 65302; + t.sixoldstyle = 63286; + t.sixparen = 9337; + t.sixperiod = 9357; + t.sixpersian = 1782; + t.sixroman = 8565; + t.sixsuperior = 8310; + t.sixteencircle = 9327; + t.sixteencurrencydenominatorbengali = 2553; + t.sixteenparen = 9347; + t.sixteenperiod = 9367; + t.sixthai = 3670; + t.slash = 47; + t.slashmonospace = 65295; + t.slong = 383; + t.slongdotaccent = 7835; + t.smileface = 9786; + t.smonospace = 65363; + t.sofpasuqhebrew = 1475; + t.softhyphen = 173; + t.softsigncyrillic = 1100; + t.sohiragana = 12381; + t.sokatakana = 12477; + t.sokatakanahalfwidth = 65407; + t.soliduslongoverlaycmb = 824; + t.solidusshortoverlaycmb = 823; + t.sorusithai = 3625; + t.sosalathai = 3624; + t.sosothai = 3595; + t.sosuathai = 3626; + t.space = 32; + t.spacehackarabic = 32; + t.spade = 9824; + t.spadesuitblack = 9824; + t.spadesuitwhite = 9828; + t.sparen = 9390; + t.squarebelowcmb = 827; + t.squarecc = 13252; + t.squarecm = 13213; + t.squarediagonalcrosshatchfill = 9641; + t.squarehorizontalfill = 9636; + t.squarekg = 13199; + t.squarekm = 13214; + t.squarekmcapital = 13262; + t.squareln = 13265; + t.squarelog = 13266; + t.squaremg = 13198; + t.squaremil = 13269; + t.squaremm = 13212; + t.squaremsquared = 13217; + t.squareorthogonalcrosshatchfill = 9638; + t.squareupperlefttolowerrightfill = 9639; + t.squareupperrighttolowerleftfill = 9640; + t.squareverticalfill = 9637; + t.squarewhitewithsmallblack = 9635; + t.srsquare = 13275; + t.ssabengali = 2487; + t.ssadeva = 2359; + t.ssagujarati = 2743; + t.ssangcieuckorean = 12617; + t.ssanghieuhkorean = 12677; + t.ssangieungkorean = 12672; + t.ssangkiyeokkorean = 12594; + t.ssangnieunkorean = 12645; + t.ssangpieupkorean = 12611; + t.ssangsioskorean = 12614; + t.ssangtikeutkorean = 12600; + t.ssuperior = 63218; + t.sterling = 163; + t.sterlingmonospace = 65505; + t.strokelongoverlaycmb = 822; + t.strokeshortoverlaycmb = 821; + t.subset = 8834; + t.subsetnotequal = 8842; + t.subsetorequal = 8838; + t.succeeds = 8827; + t.suchthat = 8715; + t.suhiragana = 12377; + t.sukatakana = 12473; + t.sukatakanahalfwidth = 65405; + t.sukunarabic = 1618; + t.summation = 8721; + t.sun = 9788; + t.superset = 8835; + t.supersetnotequal = 8843; + t.supersetorequal = 8839; + t.svsquare = 13276; + t.syouwaerasquare = 13180; + t.t = 116; + t.tabengali = 2468; + t.tackdown = 8868; + t.tackleft = 8867; + t.tadeva = 2340; + t.tagujarati = 2724; + t.tagurmukhi = 2596; + t.taharabic = 1591; + t.tahfinalarabic = 65218; + t.tahinitialarabic = 65219; + t.tahiragana = 12383; + t.tahmedialarabic = 65220; + t.taisyouerasquare = 13181; + t.takatakana = 12479; + t.takatakanahalfwidth = 65408; + t.tatweelarabic = 1600; + t.tau = 964; + t.tav = 1514; + t.tavdages = 64330; + t.tavdagesh = 64330; + t.tavdageshhebrew = 64330; + t.tavhebrew = 1514; + t.tbar = 359; + t.tbopomofo = 12554; + t.tcaron = 357; + t.tccurl = 680; + t.tcedilla = 355; + t.tcheharabic = 1670; + t.tchehfinalarabic = 64379; + t.tchehinitialarabic = 64380; + t.tchehmedialarabic = 64381; + t.tcircle = 9443; + t.tcircumflexbelow = 7793; + t.tcommaaccent = 355; + t.tdieresis = 7831; + t.tdotaccent = 7787; + t.tdotbelow = 7789; + t.tecyrillic = 1090; + t.tedescendercyrillic = 1197; + t.teharabic = 1578; + t.tehfinalarabic = 65174; + t.tehhahinitialarabic = 64674; + t.tehhahisolatedarabic = 64524; + t.tehinitialarabic = 65175; + t.tehiragana = 12390; + t.tehjeeminitialarabic = 64673; + t.tehjeemisolatedarabic = 64523; + t.tehmarbutaarabic = 1577; + t.tehmarbutafinalarabic = 65172; + t.tehmedialarabic = 65176; + t.tehmeeminitialarabic = 64676; + t.tehmeemisolatedarabic = 64526; + t.tehnoonfinalarabic = 64627; + t.tekatakana = 12486; + t.tekatakanahalfwidth = 65411; + t.telephone = 8481; + t.telephoneblack = 9742; + t.telishagedolahebrew = 1440; + t.telishaqetanahebrew = 1449; + t.tencircle = 9321; + t.tenideographicparen = 12841; + t.tenparen = 9341; + t.tenperiod = 9361; + t.tenroman = 8569; + t.tesh = 679; + t.tet = 1496; + t.tetdagesh = 64312; + t.tetdageshhebrew = 64312; + t.tethebrew = 1496; + t.tetsecyrillic = 1205; + t.tevirhebrew = 1435; + t.tevirlefthebrew = 1435; + t.thabengali = 2469; + t.thadeva = 2341; + t.thagujarati = 2725; + t.thagurmukhi = 2597; + t.thalarabic = 1584; + t.thalfinalarabic = 65196; + t.thanthakhatlowleftthai = 63640; + t.thanthakhatlowrightthai = 63639; + t.thanthakhatthai = 3660; + t.thanthakhatupperleftthai = 63638; + t.theharabic = 1579; + t.thehfinalarabic = 65178; + t.thehinitialarabic = 65179; + t.thehmedialarabic = 65180; + t.thereexists = 8707; + t.therefore = 8756; + t.theta = 952; + t.theta1 = 977; + t.thetasymbolgreek = 977; + t.thieuthacirclekorean = 12921; + t.thieuthaparenkorean = 12825; + t.thieuthcirclekorean = 12907; + t.thieuthkorean = 12620; + t.thieuthparenkorean = 12811; + t.thirteencircle = 9324; + t.thirteenparen = 9344; + t.thirteenperiod = 9364; + t.thonangmonthothai = 3601; + t.thook = 429; + t.thophuthaothai = 3602; + t.thorn = 254; + t.thothahanthai = 3607; + t.thothanthai = 3600; + t.thothongthai = 3608; + t.thothungthai = 3606; + t.thousandcyrillic = 1154; + t.thousandsseparatorarabic = 1644; + t.thousandsseparatorpersian = 1644; + t.three = 51; + t.threearabic = 1635; + t.threebengali = 2537; + t.threecircle = 9314; + t.threecircleinversesansserif = 10124; + t.threedeva = 2409; + t.threeeighths = 8540; + t.threegujarati = 2793; + t.threegurmukhi = 2665; + t.threehackarabic = 1635; + t.threehangzhou = 12323; + t.threeideographicparen = 12834; + t.threeinferior = 8323; + t.threemonospace = 65299; + t.threenumeratorbengali = 2550; + t.threeoldstyle = 63283; + t.threeparen = 9334; + t.threeperiod = 9354; + t.threepersian = 1779; + t.threequarters = 190; + t.threequartersemdash = 63198; + t.threeroman = 8562; + t.threesuperior = 179; + t.threethai = 3667; + t.thzsquare = 13204; + t.tihiragana = 12385; + t.tikatakana = 12481; + t.tikatakanahalfwidth = 65409; + t.tikeutacirclekorean = 12912; + t.tikeutaparenkorean = 12816; + t.tikeutcirclekorean = 12898; + t.tikeutkorean = 12599; + t.tikeutparenkorean = 12802; + t.tilde = 732; + t.tildebelowcmb = 816; + t.tildecmb = 771; + t.tildecomb = 771; + t.tildedoublecmb = 864; + t.tildeoperator = 8764; + t.tildeoverlaycmb = 820; + t.tildeverticalcmb = 830; + t.timescircle = 8855; + t.tipehahebrew = 1430; + t.tipehalefthebrew = 1430; + t.tippigurmukhi = 2672; + t.titlocyrilliccmb = 1155; + t.tiwnarmenian = 1407; + t.tlinebelow = 7791; + t.tmonospace = 65364; + t.toarmenian = 1385; + t.tohiragana = 12392; + t.tokatakana = 12488; + t.tokatakanahalfwidth = 65412; + t.tonebarextrahighmod = 741; + t.tonebarextralowmod = 745; + t.tonebarhighmod = 742; + t.tonebarlowmod = 744; + t.tonebarmidmod = 743; + t.tonefive = 445; + t.tonesix = 389; + t.tonetwo = 424; + t.tonos = 900; + t.tonsquare = 13095; + t.topatakthai = 3599; + t.tortoiseshellbracketleft = 12308; + t.tortoiseshellbracketleftsmall = 65117; + t.tortoiseshellbracketleftvertical = 65081; + t.tortoiseshellbracketright = 12309; + t.tortoiseshellbracketrightsmall = 65118; + t.tortoiseshellbracketrightvertical = 65082; + t.totaothai = 3605; + t.tpalatalhook = 427; + t.tparen = 9391; + t.trademark = 8482; + t.trademarksans = 63722; + t.trademarkserif = 63195; + t.tretroflexhook = 648; + t.triagdn = 9660; + t.triaglf = 9668; + t.triagrt = 9658; + t.triagup = 9650; + t.ts = 678; + t.tsadi = 1510; + t.tsadidagesh = 64326; + t.tsadidageshhebrew = 64326; + t.tsadihebrew = 1510; + t.tsecyrillic = 1094; + t.tsere = 1461; + t.tsere12 = 1461; + t.tsere1e = 1461; + t.tsere2b = 1461; + t.tserehebrew = 1461; + t.tserenarrowhebrew = 1461; + t.tserequarterhebrew = 1461; + t.tserewidehebrew = 1461; + t.tshecyrillic = 1115; + t.tsuperior = 63219; + t.ttabengali = 2463; + t.ttadeva = 2335; + t.ttagujarati = 2719; + t.ttagurmukhi = 2591; + t.tteharabic = 1657; + t.ttehfinalarabic = 64359; + t.ttehinitialarabic = 64360; + t.ttehmedialarabic = 64361; + t.tthabengali = 2464; + t.tthadeva = 2336; + t.tthagujarati = 2720; + t.tthagurmukhi = 2592; + t.tturned = 647; + t.tuhiragana = 12388; + t.tukatakana = 12484; + t.tukatakanahalfwidth = 65410; + t.tusmallhiragana = 12387; + t.tusmallkatakana = 12483; + t.tusmallkatakanahalfwidth = 65391; + t.twelvecircle = 9323; + t.twelveparen = 9343; + t.twelveperiod = 9363; + t.twelveroman = 8571; + t.twentycircle = 9331; + t.twentyhangzhou = 21316; + t.twentyparen = 9351; + t.twentyperiod = 9371; + t.two = 50; + t.twoarabic = 1634; + t.twobengali = 2536; + t.twocircle = 9313; + t.twocircleinversesansserif = 10123; + t.twodeva = 2408; + t.twodotenleader = 8229; + t.twodotleader = 8229; + t.twodotleadervertical = 65072; + t.twogujarati = 2792; + t.twogurmukhi = 2664; + t.twohackarabic = 1634; + t.twohangzhou = 12322; + t.twoideographicparen = 12833; + t.twoinferior = 8322; + t.twomonospace = 65298; + t.twonumeratorbengali = 2549; + t.twooldstyle = 63282; + t.twoparen = 9333; + t.twoperiod = 9353; + t.twopersian = 1778; + t.tworoman = 8561; + t.twostroke = 443; + t.twosuperior = 178; + t.twothai = 3666; + t.twothirds = 8532; + t.u = 117; + t.uacute = 250; + t.ubar = 649; + t.ubengali = 2441; + t.ubopomofo = 12584; + t.ubreve = 365; + t.ucaron = 468; + t.ucircle = 9444; + t.ucircumflex = 251; + t.ucircumflexbelow = 7799; + t.ucyrillic = 1091; + t.udattadeva = 2385; + t.udblacute = 369; + t.udblgrave = 533; + t.udeva = 2313; + t.udieresis = 252; + t.udieresisacute = 472; + t.udieresisbelow = 7795; + t.udieresiscaron = 474; + t.udieresiscyrillic = 1265; + t.udieresisgrave = 476; + t.udieresismacron = 470; + t.udotbelow = 7909; + t.ugrave = 249; + t.ugujarati = 2697; + t.ugurmukhi = 2569; + t.uhiragana = 12358; + t.uhookabove = 7911; + t.uhorn = 432; + t.uhornacute = 7913; + t.uhorndotbelow = 7921; + t.uhorngrave = 7915; + t.uhornhookabove = 7917; + t.uhorntilde = 7919; + t.uhungarumlaut = 369; + t.uhungarumlautcyrillic = 1267; + t.uinvertedbreve = 535; + t.ukatakana = 12454; + t.ukatakanahalfwidth = 65395; + t.ukcyrillic = 1145; + t.ukorean = 12636; + t.umacron = 363; + t.umacroncyrillic = 1263; + t.umacrondieresis = 7803; + t.umatragurmukhi = 2625; + t.umonospace = 65365; + t.underscore = 95; + t.underscoredbl = 8215; + t.underscoremonospace = 65343; + t.underscorevertical = 65075; + t.underscorewavy = 65103; + t.union = 8746; + t.universal = 8704; + t.uogonek = 371; + t.uparen = 9392; + t.upblock = 9600; + t.upperdothebrew = 1476; + t.upsilon = 965; + t.upsilondieresis = 971; + t.upsilondieresistonos = 944; + t.upsilonlatin = 650; + t.upsilontonos = 973; + t.uptackbelowcmb = 797; + t.uptackmod = 724; + t.uragurmukhi = 2675; + t.uring = 367; + t.ushortcyrillic = 1118; + t.usmallhiragana = 12357; + t.usmallkatakana = 12453; + t.usmallkatakanahalfwidth = 65385; + t.ustraightcyrillic = 1199; + t.ustraightstrokecyrillic = 1201; + t.utilde = 361; + t.utildeacute = 7801; + t.utildebelow = 7797; + t.uubengali = 2442; + t.uudeva = 2314; + t.uugujarati = 2698; + t.uugurmukhi = 2570; + t.uumatragurmukhi = 2626; + t.uuvowelsignbengali = 2498; + t.uuvowelsigndeva = 2370; + t.uuvowelsigngujarati = 2754; + t.uvowelsignbengali = 2497; + t.uvowelsigndeva = 2369; + t.uvowelsigngujarati = 2753; + t.v = 118; + t.vadeva = 2357; + t.vagujarati = 2741; + t.vagurmukhi = 2613; + t.vakatakana = 12535; + t.vav = 1493; + t.vavdagesh = 64309; + t.vavdagesh65 = 64309; + t.vavdageshhebrew = 64309; + t.vavhebrew = 1493; + t.vavholam = 64331; + t.vavholamhebrew = 64331; + t.vavvavhebrew = 1520; + t.vavyodhebrew = 1521; + t.vcircle = 9445; + t.vdotbelow = 7807; + t.vecyrillic = 1074; + t.veharabic = 1700; + t.vehfinalarabic = 64363; + t.vehinitialarabic = 64364; + t.vehmedialarabic = 64365; + t.vekatakana = 12537; + t.venus = 9792; + t.verticalbar = 124; + t.verticallineabovecmb = 781; + t.verticallinebelowcmb = 809; + t.verticallinelowmod = 716; + t.verticallinemod = 712; + t.vewarmenian = 1406; + t.vhook = 651; + t.vikatakana = 12536; + t.viramabengali = 2509; + t.viramadeva = 2381; + t.viramagujarati = 2765; + t.visargabengali = 2435; + t.visargadeva = 2307; + t.visargagujarati = 2691; + t.vmonospace = 65366; + t.voarmenian = 1400; + t.voicediterationhiragana = 12446; + t.voicediterationkatakana = 12542; + t.voicedmarkkana = 12443; + t.voicedmarkkanahalfwidth = 65438; + t.vokatakana = 12538; + t.vparen = 9393; + t.vtilde = 7805; + t.vturned = 652; + t.vuhiragana = 12436; + t.vukatakana = 12532; + t.w = 119; + t.wacute = 7811; + t.waekorean = 12633; + t.wahiragana = 12431; + t.wakatakana = 12527; + t.wakatakanahalfwidth = 65436; + t.wakorean = 12632; + t.wasmallhiragana = 12430; + t.wasmallkatakana = 12526; + t.wattosquare = 13143; + t.wavedash = 12316; + t.wavyunderscorevertical = 65076; + t.wawarabic = 1608; + t.wawfinalarabic = 65262; + t.wawhamzaabovearabic = 1572; + t.wawhamzaabovefinalarabic = 65158; + t.wbsquare = 13277; + t.wcircle = 9446; + t.wcircumflex = 373; + t.wdieresis = 7813; + t.wdotaccent = 7815; + t.wdotbelow = 7817; + t.wehiragana = 12433; + t.weierstrass = 8472; + t.wekatakana = 12529; + t.wekorean = 12638; + t.weokorean = 12637; + t.wgrave = 7809; + t.whitebullet = 9702; + t.whitecircle = 9675; + t.whitecircleinverse = 9689; + t.whitecornerbracketleft = 12302; + t.whitecornerbracketleftvertical = 65091; + t.whitecornerbracketright = 12303; + t.whitecornerbracketrightvertical = 65092; + t.whitediamond = 9671; + t.whitediamondcontainingblacksmalldiamond = 9672; + t.whitedownpointingsmalltriangle = 9663; + t.whitedownpointingtriangle = 9661; + t.whiteleftpointingsmalltriangle = 9667; + t.whiteleftpointingtriangle = 9665; + t.whitelenticularbracketleft = 12310; + t.whitelenticularbracketright = 12311; + t.whiterightpointingsmalltriangle = 9657; + t.whiterightpointingtriangle = 9655; + t.whitesmallsquare = 9643; + t.whitesmilingface = 9786; + t.whitesquare = 9633; + t.whitestar = 9734; + t.whitetelephone = 9743; + t.whitetortoiseshellbracketleft = 12312; + t.whitetortoiseshellbracketright = 12313; + t.whiteuppointingsmalltriangle = 9653; + t.whiteuppointingtriangle = 9651; + t.wihiragana = 12432; + t.wikatakana = 12528; + t.wikorean = 12639; + t.wmonospace = 65367; + t.wohiragana = 12434; + t.wokatakana = 12530; + t.wokatakanahalfwidth = 65382; + t.won = 8361; + t.wonmonospace = 65510; + t.wowaenthai = 3623; + t.wparen = 9394; + t.wring = 7832; + t.wsuperior = 695; + t.wturned = 653; + t.wynn = 447; + t.x = 120; + t.xabovecmb = 829; + t.xbopomofo = 12562; + t.xcircle = 9447; + t.xdieresis = 7821; + t.xdotaccent = 7819; + t.xeharmenian = 1389; + t.xi = 958; + t.xmonospace = 65368; + t.xparen = 9395; + t.xsuperior = 739; + t.y = 121; + t.yaadosquare = 13134; + t.yabengali = 2479; + t.yacute = 253; + t.yadeva = 2351; + t.yaekorean = 12626; + t.yagujarati = 2735; + t.yagurmukhi = 2607; + t.yahiragana = 12420; + t.yakatakana = 12516; + t.yakatakanahalfwidth = 65428; + t.yakorean = 12625; + t.yamakkanthai = 3662; + t.yasmallhiragana = 12419; + t.yasmallkatakana = 12515; + t.yasmallkatakanahalfwidth = 65388; + t.yatcyrillic = 1123; + t.ycircle = 9448; + t.ycircumflex = 375; + t.ydieresis = 255; + t.ydotaccent = 7823; + t.ydotbelow = 7925; + t.yeharabic = 1610; + t.yehbarreearabic = 1746; + t.yehbarreefinalarabic = 64431; + t.yehfinalarabic = 65266; + t.yehhamzaabovearabic = 1574; + t.yehhamzaabovefinalarabic = 65162; + t.yehhamzaaboveinitialarabic = 65163; + t.yehhamzaabovemedialarabic = 65164; + t.yehinitialarabic = 65267; + t.yehmedialarabic = 65268; + t.yehmeeminitialarabic = 64733; + t.yehmeemisolatedarabic = 64600; + t.yehnoonfinalarabic = 64660; + t.yehthreedotsbelowarabic = 1745; + t.yekorean = 12630; + t.yen = 165; + t.yenmonospace = 65509; + t.yeokorean = 12629; + t.yeorinhieuhkorean = 12678; + t.yerahbenyomohebrew = 1450; + t.yerahbenyomolefthebrew = 1450; + t.yericyrillic = 1099; + t.yerudieresiscyrillic = 1273; + t.yesieungkorean = 12673; + t.yesieungpansioskorean = 12675; + t.yesieungsioskorean = 12674; + t.yetivhebrew = 1434; + t.ygrave = 7923; + t.yhook = 436; + t.yhookabove = 7927; + t.yiarmenian = 1397; + t.yicyrillic = 1111; + t.yikorean = 12642; + t.yinyang = 9775; + t.yiwnarmenian = 1410; + t.ymonospace = 65369; + t.yod = 1497; + t.yoddagesh = 64313; + t.yoddageshhebrew = 64313; + t.yodhebrew = 1497; + t.yodyodhebrew = 1522; + t.yodyodpatahhebrew = 64287; + t.yohiragana = 12424; + t.yoikorean = 12681; + t.yokatakana = 12520; + t.yokatakanahalfwidth = 65430; + t.yokorean = 12635; + t.yosmallhiragana = 12423; + t.yosmallkatakana = 12519; + t.yosmallkatakanahalfwidth = 65390; + t.yotgreek = 1011; + t.yoyaekorean = 12680; + t.yoyakorean = 12679; + t.yoyakthai = 3618; + t.yoyingthai = 3597; + t.yparen = 9396; + t.ypogegrammeni = 890; + t.ypogegrammenigreekcmb = 837; + t.yr = 422; + t.yring = 7833; + t.ysuperior = 696; + t.ytilde = 7929; + t.yturned = 654; + t.yuhiragana = 12422; + t.yuikorean = 12684; + t.yukatakana = 12518; + t.yukatakanahalfwidth = 65429; + t.yukorean = 12640; + t.yusbigcyrillic = 1131; + t.yusbigiotifiedcyrillic = 1133; + t.yuslittlecyrillic = 1127; + t.yuslittleiotifiedcyrillic = 1129; + t.yusmallhiragana = 12421; + t.yusmallkatakana = 12517; + t.yusmallkatakanahalfwidth = 65389; + t.yuyekorean = 12683; + t.yuyeokorean = 12682; + t.yyabengali = 2527; + t.yyadeva = 2399; + t.z = 122; + t.zaarmenian = 1382; + t.zacute = 378; + t.zadeva = 2395; + t.zagurmukhi = 2651; + t.zaharabic = 1592; + t.zahfinalarabic = 65222; + t.zahinitialarabic = 65223; + t.zahiragana = 12374; + t.zahmedialarabic = 65224; + t.zainarabic = 1586; + t.zainfinalarabic = 65200; + t.zakatakana = 12470; + t.zaqefgadolhebrew = 1429; + t.zaqefqatanhebrew = 1428; + t.zarqahebrew = 1432; + t.zayin = 1494; + t.zayindagesh = 64310; + t.zayindageshhebrew = 64310; + t.zayinhebrew = 1494; + t.zbopomofo = 12567; + t.zcaron = 382; + t.zcircle = 9449; + t.zcircumflex = 7825; + t.zcurl = 657; + t.zdot = 380; + t.zdotaccent = 380; + t.zdotbelow = 7827; + t.zecyrillic = 1079; + t.zedescendercyrillic = 1177; + t.zedieresiscyrillic = 1247; + t.zehiragana = 12380; + t.zekatakana = 12476; + t.zero = 48; + t.zeroarabic = 1632; + t.zerobengali = 2534; + t.zerodeva = 2406; + t.zerogujarati = 2790; + t.zerogurmukhi = 2662; + t.zerohackarabic = 1632; + t.zeroinferior = 8320; + t.zeromonospace = 65296; + t.zerooldstyle = 63280; + t.zeropersian = 1776; + t.zerosuperior = 8304; + t.zerothai = 3664; + t.zerowidthjoiner = 65279; + t.zerowidthnonjoiner = 8204; + t.zerowidthspace = 8203; + t.zeta = 950; + t.zhbopomofo = 12563; + t.zhearmenian = 1386; + t.zhebrevecyrillic = 1218; + t.zhecyrillic = 1078; + t.zhedescendercyrillic = 1175; + t.zhedieresiscyrillic = 1245; + t.zihiragana = 12376; + t.zikatakana = 12472; + t.zinorhebrew = 1454; + t.zlinebelow = 7829; + t.zmonospace = 65370; + t.zohiragana = 12382; + t.zokatakana = 12478; + t.zparen = 9397; + t.zretroflexhook = 656; + t.zstroke = 438; + t.zuhiragana = 12378; + t.zukatakana = 12474; + t[".notdef"] = 0; + t.angbracketleftbig = 9001; + t.angbracketleftBig = 9001; + t.angbracketleftbigg = 9001; + t.angbracketleftBigg = 9001; + t.angbracketrightBig = 9002; + t.angbracketrightbig = 9002; + t.angbracketrightBigg = 9002; + t.angbracketrightbigg = 9002; + t.arrowhookleft = 8618; + t.arrowhookright = 8617; + t.arrowlefttophalf = 8636; + t.arrowleftbothalf = 8637; + t.arrownortheast = 8599; + t.arrownorthwest = 8598; + t.arrowrighttophalf = 8640; + t.arrowrightbothalf = 8641; + t.arrowsoutheast = 8600; + t.arrowsouthwest = 8601; + t.backslashbig = 8726; + t.backslashBig = 8726; + t.backslashBigg = 8726; + t.backslashbigg = 8726; + t.bardbl = 8214; + t.bracehtipdownleft = 65079; + t.bracehtipdownright = 65079; + t.bracehtipupleft = 65080; + t.bracehtipupright = 65080; + t.braceleftBig = 123; + t.braceleftbig = 123; + t.braceleftbigg = 123; + t.braceleftBigg = 123; + t.bracerightBig = 125; + t.bracerightbig = 125; + t.bracerightbigg = 125; + t.bracerightBigg = 125; + t.bracketleftbig = 91; + t.bracketleftBig = 91; + t.bracketleftbigg = 91; + t.bracketleftBigg = 91; + t.bracketrightBig = 93; + t.bracketrightbig = 93; + t.bracketrightbigg = 93; + t.bracketrightBigg = 93; + t.ceilingleftbig = 8968; + t.ceilingleftBig = 8968; + t.ceilingleftBigg = 8968; + t.ceilingleftbigg = 8968; + t.ceilingrightbig = 8969; + t.ceilingrightBig = 8969; + t.ceilingrightbigg = 8969; + t.ceilingrightBigg = 8969; + t.circledotdisplay = 8857; + t.circledottext = 8857; + t.circlemultiplydisplay = 8855; + t.circlemultiplytext = 8855; + t.circleplusdisplay = 8853; + t.circleplustext = 8853; + t.contintegraldisplay = 8750; + t.contintegraltext = 8750; + t.coproductdisplay = 8720; + t.coproducttext = 8720; + t.floorleftBig = 8970; + t.floorleftbig = 8970; + t.floorleftbigg = 8970; + t.floorleftBigg = 8970; + t.floorrightbig = 8971; + t.floorrightBig = 8971; + t.floorrightBigg = 8971; + t.floorrightbigg = 8971; + t.hatwide = 770; + t.hatwider = 770; + t.hatwidest = 770; + t.intercal = 7488; + t.integraldisplay = 8747; + t.integraltext = 8747; + t.intersectiondisplay = 8898; + t.intersectiontext = 8898; + t.logicalanddisplay = 8743; + t.logicalandtext = 8743; + t.logicalordisplay = 8744; + t.logicalortext = 8744; + t.parenleftBig = 40; + t.parenleftbig = 40; + t.parenleftBigg = 40; + t.parenleftbigg = 40; + t.parenrightBig = 41; + t.parenrightbig = 41; + t.parenrightBigg = 41; + t.parenrightbigg = 41; + t.prime = 8242; + t.productdisplay = 8719; + t.producttext = 8719; + t.radicalbig = 8730; + t.radicalBig = 8730; + t.radicalBigg = 8730; + t.radicalbigg = 8730; + t.radicalbt = 8730; + t.radicaltp = 8730; + t.radicalvertex = 8730; + t.slashbig = 47; + t.slashBig = 47; + t.slashBigg = 47; + t.slashbigg = 47; + t.summationdisplay = 8721; + t.summationtext = 8721; + t.tildewide = 732; + t.tildewider = 732; + t.tildewidest = 732; + t.uniondisplay = 8899; + t.unionmultidisplay = 8846; + t.unionmultitext = 8846; + t.unionsqdisplay = 8852; + t.unionsqtext = 8852; + t.uniontext = 8899; + t.vextenddouble = 8741; + t.vextendsingle = 8739; + }); + getDingbatsGlyphsUnicode = getLookupTableFactory(function(t) { + t.space = 32; + t.a1 = 9985; + t.a2 = 9986; + t.a202 = 9987; + t.a3 = 9988; + t.a4 = 9742; + t.a5 = 9990; + t.a119 = 9991; + t.a118 = 9992; + t.a117 = 9993; + t.a11 = 9755; + t.a12 = 9758; + t.a13 = 9996; + t.a14 = 9997; + t.a15 = 9998; + t.a16 = 9999; + t.a105 = 1e4; + t.a17 = 10001; + t.a18 = 10002; + t.a19 = 10003; + t.a20 = 10004; + t.a21 = 10005; + t.a22 = 10006; + t.a23 = 10007; + t.a24 = 10008; + t.a25 = 10009; + t.a26 = 10010; + t.a27 = 10011; + t.a28 = 10012; + t.a6 = 10013; + t.a7 = 10014; + t.a8 = 10015; + t.a9 = 10016; + t.a10 = 10017; + t.a29 = 10018; + t.a30 = 10019; + t.a31 = 10020; + t.a32 = 10021; + t.a33 = 10022; + t.a34 = 10023; + t.a35 = 9733; + t.a36 = 10025; + t.a37 = 10026; + t.a38 = 10027; + t.a39 = 10028; + t.a40 = 10029; + t.a41 = 10030; + t.a42 = 10031; + t.a43 = 10032; + t.a44 = 10033; + t.a45 = 10034; + t.a46 = 10035; + t.a47 = 10036; + t.a48 = 10037; + t.a49 = 10038; + t.a50 = 10039; + t.a51 = 10040; + t.a52 = 10041; + t.a53 = 10042; + t.a54 = 10043; + t.a55 = 10044; + t.a56 = 10045; + t.a57 = 10046; + t.a58 = 10047; + t.a59 = 10048; + t.a60 = 10049; + t.a61 = 10050; + t.a62 = 10051; + t.a63 = 10052; + t.a64 = 10053; + t.a65 = 10054; + t.a66 = 10055; + t.a67 = 10056; + t.a68 = 10057; + t.a69 = 10058; + t.a70 = 10059; + t.a71 = 9679; + t.a72 = 10061; + t.a73 = 9632; + t.a74 = 10063; + t.a203 = 10064; + t.a75 = 10065; + t.a204 = 10066; + t.a76 = 9650; + t.a77 = 9660; + t.a78 = 9670; + t.a79 = 10070; + t.a81 = 9687; + t.a82 = 10072; + t.a83 = 10073; + t.a84 = 10074; + t.a97 = 10075; + t.a98 = 10076; + t.a99 = 10077; + t.a100 = 10078; + t.a101 = 10081; + t.a102 = 10082; + t.a103 = 10083; + t.a104 = 10084; + t.a106 = 10085; + t.a107 = 10086; + t.a108 = 10087; + t.a112 = 9827; + t.a111 = 9830; + t.a110 = 9829; + t.a109 = 9824; + t.a120 = 9312; + t.a121 = 9313; + t.a122 = 9314; + t.a123 = 9315; + t.a124 = 9316; + t.a125 = 9317; + t.a126 = 9318; + t.a127 = 9319; + t.a128 = 9320; + t.a129 = 9321; + t.a130 = 10102; + t.a131 = 10103; + t.a132 = 10104; + t.a133 = 10105; + t.a134 = 10106; + t.a135 = 10107; + t.a136 = 10108; + t.a137 = 10109; + t.a138 = 10110; + t.a139 = 10111; + t.a140 = 10112; + t.a141 = 10113; + t.a142 = 10114; + t.a143 = 10115; + t.a144 = 10116; + t.a145 = 10117; + t.a146 = 10118; + t.a147 = 10119; + t.a148 = 10120; + t.a149 = 10121; + t.a150 = 10122; + t.a151 = 10123; + t.a152 = 10124; + t.a153 = 10125; + t.a154 = 10126; + t.a155 = 10127; + t.a156 = 10128; + t.a157 = 10129; + t.a158 = 10130; + t.a159 = 10131; + t.a160 = 10132; + t.a161 = 8594; + t.a163 = 8596; + t.a164 = 8597; + t.a196 = 10136; + t.a165 = 10137; + t.a192 = 10138; + t.a166 = 10139; + t.a167 = 10140; + t.a168 = 10141; + t.a169 = 10142; + t.a170 = 10143; + t.a171 = 10144; + t.a172 = 10145; + t.a173 = 10146; + t.a162 = 10147; + t.a174 = 10148; + t.a175 = 10149; + t.a176 = 10150; + t.a177 = 10151; + t.a178 = 10152; + t.a179 = 10153; + t.a193 = 10154; + t.a180 = 10155; + t.a199 = 10156; + t.a181 = 10157; + t.a200 = 10158; + t.a182 = 10159; + t.a201 = 10161; + t.a183 = 10162; + t.a184 = 10163; + t.a197 = 10164; + t.a185 = 10165; + t.a194 = 10166; + t.a198 = 10167; + t.a186 = 10168; + t.a195 = 10169; + t.a187 = 10170; + t.a188 = 10171; + t.a189 = 10172; + t.a190 = 10173; + t.a191 = 10174; + t.a89 = 10088; + t.a90 = 10089; + t.a93 = 10090; + t.a94 = 10091; + t.a91 = 10092; + t.a92 = 10093; + t.a205 = 10094; + t.a85 = 10095; + t.a206 = 10096; + t.a86 = 10097; + t.a87 = 10098; + t.a88 = 10099; + t.a95 = 10100; + t.a96 = 10101; + t[".notdef"] = 0; + }); + getSpecialPUASymbols = getLookupTableFactory(function(t) { + t[63721] = 169; + t[63193] = 169; + t[63720] = 174; + t[63194] = 174; + t[63722] = 8482; + t[63195] = 8482; + t[63729] = 9127; + t[63730] = 9128; + t[63731] = 9129; + t[63740] = 9131; + t[63741] = 9132; + t[63742] = 9133; + t[63726] = 9121; + t[63727] = 9122; + t[63728] = 9123; + t[63737] = 9124; + t[63738] = 9125; + t[63739] = 9126; + t[63723] = 9115; + t[63724] = 9116; + t[63725] = 9117; + t[63734] = 9118; + t[63735] = 9119; + t[63736] = 9120; + }); + UnicodeRanges = [[0, 127], [128, 255], [256, 383], [384, 591], [592, 687, 7424, 7551, 7552, 7615], [688, 767, 42752, 42783], [768, 879, 7616, 7679], [880, 1023], [11392, 11519], [1024, 1279, 1280, 1327, 11744, 11775, 42560, 42655], [1328, 1423], [1424, 1535], [42240, 42559], [1536, 1791, 1872, 1919], [1984, 2047], [2304, 2431], [2432, 2559], [2560, 2687], [2688, 2815], [2816, 2943], [2944, 3071], [3072, 3199], [3200, 3327], [3328, 3455], [3584, 3711], [3712, 3839], [4256, 4351, 11520, 11567], [6912, 7039], [4352, 4607], [7680, 7935, 11360, 11391, 42784, 43007], [7936, 8191], [8192, 8303, 11776, 11903], [8304, 8351], [8352, 8399], [8400, 8447], [8448, 8527], [8528, 8591], [8592, 8703, 10224, 10239, 10496, 10623, 11008, 11263], [8704, 8959, 10752, 11007, 10176, 10223, 10624, 10751], [8960, 9215], [9216, 9279], [9280, 9311], [9312, 9471], [9472, 9599], [9600, 9631], [9632, 9727], [9728, 9983], [9984, 10175], [12288, 12351], [12352, 12447], [12448, 12543, 12784, 12799], [12544, 12591, 12704, 12735], [12592, 12687], [43072, 43135], [12800, 13055], [13056, 13311], [44032, 55215], [55296, 57343], [67840, 67871], [19968, 40959, 11904, 12031, 12032, 12255, 12272, 12287, 13312, 19903, 131072, 173791, 12688, 12703], [57344, 63743], [12736, 12783, 63744, 64255, 194560, 195103], [64256, 64335], [64336, 65023], [65056, 65071], [65040, 65055], [65104, 65135], [65136, 65279], [65280, 65519], [65520, 65535], [3840, 4095], [1792, 1871], [1920, 1983], [3456, 3583], [4096, 4255], [4608, 4991, 4992, 5023, 11648, 11743], [5024, 5119], [5120, 5759], [5760, 5791], [5792, 5887], [6016, 6143], [6144, 6319], [10240, 10495], [40960, 42127], [5888, 5919, 5920, 5951, 5952, 5983, 5984, 6015], [66304, 66351], [66352, 66383], [66560, 66639], [118784, 119039, 119040, 119295, 119296, 119375], [119808, 120831], [1044480, 1048573], [65024, 65039, 917760, 917999], [917504, 917631], [6400, 6479], [6480, 6527], [6528, 6623], [6656, 6687], [11264, 11359], [11568, 11647], [19904, 19967], [43008, 43055], [65536, 65663, 65664, 65791, 65792, 65855], [65856, 65935], [66432, 66463], [66464, 66527], [66640, 66687], [66688, 66735], [67584, 67647], [68096, 68191], [119552, 119647], [73728, 74751, 74752, 74879], [119648, 119679], [7040, 7103], [7168, 7247], [7248, 7295], [43136, 43231], [43264, 43311], [43312, 43359], [43520, 43615], [65936, 65999], [66e3, 66047], [66208, 66271, 66176, 66207, 67872, 67903], [127024, 127135, 126976, 127023]]; + SpecialCharRegExp = new RegExp("^(\\s)|(\\p{Mn})|(\\p{Cf})$", "u"); + CategoryCache = /* @__PURE__ */ new Map(); + SEAC_ANALYSIS_ENABLED = true; + FontFlags = { + FixedPitch: 1, + Serif: 2, + Symbolic: 4, + Script: 8, + Nonsymbolic: 32, + Italic: 64, + AllCap: 65536, + SmallCap: 131072, + ForceBold: 262144 + }; + MacStandardGlyphOrdering = [".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", "section", "bullet", "paragraph", "germandbls", "registered", "copyright", "trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff", "summation", "product", "pi", "integral", "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot", "radical", "florin", "approxequal", "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth", "Yacute", "yacute", "Thorn", "thorn", "minus", "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter", "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", "dcroat"]; + getVerticalPresentationForm = getLookupTableFactory((t) => { + t[8211] = 65074; + t[8212] = 65073; + t[8229] = 65072; + t[8230] = 65049; + t[12289] = 65041; + t[12290] = 65042; + t[12296] = 65087; + t[12297] = 65088; + t[12298] = 65085; + t[12299] = 65086; + t[12300] = 65089; + t[12301] = 65090; + t[12302] = 65091; + t[12303] = 65092; + t[12304] = 65083; + t[12305] = 65084; + t[12308] = 65081; + t[12309] = 65082; + t[12310] = 65047; + t[12311] = 65048; + t[65103] = 65076; + t[65281] = 65045; + t[65288] = 65077; + t[65289] = 65078; + t[65292] = 65040; + t[65306] = 65043; + t[65307] = 65044; + t[65311] = 65046; + t[65339] = 65095; + t[65341] = 65096; + t[65343] = 65075; + t[65371] = 65079; + t[65373] = 65080; + }); + MAX_SIZE_TO_COMPILE = 1e3; + es_iterator_to_array = __webpack_require__2(1806); + ISOAdobeCharset = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron"]; + ExpertCharset = [".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "onequarter", "onehalf", "threequarters", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall"]; + ExpertSubsetCharset = [".notdef", "space", "dollaroldstyle", "dollarsuperior", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior", "threequartersemdash", "periodsuperior", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "hyphensuperior", "colonmonetary", "onefitted", "rupiah", "centoldstyle", "figuredash", "hypheninferior", "onequarter", "onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior", "twosuperior", "threesuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior"]; + MAX_SUBR_NESTING = 10; + CFFStandardStrings = [".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar", "percent", "ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "colon", "semicolon", "less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright", "asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent", "sterling", "fraction", "yen", "florin", "section", "currency", "quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl", "periodcentered", "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand", "questiondown", "grave", "acute", "circumflex", "tilde", "macron", "breve", "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine", "Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash", "oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu", "trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter", "divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior", "registered", "minus", "eth", "multiply", "threesuperior", "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex", "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute", "acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex", "idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis", "ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis", "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior", "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior", "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior", "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior", "tsuperior", "ff", "ffi", "ffl", "parenleftinferior", "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall", "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird", "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior", "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior", "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior", "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall", "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000", "001.001", "001.002", "001.003", "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"]; + NUM_STANDARD_CFF_STRINGS = 391; + CharstringValidationData = [null, { + id: "hstem", + min: 2, + stackClearing: true, + stem: true + }, null, { + id: "vstem", + min: 2, + stackClearing: true, + stem: true + }, { + id: "vmoveto", + min: 1, + stackClearing: true + }, { + id: "rlineto", + min: 2, + resetStack: true + }, { + id: "hlineto", + min: 1, + resetStack: true + }, { + id: "vlineto", + min: 1, + resetStack: true + }, { + id: "rrcurveto", + min: 6, + resetStack: true + }, null, { + id: "callsubr", + min: 1, + undefStack: true + }, { + id: "return", + min: 0, + undefStack: true + }, null, null, { + id: "endchar", + min: 0, + stackClearing: true + }, null, null, null, { + id: "hstemhm", + min: 2, + stackClearing: true, + stem: true + }, { + id: "hintmask", + min: 0, + stackClearing: true + }, { + id: "cntrmask", + min: 0, + stackClearing: true + }, { + id: "rmoveto", + min: 2, + stackClearing: true + }, { + id: "hmoveto", + min: 1, + stackClearing: true + }, { + id: "vstemhm", + min: 2, + stackClearing: true, + stem: true + }, { + id: "rcurveline", + min: 8, + resetStack: true + }, { + id: "rlinecurve", + min: 8, + resetStack: true + }, { + id: "vvcurveto", + min: 4, + resetStack: true + }, { + id: "hhcurveto", + min: 4, + resetStack: true + }, null, { + id: "callgsubr", + min: 1, + undefStack: true + }, { + id: "vhcurveto", + min: 4, + resetStack: true + }, { + id: "hvcurveto", + min: 4, + resetStack: true + }]; + CharstringValidationData12 = [null, null, null, { + id: "and", + min: 2, + stackDelta: -1 + }, { + id: "or", + min: 2, + stackDelta: -1 + }, { + id: "not", + min: 1, + stackDelta: 0 + }, null, null, null, { + id: "abs", + min: 1, + stackDelta: 0 + }, { + id: "add", + min: 2, + stackDelta: -1, + stackFn(stack, index2) { + stack[index2 - 2] = stack[index2 - 2] + stack[index2 - 1]; + } + }, { + id: "sub", + min: 2, + stackDelta: -1, + stackFn(stack, index2) { + stack[index2 - 2] = stack[index2 - 2] - stack[index2 - 1]; + } + }, { + id: "div", + min: 2, + stackDelta: -1, + stackFn(stack, index2) { + stack[index2 - 2] = stack[index2 - 2] / stack[index2 - 1]; + } + }, null, { + id: "neg", + min: 1, + stackDelta: 0, + stackFn(stack, index2) { + stack[index2 - 1] = -stack[index2 - 1]; + } + }, { + id: "eq", + min: 2, + stackDelta: -1 + }, null, null, { + id: "drop", + min: 1, + stackDelta: -1 + }, null, { + id: "put", + min: 2, + stackDelta: -2 + }, { + id: "get", + min: 1, + stackDelta: 0 + }, { + id: "ifelse", + min: 4, + stackDelta: -3 + }, { + id: "random", + min: 0, + stackDelta: 1 + }, { + id: "mul", + min: 2, + stackDelta: -1, + stackFn(stack, index2) { + stack[index2 - 2] = stack[index2 - 2] * stack[index2 - 1]; + } + }, null, { + id: "sqrt", + min: 1, + stackDelta: 0 + }, { + id: "dup", + min: 1, + stackDelta: 1 + }, { + id: "exch", + min: 2, + stackDelta: 0 + }, { + id: "index", + min: 2, + stackDelta: 0 + }, { + id: "roll", + min: 3, + stackDelta: -2 + }, null, null, null, { + id: "hflex", + min: 7, + resetStack: true + }, { + id: "flex", + min: 13, + resetStack: true + }, { + id: "hflex1", + min: 9, + resetStack: true + }, { + id: "flex1", + min: 11, + resetStack: true + }]; + CFFParser = class { + constructor(file2, properties, seacAnalysisEnabled) { + this.bytes = file2.getBytes(); + this.properties = properties; + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + } + parse() { + const properties = this.properties; + const cff = new CFF(); + this.cff = cff; + const header = this.parseHeader(); + const nameIndex = this.parseIndex(header.endPos); + const topDictIndex = this.parseIndex(nameIndex.endPos); + const stringIndex = this.parseIndex(topDictIndex.endPos); + const globalSubrIndex = this.parseIndex(stringIndex.endPos); + const topDictParsed = this.parseDict(topDictIndex.obj.get(0)); + const topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings); + cff.header = header.obj; + cff.names = this.parseNameIndex(nameIndex.obj); + cff.strings = this.parseStringIndex(stringIndex.obj); + cff.topDict = topDict; + cff.globalSubrIndex = globalSubrIndex.obj; + this.parsePrivateDict(cff.topDict); + cff.isCIDFont = topDict.hasName("ROS"); + const charStringOffset = topDict.getByName("CharStrings"); + const charStringIndex = this.parseIndex(charStringOffset).obj; + const fontMatrix = topDict.getByName("FontMatrix"); + if (fontMatrix) { + properties.fontMatrix = fontMatrix; + } + const fontBBox = topDict.getByName("FontBBox"); + if (fontBBox) { + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + } + let charset, encoding; + if (cff.isCIDFont) { + const fdArrayIndex = this.parseIndex(topDict.getByName("FDArray")).obj; + for (let i = 0, ii = fdArrayIndex.count; i < ii; ++i) { + const dictRaw = fdArrayIndex.get(i); + const fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings); + this.parsePrivateDict(fontDict); + cff.fdArray.push(fontDict); + } + encoding = null; + charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, true); + cff.fdSelect = this.parseFDSelect(topDict.getByName("FDSelect"), charStringIndex.count); + } else { + charset = this.parseCharsets(topDict.getByName("charset"), charStringIndex.count, cff.strings, false); + encoding = this.parseEncoding(topDict.getByName("Encoding"), properties, cff.strings, charset.charset); + } + cff.charset = charset; + cff.encoding = encoding; + const charStringsAndSeacs = this.parseCharStrings({ + charStrings: charStringIndex, + localSubrIndex: topDict.privateDict.subrsIndex, + globalSubrIndex: globalSubrIndex.obj, + fdSelect: cff.fdSelect, + fdArray: cff.fdArray, + privateDict: topDict.privateDict + }); + cff.charStrings = charStringsAndSeacs.charStrings; + cff.seacs = charStringsAndSeacs.seacs; + cff.widths = charStringsAndSeacs.widths; + return cff; + } + parseHeader() { + let bytes = this.bytes; + const bytesLength = bytes.length; + let offset = 0; + while (offset < bytesLength && bytes[offset] !== 1) { + ++offset; + } + if (offset >= bytesLength) { + throw new FormatError3("Invalid CFF header"); + } + if (offset !== 0) { + info2("cff data is shifted"); + bytes = bytes.subarray(offset); + this.bytes = bytes; + } + const major2 = bytes[0]; + const minor = bytes[1]; + const hdrSize = bytes[2]; + const offSize = bytes[3]; + const header = new CFFHeader(major2, minor, hdrSize, offSize); + return { + obj: header, + endPos: hdrSize + }; + } + parseDict(dict) { + let pos = 0; + function parseOperand() { + let value = dict[pos++]; + if (value === 30) { + return parseFloatOperand(); + } else if (value === 28) { + value = readInt16(dict, pos); + pos += 2; + return value; + } else if (value === 29) { + value = dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + value = value << 8 | dict[pos++]; + return value; + } else if (value >= 32 && value <= 246) { + return value - 139; + } else if (value >= 247 && value <= 250) { + return (value - 247) * 256 + dict[pos++] + 108; + } else if (value >= 251 && value <= 254) { + return -((value - 251) * 256) - dict[pos++] - 108; + } + warn2('CFFParser_parseDict: "' + value + '" is a reserved command.'); + return NaN; + } + function parseFloatOperand() { + let str = ""; + const eof = 15; + const lookup = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "E", "E-", null, "-"]; + const length = dict.length; + while (pos < length) { + const b2 = dict[pos++]; + const b1 = b2 >> 4; + const b22 = b2 & 15; + if (b1 === eof) { + break; + } + str += lookup[b1]; + if (b22 === eof) { + break; + } + str += lookup[b22]; + } + return parseFloat(str); + } + let operands = []; + const entries = []; + pos = 0; + const end = dict.length; + while (pos < end) { + let b2 = dict[pos]; + if (b2 <= 21) { + if (b2 === 12) { + b2 = b2 << 8 | dict[++pos]; + } + entries.push([b2, operands]); + operands = []; + ++pos; + } else { + operands.push(parseOperand()); + } + } + return entries; + } + parseIndex(pos) { + const cffIndex = new CFFIndex(); + const bytes = this.bytes; + const count = bytes[pos++] << 8 | bytes[pos++]; + const offsets = []; + let end = pos; + let i, ii; + if (count !== 0) { + const offsetSize = bytes[pos++]; + const startPos = pos + (count + 1) * offsetSize - 1; + for (i = 0, ii = count + 1; i < ii; ++i) { + let offset = 0; + for (let j = 0; j < offsetSize; ++j) { + offset <<= 8; + offset += bytes[pos++]; + } + offsets.push(startPos + offset); + } + end = offsets[count]; + } + for (i = 0, ii = offsets.length - 1; i < ii; ++i) { + const offsetStart = offsets[i]; + const offsetEnd = offsets[i + 1]; + cffIndex.add(bytes.subarray(offsetStart, offsetEnd)); + } + return { + obj: cffIndex, + endPos: end + }; + } + parseNameIndex(index2) { + const names = []; + for (let i = 0, ii = index2.count; i < ii; ++i) { + const name = index2.get(i); + names.push(bytesToString2(name)); + } + return names; + } + parseStringIndex(index2) { + const strings = new CFFStrings(); + for (let i = 0, ii = index2.count; i < ii; ++i) { + const data = index2.get(i); + strings.add(bytesToString2(data)); + } + return strings; + } + createDict(Type2, dict, strings) { + const cffDict = new Type2(strings); + for (const [key, value] of dict) { + cffDict.setByKey(key, value); + } + return cffDict; + } + parseCharString(state, data, localSubrIndex, globalSubrIndex) { + if (!data || state.callDepth > MAX_SUBR_NESTING) { + return false; + } + let stackSize = state.stackSize; + const stack = state.stack; + let length = data.length; + for (let j = 0; j < length; ) { + const value = data[j++]; + let validationCommand = null; + if (value === 12) { + const q = data[j++]; + if (q === 0) { + data[j - 2] = 139; + data[j - 1] = 22; + stackSize = 0; + } else { + validationCommand = CharstringValidationData12[q]; + } + } else if (value === 28) { + stack[stackSize] = readInt16(data, j); + j += 2; + stackSize++; + } else if (value === 14) { + if (stackSize >= 4) { + stackSize -= 4; + if (this.seacAnalysisEnabled) { + state.seac = stack.slice(stackSize, stackSize + 4); + return false; + } + } + validationCommand = CharstringValidationData[value]; + } else if (value >= 32 && value <= 246) { + stack[stackSize] = value - 139; + stackSize++; + } else if (value >= 247 && value <= 254) { + stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108; + j++; + stackSize++; + } else if (value === 255) { + stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536; + j += 4; + stackSize++; + } else if (value === 19 || value === 20) { + state.hints += stackSize >> 1; + if (state.hints === 0) { + data.copyWithin(j - 1, j, -1); + j -= 1; + length -= 1; + continue; + } + j += state.hints + 7 >> 3; + stackSize %= 2; + validationCommand = CharstringValidationData[value]; + } else if (value === 10 || value === 29) { + const subrsIndex = value === 10 ? localSubrIndex : globalSubrIndex; + if (!subrsIndex) { + validationCommand = CharstringValidationData[value]; + warn2("Missing subrsIndex for " + validationCommand.id); + return false; + } + let bias = 32768; + if (subrsIndex.count < 1240) { + bias = 107; + } else if (subrsIndex.count < 33900) { + bias = 1131; + } + const subrNumber = stack[--stackSize] + bias; + if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) { + validationCommand = CharstringValidationData[value]; + warn2("Out of bounds subrIndex for " + validationCommand.id); + return false; + } + state.stackSize = stackSize; + state.callDepth++; + const valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex); + if (!valid) { + return false; + } + state.callDepth--; + stackSize = state.stackSize; + continue; + } else if (value === 11) { + state.stackSize = stackSize; + return true; + } else if (value === 0 && j === data.length) { + data[j - 1] = 14; + validationCommand = CharstringValidationData[14]; + } else if (value === 9) { + data.copyWithin(j - 1, j, -1); + j -= 1; + length -= 1; + continue; + } else { + validationCommand = CharstringValidationData[value]; + } + if (validationCommand) { + if (validationCommand.stem) { + state.hints += stackSize >> 1; + if (value === 3 || value === 23) { + state.hasVStems = true; + } else if (state.hasVStems && (value === 1 || value === 18)) { + warn2("CFF stem hints are in wrong order"); + data[j - 1] = value === 1 ? 3 : 23; + } + } + if ("min" in validationCommand) { + if (!state.undefStack && stackSize < validationCommand.min) { + warn2("Not enough parameters for " + validationCommand.id + "; actual: " + stackSize + ", expected: " + validationCommand.min); + if (stackSize === 0) { + data[j - 1] = 14; + return true; + } + return false; + } + } + if (state.firstStackClearing && validationCommand.stackClearing) { + state.firstStackClearing = false; + stackSize -= validationCommand.min; + if (stackSize >= 2 && validationCommand.stem) { + stackSize %= 2; + } else if (stackSize > 1) { + warn2("Found too many parameters for stack-clearing command"); + } + if (stackSize > 0) { + state.width = stack[stackSize - 1]; + } + } + if ("stackDelta" in validationCommand) { + if ("stackFn" in validationCommand) { + validationCommand.stackFn(stack, stackSize); + } + stackSize += validationCommand.stackDelta; + } else if (validationCommand.stackClearing) { + stackSize = 0; + } else if (validationCommand.resetStack) { + stackSize = 0; + state.undefStack = false; + } else if (validationCommand.undefStack) { + stackSize = 0; + state.undefStack = true; + state.firstStackClearing = false; + } + } + } + if (length < data.length) { + data.fill(14, length); + } + state.stackSize = stackSize; + return true; + } + parseCharStrings({ + charStrings, + localSubrIndex, + globalSubrIndex, + fdSelect, + fdArray, + privateDict + }) { + const seacs = []; + const widths = []; + const count = charStrings.count; + for (let i = 0; i < count; i++) { + const charstring = charStrings.get(i); + const state = { + callDepth: 0, + stackSize: 0, + stack: [], + undefStack: true, + hints: 0, + firstStackClearing: true, + seac: null, + width: null, + hasVStems: false + }; + let valid = true; + let localSubrToUse = null; + let privateDictToUse = privateDict; + if (fdSelect && fdArray.length) { + const fdIndex = fdSelect.getFDIndex(i); + if (fdIndex === -1) { + warn2("Glyph index is not in fd select."); + valid = false; + } + if (fdIndex >= fdArray.length) { + warn2("Invalid fd index for glyph index."); + valid = false; + } + if (valid) { + privateDictToUse = fdArray[fdIndex].privateDict; + localSubrToUse = privateDictToUse.subrsIndex; + } + } else if (localSubrIndex) { + localSubrToUse = localSubrIndex; + } + if (valid) { + valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex); + } + if (state.width !== null) { + const nominalWidth = privateDictToUse.getByName("nominalWidthX"); + widths[i] = nominalWidth + state.width; + } else { + const defaultWidth = privateDictToUse.getByName("defaultWidthX"); + widths[i] = defaultWidth; + } + if (state.seac !== null) { + seacs[i] = state.seac; + } + if (!valid) { + charStrings.set(i, new Uint8Array([14])); + } + } + return { + charStrings, + seacs, + widths + }; + } + emptyPrivateDictionary(parentDict) { + const privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings); + parentDict.setByKey(18, [0, 0]); + parentDict.privateDict = privateDict; + } + parsePrivateDict(parentDict) { + if (!parentDict.hasName("Private")) { + this.emptyPrivateDictionary(parentDict); + return; + } + const privateOffset = parentDict.getByName("Private"); + if (!Array.isArray(privateOffset) || privateOffset.length !== 2) { + parentDict.removeByName("Private"); + return; + } + const size3 = privateOffset[0]; + const offset = privateOffset[1]; + if (size3 === 0 || offset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + const privateDictEnd = offset + size3; + const dictData = this.bytes.subarray(offset, privateDictEnd); + const dict = this.parseDict(dictData); + const privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings); + parentDict.privateDict = privateDict; + if (privateDict.getByName("ExpansionFactor") === 0) { + privateDict.setByName("ExpansionFactor", 0.06); + } + if (!privateDict.getByName("Subrs")) { + return; + } + const subrsOffset = privateDict.getByName("Subrs"); + const relativeOffset = offset + subrsOffset; + if (subrsOffset === 0 || relativeOffset >= this.bytes.length) { + this.emptyPrivateDictionary(parentDict); + return; + } + const subrsIndex = this.parseIndex(relativeOffset); + privateDict.subrsIndex = subrsIndex.obj; + } + parseCharsets(pos, length, strings, cid) { + if (pos === 0) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, ISOAdobeCharset); + } else if (pos === 1) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, ExpertCharset); + } else if (pos === 2) { + return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, ExpertSubsetCharset); + } + const bytes = this.bytes; + const start = pos; + const format = bytes[pos++]; + const charset = [cid ? 0 : ".notdef"]; + let id, count, i; + length -= 1; + switch (format) { + case 0: + for (i = 0; i < length; i++) { + id = bytes[pos++] << 8 | bytes[pos++]; + charset.push(cid ? id : strings.get(id)); + } + break; + case 1: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + case 2: + while (charset.length <= length) { + id = bytes[pos++] << 8 | bytes[pos++]; + count = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i <= count; i++) { + charset.push(cid ? id++ : strings.get(id++)); + } + } + break; + default: + throw new FormatError3("Unknown charset format"); + } + const end = pos; + const raw = bytes.subarray(start, end); + return new CFFCharset(false, format, charset, raw); + } + parseEncoding(pos, properties, strings, charset) { + const encoding = /* @__PURE__ */ Object.create(null); + const bytes = this.bytes; + let predefined = false; + let format, i, ii; + let raw = null; + function readSupplement() { + const supplementsCount = bytes[pos++]; + for (i = 0; i < supplementsCount; i++) { + const code = bytes[pos++]; + const sid = (bytes[pos++] << 8) + (bytes[pos++] & 255); + encoding[code] = charset.indexOf(strings.get(sid)); + } + } + if (pos === 0 || pos === 1) { + predefined = true; + format = pos; + const baseEncoding = pos ? ExpertEncoding : StandardEncoding; + for (i = 0, ii = charset.length; i < ii; i++) { + const index2 = baseEncoding.indexOf(charset[i]); + if (index2 !== -1) { + encoding[index2] = i; + } + } + } else { + const dataStart = pos; + format = bytes[pos++]; + switch (format & 127) { + case 0: + const glyphsCount = bytes[pos++]; + for (i = 1; i <= glyphsCount; i++) { + encoding[bytes[pos++]] = i; + } + break; + case 1: + const rangesCount = bytes[pos++]; + let gid = 1; + for (i = 0; i < rangesCount; i++) { + const start = bytes[pos++]; + const left = bytes[pos++]; + for (let j = start; j <= start + left; j++) { + encoding[j] = gid++; + } + } + break; + default: + throw new FormatError3(`Unknown encoding format: ${format} in CFF`); + } + const dataEnd = pos; + if (format & 128) { + bytes[dataStart] &= 127; + readSupplement(); + } + raw = bytes.subarray(dataStart, dataEnd); + } + format &= 127; + return new CFFEncoding(predefined, format, encoding, raw); + } + parseFDSelect(pos, length) { + const bytes = this.bytes; + const format = bytes[pos++]; + const fdSelect = []; + let i; + switch (format) { + case 0: + for (i = 0; i < length; ++i) { + const id = bytes[pos++]; + fdSelect.push(id); + } + break; + case 3: + const rangesCount = bytes[pos++] << 8 | bytes[pos++]; + for (i = 0; i < rangesCount; ++i) { + let first2 = bytes[pos++] << 8 | bytes[pos++]; + if (i === 0 && first2 !== 0) { + warn2("parseFDSelect: The first range must have a first GID of 0 -- trying to recover."); + first2 = 0; + } + const fdIndex = bytes[pos++]; + const next = bytes[pos] << 8 | bytes[pos + 1]; + for (let j = first2; j < next; ++j) { + fdSelect.push(fdIndex); + } + } + pos += 2; + break; + default: + throw new FormatError3(`parseFDSelect: Unknown format "${format}".`); + } + if (fdSelect.length !== length) { + throw new FormatError3("parseFDSelect: Invalid font data."); + } + return new CFFFDSelect(format, fdSelect); + } + }; + CFF = class { + constructor() { + this.header = null; + this.names = []; + this.topDict = null; + this.strings = new CFFStrings(); + this.globalSubrIndex = null; + this.encoding = null; + this.charset = null; + this.charStrings = null; + this.fdArray = []; + this.fdSelect = null; + this.isCIDFont = false; + } + duplicateFirstGlyph() { + if (this.charStrings.count >= 65535) { + warn2("Not enough space in charstrings to duplicate first glyph."); + return; + } + const glyphZero = this.charStrings.get(0); + this.charStrings.add(glyphZero); + if (this.isCIDFont) { + this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]); + } + } + hasGlyphId(id) { + if (id < 0 || id >= this.charStrings.count) { + return false; + } + const glyph = this.charStrings.get(id); + return glyph.length > 0; + } + }; + CFFHeader = class { + constructor(major2, minor, hdrSize, offSize) { + this.major = major2; + this.minor = minor; + this.hdrSize = hdrSize; + this.offSize = offSize; + } + }; + CFFStrings = class { + constructor() { + this.strings = []; + } + get(index2) { + if (index2 >= 0 && index2 <= NUM_STANDARD_CFF_STRINGS - 1) { + return CFFStandardStrings[index2]; + } + if (index2 - NUM_STANDARD_CFF_STRINGS <= this.strings.length) { + return this.strings[index2 - NUM_STANDARD_CFF_STRINGS]; + } + return CFFStandardStrings[0]; + } + getSID(str) { + let index2 = CFFStandardStrings.indexOf(str); + if (index2 !== -1) { + return index2; + } + index2 = this.strings.indexOf(str); + if (index2 !== -1) { + return index2 + NUM_STANDARD_CFF_STRINGS; + } + return -1; + } + add(value) { + this.strings.push(value); + } + get count() { + return this.strings.length; + } + }; + CFFIndex = class { + constructor() { + this.objects = []; + this.length = 0; + } + add(data) { + this.length += data.length; + this.objects.push(data); + } + set(index2, data) { + this.length += data.length - this.objects[index2].length; + this.objects[index2] = data; + } + get(index2) { + return this.objects[index2]; + } + get count() { + return this.objects.length; + } + }; + CFFDict = class { + constructor(tables, strings) { + this.keyToNameMap = tables.keyToNameMap; + this.nameToKeyMap = tables.nameToKeyMap; + this.defaults = tables.defaults; + this.types = tables.types; + this.opcodes = tables.opcodes; + this.order = tables.order; + this.strings = strings; + this.values = /* @__PURE__ */ Object.create(null); + } + setByKey(key, value) { + if (!(key in this.keyToNameMap)) { + return false; + } + if (value.length === 0) { + return true; + } + for (const val of value) { + if (isNaN(val)) { + warn2(`Invalid CFFDict value: "${value}" for key "${key}".`); + return true; + } + } + const type = this.types[key]; + if (type === "num" || type === "sid" || type === "offset") { + value = value[0]; + } + this.values[key] = value; + return true; + } + setByName(name, value) { + if (!(name in this.nameToKeyMap)) { + throw new FormatError3(`Invalid dictionary name "${name}"`); + } + this.values[this.nameToKeyMap[name]] = value; + } + hasName(name) { + return this.nameToKeyMap[name] in this.values; + } + getByName(name) { + if (!(name in this.nameToKeyMap)) { + throw new FormatError3(`Invalid dictionary name ${name}"`); + } + const key = this.nameToKeyMap[name]; + if (!(key in this.values)) { + return this.defaults[key]; + } + return this.values[key]; + } + removeByName(name) { + delete this.values[this.nameToKeyMap[name]]; + } + static createTables(layout) { + const tables = { + keyToNameMap: {}, + nameToKeyMap: {}, + defaults: {}, + types: {}, + opcodes: {}, + order: [] + }; + for (const entry of layout) { + const key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0]; + tables.keyToNameMap[key] = entry[1]; + tables.nameToKeyMap[entry[1]] = key; + tables.types[key] = entry[2]; + tables.defaults[key] = entry[3]; + tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]]; + tables.order.push(key); + } + return tables; + } + }; + CFFTopDictLayout = [[[12, 30], "ROS", ["sid", "sid", "num"], null], [[12, 20], "SyntheticBase", "num", null], [0, "version", "sid", null], [1, "Notice", "sid", null], [[12, 0], "Copyright", "sid", null], [2, "FullName", "sid", null], [3, "FamilyName", "sid", null], [4, "Weight", "sid", null], [[12, 1], "isFixedPitch", "num", 0], [[12, 2], "ItalicAngle", "num", 0], [[12, 3], "UnderlinePosition", "num", -100], [[12, 4], "UnderlineThickness", "num", 50], [[12, 5], "PaintType", "num", 0], [[12, 6], "CharstringType", "num", 2], [[12, 7], "FontMatrix", ["num", "num", "num", "num", "num", "num"], [1e-3, 0, 0, 1e-3, 0, 0]], [13, "UniqueID", "num", null], [5, "FontBBox", ["num", "num", "num", "num"], [0, 0, 0, 0]], [[12, 8], "StrokeWidth", "num", 0], [14, "XUID", "array", null], [15, "charset", "offset", 0], [16, "Encoding", "offset", 0], [17, "CharStrings", "offset", 0], [18, "Private", ["offset", "offset"], null], [[12, 21], "PostScript", "sid", null], [[12, 22], "BaseFontName", "sid", null], [[12, 23], "BaseFontBlend", "delta", null], [[12, 31], "CIDFontVersion", "num", 0], [[12, 32], "CIDFontRevision", "num", 0], [[12, 33], "CIDFontType", "num", 0], [[12, 34], "CIDCount", "num", 8720], [[12, 35], "UIDBase", "num", null], [[12, 37], "FDSelect", "offset", null], [[12, 36], "FDArray", "offset", null], [[12, 38], "FontName", "sid", null]]; + CFFTopDict = class _CFFTopDict extends CFFDict { + static get tables() { + return shadow2(this, "tables", this.createTables(CFFTopDictLayout)); + } + constructor(strings) { + super(_CFFTopDict.tables, strings); + this.privateDict = null; + } + }; + CFFPrivateDictLayout = [[6, "BlueValues", "delta", null], [7, "OtherBlues", "delta", null], [8, "FamilyBlues", "delta", null], [9, "FamilyOtherBlues", "delta", null], [[12, 9], "BlueScale", "num", 0.039625], [[12, 10], "BlueShift", "num", 7], [[12, 11], "BlueFuzz", "num", 1], [10, "StdHW", "num", null], [11, "StdVW", "num", null], [[12, 12], "StemSnapH", "delta", null], [[12, 13], "StemSnapV", "delta", null], [[12, 14], "ForceBold", "num", 0], [[12, 17], "LanguageGroup", "num", 0], [[12, 18], "ExpansionFactor", "num", 0.06], [[12, 19], "initialRandomSeed", "num", 0], [20, "defaultWidthX", "num", 0], [21, "nominalWidthX", "num", 0], [19, "Subrs", "offset", null]]; + CFFPrivateDict = class _CFFPrivateDict extends CFFDict { + static get tables() { + return shadow2(this, "tables", this.createTables(CFFPrivateDictLayout)); + } + constructor(strings) { + super(_CFFPrivateDict.tables, strings); + this.subrsIndex = null; + } + }; + CFFCharsetPredefinedTypes = { + ISO_ADOBE: 0, + EXPERT: 1, + EXPERT_SUBSET: 2 + }; + CFFCharset = class { + constructor(predefined, format, charset, raw) { + this.predefined = predefined; + this.format = format; + this.charset = charset; + this.raw = raw; + } + }; + CFFEncoding = class { + constructor(predefined, format, encoding, raw) { + this.predefined = predefined; + this.format = format; + this.encoding = encoding; + this.raw = raw; + } + }; + CFFFDSelect = class { + constructor(format, fdSelect) { + this.format = format; + this.fdSelect = fdSelect; + } + getFDIndex(glyphIndex) { + if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) { + return -1; + } + return this.fdSelect[glyphIndex]; + } + }; + CFFOffsetTracker = class { + constructor() { + this.offsets = /* @__PURE__ */ Object.create(null); + } + isTracking(key) { + return key in this.offsets; + } + track(key, location) { + if (key in this.offsets) { + throw new FormatError3(`Already tracking location of ${key}`); + } + this.offsets[key] = location; + } + offset(value) { + for (const key in this.offsets) { + this.offsets[key] += value; + } + } + setEntryLocation(key, values3, output2) { + if (!(key in this.offsets)) { + throw new FormatError3(`Not tracking location of ${key}`); + } + const data = output2.data; + const dataOffset = this.offsets[key]; + const size3 = 5; + for (let i = 0, ii = values3.length; i < ii; ++i) { + const offset0 = i * size3 + dataOffset; + const offset1 = offset0 + 1; + const offset2 = offset0 + 2; + const offset3 = offset0 + 3; + const offset4 = offset0 + 4; + if (data[offset0] !== 29 || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) { + throw new FormatError3("writing to an offset that is not empty"); + } + const value = values3[i]; + data[offset0] = 29; + data[offset1] = value >> 24 & 255; + data[offset2] = value >> 16 & 255; + data[offset3] = value >> 8 & 255; + data[offset4] = value & 255; + } + } + }; + CFFCompiler = class _CFFCompiler { + constructor(cff) { + this.cff = cff; + } + compile() { + const cff = this.cff; + const output2 = { + data: [], + length: 0, + add(data) { + try { + this.data.push(...data); + } catch { + this.data = this.data.concat(data); + } + this.length = this.data.length; + } + }; + const header = this.compileHeader(cff.header); + output2.add(header); + const nameIndex = this.compileNameIndex(cff.names); + output2.add(nameIndex); + if (cff.isCIDFont) { + if (cff.topDict.hasName("FontMatrix")) { + const base = cff.topDict.getByName("FontMatrix"); + cff.topDict.removeByName("FontMatrix"); + for (const subDict of cff.fdArray) { + let matrix = base.slice(0); + if (subDict.hasName("FontMatrix")) { + matrix = Util2.transform(matrix, subDict.getByName("FontMatrix")); + } + subDict.setByName("FontMatrix", matrix); + } + } + } + const xuid = cff.topDict.getByName("XUID"); + if (xuid?.length > 16) { + cff.topDict.removeByName("XUID"); + } + cff.topDict.setByName("charset", 0); + let compiled = this.compileTopDicts([cff.topDict], output2.length, cff.isCIDFont); + output2.add(compiled.output); + const topDictTracker = compiled.trackers[0]; + const stringIndex = this.compileStringIndex(cff.strings.strings); + output2.add(stringIndex); + const globalSubrIndex = this.compileIndex(cff.globalSubrIndex); + output2.add(globalSubrIndex); + if (cff.encoding && cff.topDict.hasName("Encoding")) { + if (cff.encoding.predefined) { + topDictTracker.setEntryLocation("Encoding", [cff.encoding.format], output2); + } else { + const encoding = this.compileEncoding(cff.encoding); + topDictTracker.setEntryLocation("Encoding", [output2.length], output2); + output2.add(encoding); + } + } + const charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont); + topDictTracker.setEntryLocation("charset", [output2.length], output2); + output2.add(charset); + const charStrings = this.compileCharStrings(cff.charStrings); + topDictTracker.setEntryLocation("CharStrings", [output2.length], output2); + output2.add(charStrings); + if (cff.isCIDFont) { + topDictTracker.setEntryLocation("FDSelect", [output2.length], output2); + const fdSelect = this.compileFDSelect(cff.fdSelect); + output2.add(fdSelect); + compiled = this.compileTopDicts(cff.fdArray, output2.length, true); + topDictTracker.setEntryLocation("FDArray", [output2.length], output2); + output2.add(compiled.output); + const fontDictTrackers = compiled.trackers; + this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output2); + } + this.compilePrivateDicts([cff.topDict], [topDictTracker], output2); + output2.add([0]); + return output2.data; + } + encodeNumber(value) { + if (Number.isInteger(value)) { + return this.encodeInteger(value); + } + return this.encodeFloat(value); + } + static get EncodeFloatRegExp() { + return shadow2(this, "EncodeFloatRegExp", /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/); + } + encodeFloat(num) { + let value = num.toString(); + const m = _CFFCompiler.EncodeFloatRegExp.exec(value); + if (m) { + const epsilon = parseFloat("1e" + ((m[2] ? +m[2] : 0) + m[1].length)); + value = (Math.round(num * epsilon) / epsilon).toString(); + } + let nibbles = ""; + let i, ii; + for (i = 0, ii = value.length; i < ii; ++i) { + const a = value[i]; + if (a === "e") { + nibbles += value[++i] === "-" ? "c" : "b"; + } else if (a === ".") { + nibbles += "a"; + } else if (a === "-") { + nibbles += "e"; + } else { + nibbles += a; + } + } + nibbles += nibbles.length & 1 ? "f" : "ff"; + const out = [30]; + for (i = 0, ii = nibbles.length; i < ii; i += 2) { + out.push(parseInt(nibbles.substring(i, i + 2), 16)); + } + return out; + } + encodeInteger(value) { + let code; + if (value >= -107 && value <= 107) { + code = [value + 139]; + } else if (value >= 108 && value <= 1131) { + value -= 108; + code = [(value >> 8) + 247, value & 255]; + } else if (value >= -1131 && value <= -108) { + value = -value - 108; + code = [(value >> 8) + 251, value & 255]; + } else if (value >= -32768 && value <= 32767) { + code = [28, value >> 8 & 255, value & 255]; + } else { + code = [29, value >> 24 & 255, value >> 16 & 255, value >> 8 & 255, value & 255]; + } + return code; + } + compileHeader(header) { + return [header.major, header.minor, 4, header.offSize]; + } + compileNameIndex(names) { + const nameIndex = new CFFIndex(); + for (const name of names) { + const length = Math.min(name.length, 127); + let sanitizedName = new Array(length); + for (let j = 0; j < length; j++) { + let char2 = name[j]; + if (char2 < "!" || char2 > "~" || char2 === "[" || char2 === "]" || char2 === "(" || char2 === ")" || char2 === "{" || char2 === "}" || char2 === "<" || char2 === ">" || char2 === "/" || char2 === "%") { + char2 = "_"; + } + sanitizedName[j] = char2; + } + sanitizedName = sanitizedName.join(""); + if (sanitizedName === "") { + sanitizedName = "Bad_Font_Name"; + } + nameIndex.add(stringToBytes2(sanitizedName)); + } + return this.compileIndex(nameIndex); + } + compileTopDicts(dicts, length, removeCidKeys) { + const fontDictTrackers = []; + let fdArrayIndex = new CFFIndex(); + for (const fontDict of dicts) { + if (removeCidKeys) { + fontDict.removeByName("CIDFontVersion"); + fontDict.removeByName("CIDFontRevision"); + fontDict.removeByName("CIDFontType"); + fontDict.removeByName("CIDCount"); + fontDict.removeByName("UIDBase"); + } + const fontDictTracker = new CFFOffsetTracker(); + const fontDictData = this.compileDict(fontDict, fontDictTracker); + fontDictTrackers.push(fontDictTracker); + fdArrayIndex.add(fontDictData); + fontDictTracker.offset(length); + } + fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers); + return { + trackers: fontDictTrackers, + output: fdArrayIndex + }; + } + compilePrivateDicts(dicts, trackers, output2) { + for (let i = 0, ii = dicts.length; i < ii; ++i) { + const fontDict = dicts[i]; + const privateDict = fontDict.privateDict; + if (!privateDict || !fontDict.hasName("Private")) { + throw new FormatError3("There must be a private dictionary."); + } + const privateDictTracker = new CFFOffsetTracker(); + const privateDictData = this.compileDict(privateDict, privateDictTracker); + let outputLength = output2.length; + privateDictTracker.offset(outputLength); + if (!privateDictData.length) { + outputLength = 0; + } + trackers[i].setEntryLocation("Private", [privateDictData.length, outputLength], output2); + output2.add(privateDictData); + if (privateDict.subrsIndex && privateDict.hasName("Subrs")) { + const subrs = this.compileIndex(privateDict.subrsIndex); + privateDictTracker.setEntryLocation("Subrs", [privateDictData.length], output2); + output2.add(subrs); + } + } + } + compileDict(dict, offsetTracker) { + const out = []; + for (const key of dict.order) { + if (!(key in dict.values)) { + continue; + } + let values3 = dict.values[key]; + let types3 = dict.types[key]; + if (!Array.isArray(types3)) { + types3 = [types3]; + } + if (!Array.isArray(values3)) { + values3 = [values3]; + } + if (values3.length === 0) { + continue; + } + for (let j = 0, jj = types3.length; j < jj; ++j) { + const type = types3[j]; + const value = values3[j]; + switch (type) { + case "num": + case "sid": + out.push(...this.encodeNumber(value)); + break; + case "offset": + const name = dict.keyToNameMap[key]; + if (!offsetTracker.isTracking(name)) { + offsetTracker.track(name, out.length); + } + out.push(29, 0, 0, 0, 0); + break; + case "array": + case "delta": + out.push(...this.encodeNumber(value)); + for (let k = 1, kk = values3.length; k < kk; ++k) { + out.push(...this.encodeNumber(values3[k])); + } + break; + default: + throw new FormatError3(`Unknown data type of ${type}`); + } + } + out.push(...dict.opcodes[key]); + } + return out; + } + compileStringIndex(strings) { + const stringIndex = new CFFIndex(); + for (const string4 of strings) { + stringIndex.add(stringToBytes2(string4)); + } + return this.compileIndex(stringIndex); + } + compileCharStrings(charStrings) { + const charStringsIndex = new CFFIndex(); + for (let i = 0; i < charStrings.count; i++) { + const glyph = charStrings.get(i); + if (glyph.length === 0) { + charStringsIndex.add(new Uint8Array([139, 14])); + continue; + } + charStringsIndex.add(glyph); + } + return this.compileIndex(charStringsIndex); + } + compileCharset(charset, numGlyphs, strings, isCIDFont) { + let out; + const numGlyphsLessNotDef = numGlyphs - 1; + if (isCIDFont) { + const nLeft = numGlyphsLessNotDef - 1; + out = new Uint8Array([2, 0, 1, nLeft >> 8 & 255, nLeft & 255]); + } else { + const length = 1 + numGlyphsLessNotDef * 2; + out = new Uint8Array(length); + out[0] = 0; + let charsetIndex = 0; + const numCharsets = charset.charset.length; + let warned = false; + for (let i = 1; i < out.length; i += 2) { + let sid = 0; + if (charsetIndex < numCharsets) { + const name = charset.charset[charsetIndex++]; + sid = strings.getSID(name); + if (sid === -1) { + sid = 0; + if (!warned) { + warned = true; + warn2(`Couldn't find ${name} in CFF strings`); + } + } + } + out[i] = sid >> 8 & 255; + out[i + 1] = sid & 255; + } + } + return this.compileTypedArray(out); + } + compileEncoding(encoding) { + return this.compileTypedArray(encoding.raw); + } + compileFDSelect(fdSelect) { + const format = fdSelect.format; + let out, i; + switch (format) { + case 0: + out = new Uint8Array(1 + fdSelect.fdSelect.length); + out[0] = format; + for (i = 0; i < fdSelect.fdSelect.length; i++) { + out[i + 1] = fdSelect.fdSelect[i]; + } + break; + case 3: + const start = 0; + let lastFD = fdSelect.fdSelect[0]; + const ranges = [format, 0, 0, start >> 8 & 255, start & 255, lastFD]; + for (i = 1; i < fdSelect.fdSelect.length; i++) { + const currentFD = fdSelect.fdSelect[i]; + if (currentFD !== lastFD) { + ranges.push(i >> 8 & 255, i & 255, currentFD); + lastFD = currentFD; + } + } + const numRanges = (ranges.length - 3) / 3; + ranges[1] = numRanges >> 8 & 255; + ranges[2] = numRanges & 255; + ranges.push(i >> 8 & 255, i & 255); + out = new Uint8Array(ranges); + break; + } + return this.compileTypedArray(out); + } + compileTypedArray(data) { + return Array.from(data); + } + compileIndex(index2, trackers = []) { + const objects = index2.objects; + const count = objects.length; + if (count === 0) { + return [0, 0]; + } + const data = [count >> 8 & 255, count & 255]; + let lastOffset = 1, i; + for (i = 0; i < count; ++i) { + lastOffset += objects[i].length; + } + let offsetSize; + if (lastOffset < 256) { + offsetSize = 1; + } else if (lastOffset < 65536) { + offsetSize = 2; + } else if (lastOffset < 16777216) { + offsetSize = 3; + } else { + offsetSize = 4; + } + data.push(offsetSize); + let relativeOffset = 1; + for (i = 0; i < count + 1; i++) { + if (offsetSize === 1) { + data.push(relativeOffset & 255); + } else if (offsetSize === 2) { + data.push(relativeOffset >> 8 & 255, relativeOffset & 255); + } else if (offsetSize === 3) { + data.push(relativeOffset >> 16 & 255, relativeOffset >> 8 & 255, relativeOffset & 255); + } else { + data.push(relativeOffset >>> 24 & 255, relativeOffset >> 16 & 255, relativeOffset >> 8 & 255, relativeOffset & 255); + } + if (objects[i]) { + relativeOffset += objects[i].length; + } + } + for (i = 0; i < count; i++) { + if (trackers[i]) { + trackers[i].offset(data.length); + } + data.push(...objects[i]); + } + return data; + } + }; + getStdFontMap = getLookupTableFactory(function(t) { + t["Times-Roman"] = "Times-Roman"; + t.Helvetica = "Helvetica"; + t.Courier = "Courier"; + t.Symbol = "Symbol"; + t["Times-Bold"] = "Times-Bold"; + t["Helvetica-Bold"] = "Helvetica-Bold"; + t["Courier-Bold"] = "Courier-Bold"; + t.ZapfDingbats = "ZapfDingbats"; + t["Times-Italic"] = "Times-Italic"; + t["Helvetica-Oblique"] = "Helvetica-Oblique"; + t["Courier-Oblique"] = "Courier-Oblique"; + t["Times-BoldItalic"] = "Times-BoldItalic"; + t["Helvetica-BoldOblique"] = "Helvetica-BoldOblique"; + t["Courier-BoldOblique"] = "Courier-BoldOblique"; + t.ArialNarrow = "Helvetica"; + t["ArialNarrow-Bold"] = "Helvetica-Bold"; + t["ArialNarrow-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialNarrow-Italic"] = "Helvetica-Oblique"; + t.ArialBlack = "Helvetica"; + t["ArialBlack-Bold"] = "Helvetica-Bold"; + t["ArialBlack-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialBlack-Italic"] = "Helvetica-Oblique"; + t["Arial-Black"] = "Helvetica"; + t["Arial-Black-Bold"] = "Helvetica-Bold"; + t["Arial-Black-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-Black-Italic"] = "Helvetica-Oblique"; + t.Arial = "Helvetica"; + t["Arial-Bold"] = "Helvetica-Bold"; + t["Arial-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-Italic"] = "Helvetica-Oblique"; + t.ArialMT = "Helvetica"; + t["Arial-BoldItalicMT"] = "Helvetica-BoldOblique"; + t["Arial-BoldMT"] = "Helvetica-Bold"; + t["Arial-ItalicMT"] = "Helvetica-Oblique"; + t["Arial-BoldItalicMT-BoldItalic"] = "Helvetica-BoldOblique"; + t["Arial-BoldMT-Bold"] = "Helvetica-Bold"; + t["Arial-ItalicMT-Italic"] = "Helvetica-Oblique"; + t.ArialUnicodeMS = "Helvetica"; + t["ArialUnicodeMS-Bold"] = "Helvetica-Bold"; + t["ArialUnicodeMS-BoldItalic"] = "Helvetica-BoldOblique"; + t["ArialUnicodeMS-Italic"] = "Helvetica-Oblique"; + t["Courier-BoldItalic"] = "Courier-BoldOblique"; + t["Courier-Italic"] = "Courier-Oblique"; + t.CourierNew = "Courier"; + t["CourierNew-Bold"] = "Courier-Bold"; + t["CourierNew-BoldItalic"] = "Courier-BoldOblique"; + t["CourierNew-Italic"] = "Courier-Oblique"; + t["CourierNewPS-BoldItalicMT"] = "Courier-BoldOblique"; + t["CourierNewPS-BoldMT"] = "Courier-Bold"; + t["CourierNewPS-ItalicMT"] = "Courier-Oblique"; + t.CourierNewPSMT = "Courier"; + t["Helvetica-BoldItalic"] = "Helvetica-BoldOblique"; + t["Helvetica-Italic"] = "Helvetica-Oblique"; + t["HelveticaLTStd-Bold"] = "Helvetica-Bold"; + t["Symbol-Bold"] = "Symbol"; + t["Symbol-BoldItalic"] = "Symbol"; + t["Symbol-Italic"] = "Symbol"; + t.TimesNewRoman = "Times-Roman"; + t["TimesNewRoman-Bold"] = "Times-Bold"; + t["TimesNewRoman-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRoman-Italic"] = "Times-Italic"; + t.TimesNewRomanPS = "Times-Roman"; + t["TimesNewRomanPS-Bold"] = "Times-Bold"; + t["TimesNewRomanPS-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRomanPS-BoldItalicMT"] = "Times-BoldItalic"; + t["TimesNewRomanPS-BoldMT"] = "Times-Bold"; + t["TimesNewRomanPS-Italic"] = "Times-Italic"; + t["TimesNewRomanPS-ItalicMT"] = "Times-Italic"; + t.TimesNewRomanPSMT = "Times-Roman"; + t["TimesNewRomanPSMT-Bold"] = "Times-Bold"; + t["TimesNewRomanPSMT-BoldItalic"] = "Times-BoldItalic"; + t["TimesNewRomanPSMT-Italic"] = "Times-Italic"; + }); + getFontNameToFileMap = getLookupTableFactory(function(t) { + t.Courier = "FoxitFixed.pfb"; + t["Courier-Bold"] = "FoxitFixedBold.pfb"; + t["Courier-BoldOblique"] = "FoxitFixedBoldItalic.pfb"; + t["Courier-Oblique"] = "FoxitFixedItalic.pfb"; + t.Helvetica = "LiberationSans-Regular.ttf"; + t["Helvetica-Bold"] = "LiberationSans-Bold.ttf"; + t["Helvetica-BoldOblique"] = "LiberationSans-BoldItalic.ttf"; + t["Helvetica-Oblique"] = "LiberationSans-Italic.ttf"; + t["Times-Roman"] = "FoxitSerif.pfb"; + t["Times-Bold"] = "FoxitSerifBold.pfb"; + t["Times-BoldItalic"] = "FoxitSerifBoldItalic.pfb"; + t["Times-Italic"] = "FoxitSerifItalic.pfb"; + t.Symbol = "FoxitSymbol.pfb"; + t.ZapfDingbats = "FoxitDingbats.pfb"; + t["LiberationSans-Regular"] = "LiberationSans-Regular.ttf"; + t["LiberationSans-Bold"] = "LiberationSans-Bold.ttf"; + t["LiberationSans-Italic"] = "LiberationSans-Italic.ttf"; + t["LiberationSans-BoldItalic"] = "LiberationSans-BoldItalic.ttf"; + }); + getNonStdFontMap = getLookupTableFactory(function(t) { + t.Calibri = "Helvetica"; + t["Calibri-Bold"] = "Helvetica-Bold"; + t["Calibri-BoldItalic"] = "Helvetica-BoldOblique"; + t["Calibri-Italic"] = "Helvetica-Oblique"; + t.CenturyGothic = "Helvetica"; + t["CenturyGothic-Bold"] = "Helvetica-Bold"; + t["CenturyGothic-BoldItalic"] = "Helvetica-BoldOblique"; + t["CenturyGothic-Italic"] = "Helvetica-Oblique"; + t.ComicSansMS = "Comic Sans MS"; + t["ComicSansMS-Bold"] = "Comic Sans MS-Bold"; + t["ComicSansMS-BoldItalic"] = "Comic Sans MS-BoldItalic"; + t["ComicSansMS-Italic"] = "Comic Sans MS-Italic"; + t.GillSansMT = "Helvetica"; + t["GillSansMT-Bold"] = "Helvetica-Bold"; + t["GillSansMT-BoldItalic"] = "Helvetica-BoldOblique"; + t["GillSansMT-Italic"] = "Helvetica-Oblique"; + t.Impact = "Helvetica"; + t["ItcSymbol-Bold"] = "Helvetica-Bold"; + t["ItcSymbol-BoldItalic"] = "Helvetica-BoldOblique"; + t["ItcSymbol-Book"] = "Helvetica"; + t["ItcSymbol-BookItalic"] = "Helvetica-Oblique"; + t["ItcSymbol-Medium"] = "Helvetica"; + t["ItcSymbol-MediumItalic"] = "Helvetica-Oblique"; + t.LucidaConsole = "Courier"; + t["LucidaConsole-Bold"] = "Courier-Bold"; + t["LucidaConsole-BoldItalic"] = "Courier-BoldOblique"; + t["LucidaConsole-Italic"] = "Courier-Oblique"; + t["LucidaSans-Demi"] = "Helvetica-Bold"; + t["MS-Gothic"] = "MS Gothic"; + t["MS-Gothic-Bold"] = "MS Gothic-Bold"; + t["MS-Gothic-BoldItalic"] = "MS Gothic-BoldItalic"; + t["MS-Gothic-Italic"] = "MS Gothic-Italic"; + t["MS-Mincho"] = "MS Mincho"; + t["MS-Mincho-Bold"] = "MS Mincho-Bold"; + t["MS-Mincho-BoldItalic"] = "MS Mincho-BoldItalic"; + t["MS-Mincho-Italic"] = "MS Mincho-Italic"; + t["MS-PGothic"] = "MS PGothic"; + t["MS-PGothic-Bold"] = "MS PGothic-Bold"; + t["MS-PGothic-BoldItalic"] = "MS PGothic-BoldItalic"; + t["MS-PGothic-Italic"] = "MS PGothic-Italic"; + t["MS-PMincho"] = "MS PMincho"; + t["MS-PMincho-Bold"] = "MS PMincho-Bold"; + t["MS-PMincho-BoldItalic"] = "MS PMincho-BoldItalic"; + t["MS-PMincho-Italic"] = "MS PMincho-Italic"; + t.NuptialScript = "Times-Italic"; + t.SegoeUISymbol = "Helvetica"; + }); + getSerifFonts = getLookupTableFactory(function(t) { + t["Adobe Jenson"] = true; + t["Adobe Text"] = true; + t.Albertus = true; + t.Aldus = true; + t.Alexandria = true; + t.Algerian = true; + t["American Typewriter"] = true; + t.Antiqua = true; + t.Apex = true; + t.Arno = true; + t.Aster = true; + t.Aurora = true; + t.Baskerville = true; + t.Bell = true; + t.Bembo = true; + t["Bembo Schoolbook"] = true; + t.Benguiat = true; + t["Berkeley Old Style"] = true; + t["Bernhard Modern"] = true; + t["Berthold City"] = true; + t.Bodoni = true; + t["Bauer Bodoni"] = true; + t["Book Antiqua"] = true; + t.Bookman = true; + t["Bordeaux Roman"] = true; + t["Californian FB"] = true; + t.Calisto = true; + t.Calvert = true; + t.Capitals = true; + t.Cambria = true; + t.Cartier = true; + t.Caslon = true; + t.Catull = true; + t.Centaur = true; + t["Century Old Style"] = true; + t["Century Schoolbook"] = true; + t.Chaparral = true; + t["Charis SIL"] = true; + t.Cheltenham = true; + t["Cholla Slab"] = true; + t.Clarendon = true; + t.Clearface = true; + t.Cochin = true; + t.Colonna = true; + t["Computer Modern"] = true; + t["Concrete Roman"] = true; + t.Constantia = true; + t["Cooper Black"] = true; + t.Corona = true; + t.Ecotype = true; + t.Egyptienne = true; + t.Elephant = true; + t.Excelsior = true; + t.Fairfield = true; + t["FF Scala"] = true; + t.Folkard = true; + t.Footlight = true; + t.FreeSerif = true; + t["Friz Quadrata"] = true; + t.Garamond = true; + t.Gentium = true; + t.Georgia = true; + t.Gloucester = true; + t["Goudy Old Style"] = true; + t["Goudy Schoolbook"] = true; + t["Goudy Pro Font"] = true; + t.Granjon = true; + t["Guardian Egyptian"] = true; + t.Heather = true; + t.Hercules = true; + t["High Tower Text"] = true; + t.Hiroshige = true; + t["Hoefler Text"] = true; + t["Humana Serif"] = true; + t.Imprint = true; + t["Ionic No. 5"] = true; + t.Janson = true; + t.Joanna = true; + t.Korinna = true; + t.Lexicon = true; + t.LiberationSerif = true; + t["Liberation Serif"] = true; + t["Linux Libertine"] = true; + t.Literaturnaya = true; + t.Lucida = true; + t["Lucida Bright"] = true; + t.Melior = true; + t.Memphis = true; + t.Miller = true; + t.Minion = true; + t.Modern = true; + t["Mona Lisa"] = true; + t["Mrs Eaves"] = true; + t["MS Serif"] = true; + t["Museo Slab"] = true; + t["New York"] = true; + t["Nimbus Roman"] = true; + t["NPS Rawlinson Roadway"] = true; + t.NuptialScript = true; + t.Palatino = true; + t.Perpetua = true; + t.Plantin = true; + t["Plantin Schoolbook"] = true; + t.Playbill = true; + t["Poor Richard"] = true; + t["Rawlinson Roadway"] = true; + t.Renault = true; + t.Requiem = true; + t.Rockwell = true; + t.Roman = true; + t["Rotis Serif"] = true; + t.Sabon = true; + t.Scala = true; + t.Seagull = true; + t.Sistina = true; + t.Souvenir = true; + t.STIX = true; + t["Stone Informal"] = true; + t["Stone Serif"] = true; + t.Sylfaen = true; + t.Times = true; + t.Trajan = true; + t["Trinit\xE9"] = true; + t["Trump Mediaeval"] = true; + t.Utopia = true; + t["Vale Type"] = true; + t["Bitstream Vera"] = true; + t["Vera Serif"] = true; + t.Versailles = true; + t.Wanted = true; + t.Weiss = true; + t["Wide Latin"] = true; + t.Windsor = true; + t.XITS = true; + }); + getSymbolsFonts = getLookupTableFactory(function(t) { + t.Dingbats = true; + t.Symbol = true; + t.ZapfDingbats = true; + t.Wingdings = true; + t["Wingdings-Bold"] = true; + t["Wingdings-Regular"] = true; + }); + getGlyphMapForStandardFonts = getLookupTableFactory(function(t) { + t[2] = 10; + t[3] = 32; + t[4] = 33; + t[5] = 34; + t[6] = 35; + t[7] = 36; + t[8] = 37; + t[9] = 38; + t[10] = 39; + t[11] = 40; + t[12] = 41; + t[13] = 42; + t[14] = 43; + t[15] = 44; + t[16] = 45; + t[17] = 46; + t[18] = 47; + t[19] = 48; + t[20] = 49; + t[21] = 50; + t[22] = 51; + t[23] = 52; + t[24] = 53; + t[25] = 54; + t[26] = 55; + t[27] = 56; + t[28] = 57; + t[29] = 58; + t[30] = 894; + t[31] = 60; + t[32] = 61; + t[33] = 62; + t[34] = 63; + t[35] = 64; + t[36] = 65; + t[37] = 66; + t[38] = 67; + t[39] = 68; + t[40] = 69; + t[41] = 70; + t[42] = 71; + t[43] = 72; + t[44] = 73; + t[45] = 74; + t[46] = 75; + t[47] = 76; + t[48] = 77; + t[49] = 78; + t[50] = 79; + t[51] = 80; + t[52] = 81; + t[53] = 82; + t[54] = 83; + t[55] = 84; + t[56] = 85; + t[57] = 86; + t[58] = 87; + t[59] = 88; + t[60] = 89; + t[61] = 90; + t[62] = 91; + t[63] = 92; + t[64] = 93; + t[65] = 94; + t[66] = 95; + t[67] = 96; + t[68] = 97; + t[69] = 98; + t[70] = 99; + t[71] = 100; + t[72] = 101; + t[73] = 102; + t[74] = 103; + t[75] = 104; + t[76] = 105; + t[77] = 106; + t[78] = 107; + t[79] = 108; + t[80] = 109; + t[81] = 110; + t[82] = 111; + t[83] = 112; + t[84] = 113; + t[85] = 114; + t[86] = 115; + t[87] = 116; + t[88] = 117; + t[89] = 118; + t[90] = 119; + t[91] = 120; + t[92] = 121; + t[93] = 122; + t[94] = 123; + t[95] = 124; + t[96] = 125; + t[97] = 126; + t[98] = 196; + t[99] = 197; + t[100] = 199; + t[101] = 201; + t[102] = 209; + t[103] = 214; + t[104] = 220; + t[105] = 225; + t[106] = 224; + t[107] = 226; + t[108] = 228; + t[109] = 227; + t[110] = 229; + t[111] = 231; + t[112] = 233; + t[113] = 232; + t[114] = 234; + t[115] = 235; + t[116] = 237; + t[117] = 236; + t[118] = 238; + t[119] = 239; + t[120] = 241; + t[121] = 243; + t[122] = 242; + t[123] = 244; + t[124] = 246; + t[125] = 245; + t[126] = 250; + t[127] = 249; + t[128] = 251; + t[129] = 252; + t[130] = 8224; + t[131] = 176; + t[132] = 162; + t[133] = 163; + t[134] = 167; + t[135] = 8226; + t[136] = 182; + t[137] = 223; + t[138] = 174; + t[139] = 169; + t[140] = 8482; + t[141] = 180; + t[142] = 168; + t[143] = 8800; + t[144] = 198; + t[145] = 216; + t[146] = 8734; + t[147] = 177; + t[148] = 8804; + t[149] = 8805; + t[150] = 165; + t[151] = 181; + t[152] = 8706; + t[153] = 8721; + t[154] = 8719; + t[156] = 8747; + t[157] = 170; + t[158] = 186; + t[159] = 8486; + t[160] = 230; + t[161] = 248; + t[162] = 191; + t[163] = 161; + t[164] = 172; + t[165] = 8730; + t[166] = 402; + t[167] = 8776; + t[168] = 8710; + t[169] = 171; + t[170] = 187; + t[171] = 8230; + t[179] = 8220; + t[180] = 8221; + t[181] = 8216; + t[182] = 8217; + t[200] = 193; + t[203] = 205; + t[207] = 211; + t[210] = 218; + t[223] = 711; + t[224] = 321; + t[225] = 322; + t[226] = 352; + t[227] = 353; + t[228] = 381; + t[229] = 382; + t[233] = 221; + t[234] = 253; + t[252] = 263; + t[253] = 268; + t[254] = 269; + t[258] = 258; + t[260] = 260; + t[261] = 261; + t[265] = 280; + t[266] = 281; + t[267] = 282; + t[268] = 283; + t[269] = 313; + t[275] = 323; + t[276] = 324; + t[278] = 328; + t[283] = 344; + t[284] = 345; + t[285] = 346; + t[286] = 347; + t[292] = 367; + t[295] = 377; + t[296] = 378; + t[298] = 380; + t[305] = 963; + t[306] = 964; + t[307] = 966; + t[308] = 8215; + t[309] = 8252; + t[310] = 8319; + t[311] = 8359; + t[312] = 8592; + t[313] = 8593; + t[337] = 9552; + t[493] = 1039; + t[494] = 1040; + t[570] = 1040; + t[571] = 1041; + t[572] = 1042; + t[573] = 1043; + t[574] = 1044; + t[575] = 1045; + t[576] = 1046; + t[577] = 1047; + t[578] = 1048; + t[579] = 1049; + t[580] = 1050; + t[581] = 1051; + t[582] = 1052; + t[583] = 1053; + t[584] = 1054; + t[585] = 1055; + t[586] = 1056; + t[587] = 1057; + t[588] = 1058; + t[589] = 1059; + t[590] = 1060; + t[591] = 1061; + t[592] = 1062; + t[593] = 1063; + t[594] = 1064; + t[595] = 1065; + t[596] = 1066; + t[597] = 1067; + t[598] = 1068; + t[599] = 1069; + t[600] = 1070; + t[672] = 1488; + t[673] = 1489; + t[674] = 1490; + t[675] = 1491; + t[676] = 1492; + t[677] = 1493; + t[678] = 1494; + t[679] = 1495; + t[680] = 1496; + t[681] = 1497; + t[682] = 1498; + t[683] = 1499; + t[684] = 1500; + t[685] = 1501; + t[686] = 1502; + t[687] = 1503; + t[688] = 1504; + t[689] = 1505; + t[690] = 1506; + t[691] = 1507; + t[692] = 1508; + t[693] = 1509; + t[694] = 1510; + t[695] = 1511; + t[696] = 1512; + t[697] = 1513; + t[698] = 1514; + t[705] = 1524; + t[706] = 8362; + t[710] = 64288; + t[711] = 64298; + t[759] = 1617; + t[761] = 1776; + t[763] = 1778; + t[775] = 1652; + t[777] = 1764; + t[778] = 1780; + t[779] = 1781; + t[780] = 1782; + t[782] = 771; + t[783] = 64726; + t[786] = 8363; + t[788] = 8532; + t[790] = 768; + t[791] = 769; + t[792] = 768; + t[795] = 803; + t[797] = 64336; + t[798] = 64337; + t[799] = 64342; + t[800] = 64343; + t[801] = 64344; + t[802] = 64345; + t[803] = 64362; + t[804] = 64363; + t[805] = 64364; + t[2424] = 7821; + t[2425] = 7822; + t[2426] = 7823; + t[2427] = 7824; + t[2428] = 7825; + t[2429] = 7826; + t[2430] = 7827; + t[2433] = 7682; + t[2678] = 8045; + t[2679] = 8046; + t[2830] = 1552; + t[2838] = 686; + t[2840] = 751; + t[2842] = 753; + t[2843] = 754; + t[2844] = 755; + t[2846] = 757; + t[2856] = 767; + t[2857] = 848; + t[2858] = 849; + t[2862] = 853; + t[2863] = 854; + t[2864] = 855; + t[2865] = 861; + t[2866] = 862; + t[2906] = 7460; + t[2908] = 7462; + t[2909] = 7463; + t[2910] = 7464; + t[2912] = 7466; + t[2913] = 7467; + t[2914] = 7468; + t[2916] = 7470; + t[2917] = 7471; + t[2918] = 7472; + t[2920] = 7474; + t[2921] = 7475; + t[2922] = 7476; + t[2924] = 7478; + t[2925] = 7479; + t[2926] = 7480; + t[2928] = 7482; + t[2929] = 7483; + t[2930] = 7484; + t[2932] = 7486; + t[2933] = 7487; + t[2934] = 7488; + t[2936] = 7490; + t[2937] = 7491; + t[2938] = 7492; + t[2940] = 7494; + t[2941] = 7495; + t[2942] = 7496; + t[2944] = 7498; + t[2946] = 7500; + t[2948] = 7502; + t[2950] = 7504; + t[2951] = 7505; + t[2952] = 7506; + t[2954] = 7508; + t[2955] = 7509; + t[2956] = 7510; + t[2958] = 7512; + t[2959] = 7513; + t[2960] = 7514; + t[2962] = 7516; + t[2963] = 7517; + t[2964] = 7518; + t[2966] = 7520; + t[2967] = 7521; + t[2968] = 7522; + t[2970] = 7524; + t[2971] = 7525; + t[2972] = 7526; + t[2974] = 7528; + t[2975] = 7529; + t[2976] = 7530; + t[2978] = 1537; + t[2979] = 1538; + t[2980] = 1539; + t[2982] = 1549; + t[2983] = 1551; + t[2984] = 1552; + t[2986] = 1554; + t[2987] = 1555; + t[2988] = 1556; + t[2990] = 1623; + t[2991] = 1624; + t[2995] = 1775; + t[2999] = 1791; + t[3002] = 64290; + t[3003] = 64291; + t[3004] = 64292; + t[3006] = 64294; + t[3007] = 64295; + t[3008] = 64296; + t[3011] = 1900; + t[3014] = 8223; + t[3015] = 8244; + t[3017] = 7532; + t[3018] = 7533; + t[3019] = 7534; + t[3075] = 7590; + t[3076] = 7591; + t[3079] = 7594; + t[3080] = 7595; + t[3083] = 7598; + t[3084] = 7599; + t[3087] = 7602; + t[3088] = 7603; + t[3091] = 7606; + t[3092] = 7607; + t[3095] = 7610; + t[3096] = 7611; + t[3099] = 7614; + t[3100] = 7615; + t[3103] = 7618; + t[3104] = 7619; + t[3107] = 8337; + t[3108] = 8338; + t[3116] = 1884; + t[3119] = 1885; + t[3120] = 1885; + t[3123] = 1886; + t[3124] = 1886; + t[3127] = 1887; + t[3128] = 1887; + t[3131] = 1888; + t[3132] = 1888; + t[3135] = 1889; + t[3136] = 1889; + t[3139] = 1890; + t[3140] = 1890; + t[3143] = 1891; + t[3144] = 1891; + t[3147] = 1892; + t[3148] = 1892; + t[3153] = 580; + t[3154] = 581; + t[3157] = 584; + t[3158] = 585; + t[3161] = 588; + t[3162] = 589; + t[3165] = 891; + t[3166] = 892; + t[3169] = 1274; + t[3170] = 1275; + t[3173] = 1278; + t[3174] = 1279; + t[3181] = 7622; + t[3182] = 7623; + t[3282] = 11799; + t[3316] = 578; + t[3379] = 42785; + t[3393] = 1159; + t[3416] = 8377; + }); + getSupplementalGlyphMapForArialBlack = getLookupTableFactory(function(t) { + t[227] = 322; + t[264] = 261; + t[291] = 346; + }); + getSupplementalGlyphMapForCalibri = getLookupTableFactory(function(t) { + t[1] = 32; + t[4] = 65; + t[5] = 192; + t[6] = 193; + t[9] = 196; + t[17] = 66; + t[18] = 67; + t[21] = 268; + t[24] = 68; + t[28] = 69; + t[29] = 200; + t[30] = 201; + t[32] = 282; + t[38] = 70; + t[39] = 71; + t[44] = 72; + t[47] = 73; + t[48] = 204; + t[49] = 205; + t[58] = 74; + t[60] = 75; + t[62] = 76; + t[68] = 77; + t[69] = 78; + t[75] = 79; + t[76] = 210; + t[80] = 214; + t[87] = 80; + t[89] = 81; + t[90] = 82; + t[92] = 344; + t[94] = 83; + t[97] = 352; + t[100] = 84; + t[104] = 85; + t[109] = 220; + t[115] = 86; + t[116] = 87; + t[121] = 88; + t[122] = 89; + t[124] = 221; + t[127] = 90; + t[129] = 381; + t[258] = 97; + t[259] = 224; + t[260] = 225; + t[263] = 228; + t[268] = 261; + t[271] = 98; + t[272] = 99; + t[273] = 263; + t[275] = 269; + t[282] = 100; + t[286] = 101; + t[287] = 232; + t[288] = 233; + t[290] = 283; + t[295] = 281; + t[296] = 102; + t[336] = 103; + t[346] = 104; + t[349] = 105; + t[350] = 236; + t[351] = 237; + t[361] = 106; + t[364] = 107; + t[367] = 108; + t[371] = 322; + t[373] = 109; + t[374] = 110; + t[381] = 111; + t[382] = 242; + t[383] = 243; + t[386] = 246; + t[393] = 112; + t[395] = 113; + t[396] = 114; + t[398] = 345; + t[400] = 115; + t[401] = 347; + t[403] = 353; + t[410] = 116; + t[437] = 117; + t[442] = 252; + t[448] = 118; + t[449] = 119; + t[454] = 120; + t[455] = 121; + t[457] = 253; + t[460] = 122; + t[462] = 382; + t[463] = 380; + t[853] = 44; + t[855] = 58; + t[856] = 46; + t[876] = 47; + t[878] = 45; + t[882] = 45; + t[894] = 40; + t[895] = 41; + t[896] = 91; + t[897] = 93; + t[923] = 64; + t[940] = 163; + t[1004] = 48; + t[1005] = 49; + t[1006] = 50; + t[1007] = 51; + t[1008] = 52; + t[1009] = 53; + t[1010] = 54; + t[1011] = 55; + t[1012] = 56; + t[1013] = 57; + t[1081] = 37; + t[1085] = 43; + t[1086] = 45; + }); + ToUnicodeMap = class { + constructor(cmap = []) { + this._map = cmap; + } + get length() { + return this._map.length; + } + forEach(callback) { + for (const charCode in this._map) { + callback(charCode, this._map[charCode].codePointAt(0)); + } + } + has(i) { + return this._map[i] !== void 0; + } + get(i) { + return this._map[i]; + } + charCodeOf(value) { + const map3 = this._map; + if (map3.length <= 65536) { + return map3.indexOf(value); + } + for (const charCode in map3) { + if (map3[charCode] === value) { + return charCode | 0; + } + } + return -1; + } + amend(map3) { + for (const charCode in map3) { + this._map[charCode] = map3[charCode]; + } + } + }; + IdentityToUnicodeMap = class { + constructor(firstChar, lastChar) { + this.firstChar = firstChar; + this.lastChar = lastChar; + } + get length() { + return this.lastChar + 1 - this.firstChar; + } + forEach(callback) { + for (let i = this.firstChar, ii = this.lastChar; i <= ii; i++) { + callback(i, i); + } + } + has(i) { + return this.firstChar <= i && i <= this.lastChar; + } + get(i) { + if (this.firstChar <= i && i <= this.lastChar) { + return String.fromCharCode(i); + } + return void 0; + } + charCodeOf(v) { + return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1; + } + amend(map3) { + unreachable2("Should not call amend()"); + } + }; + CFFFont = class { + constructor(file2, properties) { + this.properties = properties; + const parser = new CFFParser(file2, properties, SEAC_ANALYSIS_ENABLED); + this.cff = parser.parse(); + this.cff.duplicateFirstGlyph(); + const compiler = new CFFCompiler(this.cff); + this.seacs = this.cff.seacs; + try { + this.data = compiler.compile(); + } catch { + warn2("Failed to compile font " + properties.loadedName); + this.data = file2; + } + this._createBuiltInEncoding(); + } + get numGlyphs() { + return this.cff.charStrings.count; + } + getCharset() { + return this.cff.charset.charset; + } + getGlyphMapping() { + const cff = this.cff; + const properties = this.properties; + const { + cidToGidMap, + cMap + } = properties; + const charsets = cff.charset.charset; + let charCodeToGlyphId; + let glyphId; + if (properties.composite) { + let invCidToGidMap; + if (cidToGidMap?.length > 0) { + invCidToGidMap = /* @__PURE__ */ Object.create(null); + for (let i = 0, ii = cidToGidMap.length; i < ii; i++) { + const gid = cidToGidMap[i]; + if (gid !== void 0) { + invCidToGidMap[gid] = i; + } + } + } + charCodeToGlyphId = /* @__PURE__ */ Object.create(null); + let charCode; + if (cff.isCIDFont) { + for (glyphId = 0; glyphId < charsets.length; glyphId++) { + const cid = charsets[glyphId]; + charCode = cMap.charCodeOf(cid); + if (invCidToGidMap?.[charCode] !== void 0) { + charCode = invCidToGidMap[charCode]; + } + charCodeToGlyphId[charCode] = glyphId; + } + } else { + for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) { + charCode = cMap.charCodeOf(glyphId); + charCodeToGlyphId[charCode] = glyphId; + } + } + return charCodeToGlyphId; + } + let encoding = cff.encoding ? cff.encoding.encoding : null; + if (properties.isInternalFont) { + encoding = properties.defaultEncoding; + } + charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets); + return charCodeToGlyphId; + } + hasGlyphId(id) { + return this.cff.hasGlyphId(id); + } + _createBuiltInEncoding() { + const { + charset, + encoding + } = this.cff; + if (!charset || !encoding) { + return; + } + const charsets = charset.charset, encodings = encoding.encoding; + const map3 = []; + for (const charCode in encodings) { + const glyphId = encodings[charCode]; + if (glyphId >= 0) { + const glyphName = charsets[glyphId]; + if (glyphName) { + map3[charCode] = glyphName; + } + } + } + if (map3.length > 0) { + this.properties.builtInEncoding = map3; + } + } + }; + NOOP = ""; + Commands = class { + cmds = []; + transformStack = []; + currentTransform = [1, 0, 0, 1, 0, 0]; + add(cmd, args) { + if (args) { + const { + currentTransform + } = this; + for (let i = 0, ii = args.length; i < ii; i += 2) { + Util2.applyTransform(args, currentTransform, i); + } + this.cmds.push(`${cmd}${args.join(" ")}`); + } else { + this.cmds.push(cmd); + } + } + transform(transf) { + this.currentTransform = Util2.transform(this.currentTransform, transf); + } + translate(x, y) { + this.transform([1, 0, 0, 1, x, y]); + } + save() { + this.transformStack.push(this.currentTransform.slice()); + } + restore() { + this.currentTransform = this.transformStack.pop() || [1, 0, 0, 1, 0, 0]; + } + getSVG() { + return this.cmds.join(""); + } + }; + CompiledFont = class { + constructor(fontMatrix) { + this.fontMatrix = fontMatrix; + this.compiledGlyphs = /* @__PURE__ */ Object.create(null); + this.compiledCharCodeToGlyphId = /* @__PURE__ */ Object.create(null); + } + getPathJs(unicode) { + const { + charCode, + glyphId + } = lookupCmap(this.cmap, unicode); + let fn = this.compiledGlyphs[glyphId], compileEx; + if (fn === void 0) { + try { + fn = this.compileGlyph(this.glyphs[glyphId], glyphId); + } catch (ex) { + fn = NOOP; + compileEx = ex; + } + this.compiledGlyphs[glyphId] = fn; + } + this.compiledCharCodeToGlyphId[charCode] ??= glyphId; + if (compileEx) { + throw compileEx; + } + return fn; + } + compileGlyph(code, glyphId) { + if (!code?.length || code[0] === 14) { + return NOOP; + } + let fontMatrix = this.fontMatrix; + if (this.isCFFCIDFont) { + const fdIndex = this.fdSelect.getFDIndex(glyphId); + if (fdIndex >= 0 && fdIndex < this.fdArray.length) { + const fontDict = this.fdArray[fdIndex]; + fontMatrix = fontDict.getByName("FontMatrix") || FONT_IDENTITY_MATRIX2; + } else { + warn2("Invalid fd index for glyph index."); + } + } + assert3(isNumberArray(fontMatrix, 6), "Expected a valid fontMatrix."); + const cmds = new Commands(); + cmds.transform(fontMatrix.slice()); + this.compileGlyphImpl(code, cmds, glyphId); + cmds.add("Z"); + return cmds.getSVG(); + } + compileGlyphImpl() { + unreachable2("Children classes should implement this."); + } + hasBuiltPath(unicode) { + const { + charCode, + glyphId + } = lookupCmap(this.cmap, unicode); + return this.compiledGlyphs[glyphId] !== void 0 && this.compiledCharCodeToGlyphId[charCode] !== void 0; + } + }; + TrueTypeCompiled = class extends CompiledFont { + constructor(glyphs, cmap, fontMatrix) { + super(fontMatrix || [488e-6, 0, 0, 488e-6, 0, 0]); + this.glyphs = glyphs; + this.cmap = cmap; + } + compileGlyphImpl(code, cmds) { + compileGlyf(code, cmds, this); + } + }; + Type2Compiled = class extends CompiledFont { + constructor(cffInfo, cmap, fontMatrix) { + super(fontMatrix || [1e-3, 0, 0, 1e-3, 0, 0]); + this.glyphs = cffInfo.glyphs; + this.gsubrs = cffInfo.gsubrs || []; + this.subrs = cffInfo.subrs || []; + this.cmap = cmap; + this.glyphNameMap = getGlyphsUnicode(); + this.gsubrsBias = getSubroutineBias(this.gsubrs); + this.subrsBias = getSubroutineBias(this.subrs); + this.isCFFCIDFont = cffInfo.isCFFCIDFont; + this.fdSelect = cffInfo.fdSelect; + this.fdArray = cffInfo.fdArray; + } + compileGlyphImpl(code, cmds, glyphId) { + compileCharString(code, cmds, this, glyphId); + } + }; + FontRendererFactory = class { + static create(font, seacAnalysisEnabled) { + const data = new Uint8Array(font.data); + let cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm; + const numTables = readUint16(data, 4); + for (let i = 0, p = 12; i < numTables; i++, p += 16) { + const tag2 = bytesToString2(data.subarray(p, p + 4)); + const offset = readUint32(data, p + 8); + const length = readUint32(data, p + 12); + switch (tag2) { + case "cmap": + cmap = parseCmap(data, offset, offset + length); + break; + case "glyf": + glyf = data.subarray(offset, offset + length); + break; + case "loca": + loca = data.subarray(offset, offset + length); + break; + case "head": + unitsPerEm = readUint16(data, offset + 18); + indexToLocFormat = readUint16(data, offset + 50); + break; + case "CFF ": + cff = parseCff(data, offset, offset + length, seacAnalysisEnabled); + break; + } + } + if (glyf) { + const fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]; + return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix); + } + return new Type2Compiled(cff, cmap, font.fontMatrix); + } + }; + getMetrics = getLookupTableFactory(function(t) { + t.Courier = 600; + t["Courier-Bold"] = 600; + t["Courier-BoldOblique"] = 600; + t["Courier-Oblique"] = 600; + t.Helvetica = getLookupTableFactory(function(t2) { + t2.space = 278; + t2.exclam = 278; + t2.quotedbl = 355; + t2.numbersign = 556; + t2.dollar = 556; + t2.percent = 889; + t2.ampersand = 667; + t2.quoteright = 222; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 389; + t2.plus = 584; + t2.comma = 278; + t2.hyphen = 333; + t2.period = 278; + t2.slash = 278; + t2.zero = 556; + t2.one = 556; + t2.two = 556; + t2.three = 556; + t2.four = 556; + t2.five = 556; + t2.six = 556; + t2.seven = 556; + t2.eight = 556; + t2.nine = 556; + t2.colon = 278; + t2.semicolon = 278; + t2.less = 584; + t2.equal = 584; + t2.greater = 584; + t2.question = 556; + t2.at = 1015; + t2.A = 667; + t2.B = 667; + t2.C = 722; + t2.D = 722; + t2.E = 667; + t2.F = 611; + t2.G = 778; + t2.H = 722; + t2.I = 278; + t2.J = 500; + t2.K = 667; + t2.L = 556; + t2.M = 833; + t2.N = 722; + t2.O = 778; + t2.P = 667; + t2.Q = 778; + t2.R = 722; + t2.S = 667; + t2.T = 611; + t2.U = 722; + t2.V = 667; + t2.W = 944; + t2.X = 667; + t2.Y = 667; + t2.Z = 611; + t2.bracketleft = 278; + t2.backslash = 278; + t2.bracketright = 278; + t2.asciicircum = 469; + t2.underscore = 556; + t2.quoteleft = 222; + t2.a = 556; + t2.b = 556; + t2.c = 500; + t2.d = 556; + t2.e = 556; + t2.f = 278; + t2.g = 556; + t2.h = 556; + t2.i = 222; + t2.j = 222; + t2.k = 500; + t2.l = 222; + t2.m = 833; + t2.n = 556; + t2.o = 556; + t2.p = 556; + t2.q = 556; + t2.r = 333; + t2.s = 500; + t2.t = 278; + t2.u = 556; + t2.v = 500; + t2.w = 722; + t2.x = 500; + t2.y = 500; + t2.z = 500; + t2.braceleft = 334; + t2.bar = 260; + t2.braceright = 334; + t2.asciitilde = 584; + t2.exclamdown = 333; + t2.cent = 556; + t2.sterling = 556; + t2.fraction = 167; + t2.yen = 556; + t2.florin = 556; + t2.section = 556; + t2.currency = 556; + t2.quotesingle = 191; + t2.quotedblleft = 333; + t2.guillemotleft = 556; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 500; + t2.fl = 500; + t2.endash = 556; + t2.dagger = 556; + t2.daggerdbl = 556; + t2.periodcentered = 278; + t2.paragraph = 537; + t2.bullet = 350; + t2.quotesinglbase = 222; + t2.quotedblbase = 333; + t2.quotedblright = 333; + t2.guillemotright = 556; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 611; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 1e3; + t2.ordfeminine = 370; + t2.Lslash = 556; + t2.Oslash = 778; + t2.OE = 1e3; + t2.ordmasculine = 365; + t2.ae = 889; + t2.dotlessi = 278; + t2.lslash = 222; + t2.oslash = 611; + t2.oe = 944; + t2.germandbls = 611; + t2.Idieresis = 278; + t2.eacute = 556; + t2.abreve = 556; + t2.uhungarumlaut = 556; + t2.ecaron = 556; + t2.Ydieresis = 667; + t2.divide = 584; + t2.Yacute = 667; + t2.Acircumflex = 667; + t2.aacute = 556; + t2.Ucircumflex = 722; + t2.yacute = 500; + t2.scommaaccent = 500; + t2.ecircumflex = 556; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 556; + t2.Uacute = 722; + t2.uogonek = 556; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 737; + t2.Emacron = 667; + t2.ccaron = 500; + t2.aring = 556; + t2.Ncommaaccent = 722; + t2.lacute = 222; + t2.agrave = 556; + t2.Tcommaaccent = 611; + t2.Cacute = 722; + t2.atilde = 556; + t2.Edotaccent = 667; + t2.scaron = 500; + t2.scedilla = 500; + t2.iacute = 278; + t2.lozenge = 471; + t2.Rcaron = 722; + t2.Gcommaaccent = 778; + t2.ucircumflex = 556; + t2.acircumflex = 556; + t2.Amacron = 667; + t2.rcaron = 333; + t2.ccedilla = 500; + t2.Zdotaccent = 611; + t2.Thorn = 667; + t2.Omacron = 778; + t2.Racute = 722; + t2.Sacute = 667; + t2.dcaron = 643; + t2.Umacron = 722; + t2.uring = 556; + t2.threesuperior = 333; + t2.Ograve = 778; + t2.Agrave = 667; + t2.Abreve = 667; + t2.multiply = 584; + t2.uacute = 556; + t2.Tcaron = 611; + t2.partialdiff = 476; + t2.ydieresis = 500; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 556; + t2.edieresis = 556; + t2.cacute = 500; + t2.nacute = 556; + t2.umacron = 556; + t2.Ncaron = 722; + t2.Iacute = 278; + t2.plusminus = 584; + t2.brokenbar = 260; + t2.registered = 737; + t2.Gbreve = 778; + t2.Idotaccent = 278; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 333; + t2.omacron = 556; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 722; + t2.lcommaaccent = 222; + t2.tcaron = 317; + t2.eogonek = 556; + t2.Uogonek = 722; + t2.Aacute = 667; + t2.Adieresis = 667; + t2.egrave = 556; + t2.zacute = 500; + t2.iogonek = 222; + t2.Oacute = 778; + t2.oacute = 556; + t2.amacron = 556; + t2.sacute = 500; + t2.idieresis = 278; + t2.Ocircumflex = 778; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 556; + t2.twosuperior = 333; + t2.Odieresis = 778; + t2.mu = 556; + t2.igrave = 278; + t2.ohungarumlaut = 556; + t2.Eogonek = 667; + t2.dcroat = 556; + t2.threequarters = 834; + t2.Scedilla = 667; + t2.lcaron = 299; + t2.Kcommaaccent = 667; + t2.Lacute = 556; + t2.trademark = 1e3; + t2.edotaccent = 556; + t2.Igrave = 278; + t2.Imacron = 278; + t2.Lcaron = 556; + t2.onehalf = 834; + t2.lessequal = 549; + t2.ocircumflex = 556; + t2.ntilde = 556; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 556; + t2.gbreve = 556; + t2.onequarter = 834; + t2.Scaron = 667; + t2.Scommaaccent = 667; + t2.Ohungarumlaut = 778; + t2.degree = 400; + t2.ograve = 556; + t2.Ccaron = 722; + t2.ugrave = 556; + t2.radical = 453; + t2.Dcaron = 722; + t2.rcommaaccent = 333; + t2.Ntilde = 722; + t2.otilde = 556; + t2.Rcommaaccent = 722; + t2.Lcommaaccent = 556; + t2.Atilde = 667; + t2.Aogonek = 667; + t2.Aring = 667; + t2.Otilde = 778; + t2.zdotaccent = 500; + t2.Ecaron = 667; + t2.Iogonek = 278; + t2.kcommaaccent = 500; + t2.minus = 584; + t2.Icircumflex = 278; + t2.ncaron = 556; + t2.tcommaaccent = 278; + t2.logicalnot = 584; + t2.odieresis = 556; + t2.udieresis = 556; + t2.notequal = 549; + t2.gcommaaccent = 556; + t2.eth = 556; + t2.zcaron = 500; + t2.ncommaaccent = 556; + t2.onesuperior = 333; + t2.imacron = 278; + t2.Euro = 556; + }); + t["Helvetica-Bold"] = getLookupTableFactory(function(t2) { + t2.space = 278; + t2.exclam = 333; + t2.quotedbl = 474; + t2.numbersign = 556; + t2.dollar = 556; + t2.percent = 889; + t2.ampersand = 722; + t2.quoteright = 278; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 389; + t2.plus = 584; + t2.comma = 278; + t2.hyphen = 333; + t2.period = 278; + t2.slash = 278; + t2.zero = 556; + t2.one = 556; + t2.two = 556; + t2.three = 556; + t2.four = 556; + t2.five = 556; + t2.six = 556; + t2.seven = 556; + t2.eight = 556; + t2.nine = 556; + t2.colon = 333; + t2.semicolon = 333; + t2.less = 584; + t2.equal = 584; + t2.greater = 584; + t2.question = 611; + t2.at = 975; + t2.A = 722; + t2.B = 722; + t2.C = 722; + t2.D = 722; + t2.E = 667; + t2.F = 611; + t2.G = 778; + t2.H = 722; + t2.I = 278; + t2.J = 556; + t2.K = 722; + t2.L = 611; + t2.M = 833; + t2.N = 722; + t2.O = 778; + t2.P = 667; + t2.Q = 778; + t2.R = 722; + t2.S = 667; + t2.T = 611; + t2.U = 722; + t2.V = 667; + t2.W = 944; + t2.X = 667; + t2.Y = 667; + t2.Z = 611; + t2.bracketleft = 333; + t2.backslash = 278; + t2.bracketright = 333; + t2.asciicircum = 584; + t2.underscore = 556; + t2.quoteleft = 278; + t2.a = 556; + t2.b = 611; + t2.c = 556; + t2.d = 611; + t2.e = 556; + t2.f = 333; + t2.g = 611; + t2.h = 611; + t2.i = 278; + t2.j = 278; + t2.k = 556; + t2.l = 278; + t2.m = 889; + t2.n = 611; + t2.o = 611; + t2.p = 611; + t2.q = 611; + t2.r = 389; + t2.s = 556; + t2.t = 333; + t2.u = 611; + t2.v = 556; + t2.w = 778; + t2.x = 556; + t2.y = 556; + t2.z = 500; + t2.braceleft = 389; + t2.bar = 280; + t2.braceright = 389; + t2.asciitilde = 584; + t2.exclamdown = 333; + t2.cent = 556; + t2.sterling = 556; + t2.fraction = 167; + t2.yen = 556; + t2.florin = 556; + t2.section = 556; + t2.currency = 556; + t2.quotesingle = 238; + t2.quotedblleft = 500; + t2.guillemotleft = 556; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 611; + t2.fl = 611; + t2.endash = 556; + t2.dagger = 556; + t2.daggerdbl = 556; + t2.periodcentered = 278; + t2.paragraph = 556; + t2.bullet = 350; + t2.quotesinglbase = 278; + t2.quotedblbase = 500; + t2.quotedblright = 500; + t2.guillemotright = 556; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 611; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 1e3; + t2.ordfeminine = 370; + t2.Lslash = 611; + t2.Oslash = 778; + t2.OE = 1e3; + t2.ordmasculine = 365; + t2.ae = 889; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 611; + t2.oe = 944; + t2.germandbls = 611; + t2.Idieresis = 278; + t2.eacute = 556; + t2.abreve = 556; + t2.uhungarumlaut = 611; + t2.ecaron = 556; + t2.Ydieresis = 667; + t2.divide = 584; + t2.Yacute = 667; + t2.Acircumflex = 722; + t2.aacute = 556; + t2.Ucircumflex = 722; + t2.yacute = 556; + t2.scommaaccent = 556; + t2.ecircumflex = 556; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 556; + t2.Uacute = 722; + t2.uogonek = 611; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 737; + t2.Emacron = 667; + t2.ccaron = 556; + t2.aring = 556; + t2.Ncommaaccent = 722; + t2.lacute = 278; + t2.agrave = 556; + t2.Tcommaaccent = 611; + t2.Cacute = 722; + t2.atilde = 556; + t2.Edotaccent = 667; + t2.scaron = 556; + t2.scedilla = 556; + t2.iacute = 278; + t2.lozenge = 494; + t2.Rcaron = 722; + t2.Gcommaaccent = 778; + t2.ucircumflex = 611; + t2.acircumflex = 556; + t2.Amacron = 722; + t2.rcaron = 389; + t2.ccedilla = 556; + t2.Zdotaccent = 611; + t2.Thorn = 667; + t2.Omacron = 778; + t2.Racute = 722; + t2.Sacute = 667; + t2.dcaron = 743; + t2.Umacron = 722; + t2.uring = 611; + t2.threesuperior = 333; + t2.Ograve = 778; + t2.Agrave = 722; + t2.Abreve = 722; + t2.multiply = 584; + t2.uacute = 611; + t2.Tcaron = 611; + t2.partialdiff = 494; + t2.ydieresis = 556; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 556; + t2.edieresis = 556; + t2.cacute = 556; + t2.nacute = 611; + t2.umacron = 611; + t2.Ncaron = 722; + t2.Iacute = 278; + t2.plusminus = 584; + t2.brokenbar = 280; + t2.registered = 737; + t2.Gbreve = 778; + t2.Idotaccent = 278; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 389; + t2.omacron = 611; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 722; + t2.lcommaaccent = 278; + t2.tcaron = 389; + t2.eogonek = 556; + t2.Uogonek = 722; + t2.Aacute = 722; + t2.Adieresis = 722; + t2.egrave = 556; + t2.zacute = 500; + t2.iogonek = 278; + t2.Oacute = 778; + t2.oacute = 611; + t2.amacron = 556; + t2.sacute = 556; + t2.idieresis = 278; + t2.Ocircumflex = 778; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 611; + t2.twosuperior = 333; + t2.Odieresis = 778; + t2.mu = 611; + t2.igrave = 278; + t2.ohungarumlaut = 611; + t2.Eogonek = 667; + t2.dcroat = 611; + t2.threequarters = 834; + t2.Scedilla = 667; + t2.lcaron = 400; + t2.Kcommaaccent = 722; + t2.Lacute = 611; + t2.trademark = 1e3; + t2.edotaccent = 556; + t2.Igrave = 278; + t2.Imacron = 278; + t2.Lcaron = 611; + t2.onehalf = 834; + t2.lessequal = 549; + t2.ocircumflex = 611; + t2.ntilde = 611; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 556; + t2.gbreve = 611; + t2.onequarter = 834; + t2.Scaron = 667; + t2.Scommaaccent = 667; + t2.Ohungarumlaut = 778; + t2.degree = 400; + t2.ograve = 611; + t2.Ccaron = 722; + t2.ugrave = 611; + t2.radical = 549; + t2.Dcaron = 722; + t2.rcommaaccent = 389; + t2.Ntilde = 722; + t2.otilde = 611; + t2.Rcommaaccent = 722; + t2.Lcommaaccent = 611; + t2.Atilde = 722; + t2.Aogonek = 722; + t2.Aring = 722; + t2.Otilde = 778; + t2.zdotaccent = 500; + t2.Ecaron = 667; + t2.Iogonek = 278; + t2.kcommaaccent = 556; + t2.minus = 584; + t2.Icircumflex = 278; + t2.ncaron = 611; + t2.tcommaaccent = 333; + t2.logicalnot = 584; + t2.odieresis = 611; + t2.udieresis = 611; + t2.notequal = 549; + t2.gcommaaccent = 611; + t2.eth = 611; + t2.zcaron = 500; + t2.ncommaaccent = 611; + t2.onesuperior = 333; + t2.imacron = 278; + t2.Euro = 556; + }); + t["Helvetica-BoldOblique"] = getLookupTableFactory(function(t2) { + t2.space = 278; + t2.exclam = 333; + t2.quotedbl = 474; + t2.numbersign = 556; + t2.dollar = 556; + t2.percent = 889; + t2.ampersand = 722; + t2.quoteright = 278; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 389; + t2.plus = 584; + t2.comma = 278; + t2.hyphen = 333; + t2.period = 278; + t2.slash = 278; + t2.zero = 556; + t2.one = 556; + t2.two = 556; + t2.three = 556; + t2.four = 556; + t2.five = 556; + t2.six = 556; + t2.seven = 556; + t2.eight = 556; + t2.nine = 556; + t2.colon = 333; + t2.semicolon = 333; + t2.less = 584; + t2.equal = 584; + t2.greater = 584; + t2.question = 611; + t2.at = 975; + t2.A = 722; + t2.B = 722; + t2.C = 722; + t2.D = 722; + t2.E = 667; + t2.F = 611; + t2.G = 778; + t2.H = 722; + t2.I = 278; + t2.J = 556; + t2.K = 722; + t2.L = 611; + t2.M = 833; + t2.N = 722; + t2.O = 778; + t2.P = 667; + t2.Q = 778; + t2.R = 722; + t2.S = 667; + t2.T = 611; + t2.U = 722; + t2.V = 667; + t2.W = 944; + t2.X = 667; + t2.Y = 667; + t2.Z = 611; + t2.bracketleft = 333; + t2.backslash = 278; + t2.bracketright = 333; + t2.asciicircum = 584; + t2.underscore = 556; + t2.quoteleft = 278; + t2.a = 556; + t2.b = 611; + t2.c = 556; + t2.d = 611; + t2.e = 556; + t2.f = 333; + t2.g = 611; + t2.h = 611; + t2.i = 278; + t2.j = 278; + t2.k = 556; + t2.l = 278; + t2.m = 889; + t2.n = 611; + t2.o = 611; + t2.p = 611; + t2.q = 611; + t2.r = 389; + t2.s = 556; + t2.t = 333; + t2.u = 611; + t2.v = 556; + t2.w = 778; + t2.x = 556; + t2.y = 556; + t2.z = 500; + t2.braceleft = 389; + t2.bar = 280; + t2.braceright = 389; + t2.asciitilde = 584; + t2.exclamdown = 333; + t2.cent = 556; + t2.sterling = 556; + t2.fraction = 167; + t2.yen = 556; + t2.florin = 556; + t2.section = 556; + t2.currency = 556; + t2.quotesingle = 238; + t2.quotedblleft = 500; + t2.guillemotleft = 556; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 611; + t2.fl = 611; + t2.endash = 556; + t2.dagger = 556; + t2.daggerdbl = 556; + t2.periodcentered = 278; + t2.paragraph = 556; + t2.bullet = 350; + t2.quotesinglbase = 278; + t2.quotedblbase = 500; + t2.quotedblright = 500; + t2.guillemotright = 556; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 611; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 1e3; + t2.ordfeminine = 370; + t2.Lslash = 611; + t2.Oslash = 778; + t2.OE = 1e3; + t2.ordmasculine = 365; + t2.ae = 889; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 611; + t2.oe = 944; + t2.germandbls = 611; + t2.Idieresis = 278; + t2.eacute = 556; + t2.abreve = 556; + t2.uhungarumlaut = 611; + t2.ecaron = 556; + t2.Ydieresis = 667; + t2.divide = 584; + t2.Yacute = 667; + t2.Acircumflex = 722; + t2.aacute = 556; + t2.Ucircumflex = 722; + t2.yacute = 556; + t2.scommaaccent = 556; + t2.ecircumflex = 556; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 556; + t2.Uacute = 722; + t2.uogonek = 611; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 737; + t2.Emacron = 667; + t2.ccaron = 556; + t2.aring = 556; + t2.Ncommaaccent = 722; + t2.lacute = 278; + t2.agrave = 556; + t2.Tcommaaccent = 611; + t2.Cacute = 722; + t2.atilde = 556; + t2.Edotaccent = 667; + t2.scaron = 556; + t2.scedilla = 556; + t2.iacute = 278; + t2.lozenge = 494; + t2.Rcaron = 722; + t2.Gcommaaccent = 778; + t2.ucircumflex = 611; + t2.acircumflex = 556; + t2.Amacron = 722; + t2.rcaron = 389; + t2.ccedilla = 556; + t2.Zdotaccent = 611; + t2.Thorn = 667; + t2.Omacron = 778; + t2.Racute = 722; + t2.Sacute = 667; + t2.dcaron = 743; + t2.Umacron = 722; + t2.uring = 611; + t2.threesuperior = 333; + t2.Ograve = 778; + t2.Agrave = 722; + t2.Abreve = 722; + t2.multiply = 584; + t2.uacute = 611; + t2.Tcaron = 611; + t2.partialdiff = 494; + t2.ydieresis = 556; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 556; + t2.edieresis = 556; + t2.cacute = 556; + t2.nacute = 611; + t2.umacron = 611; + t2.Ncaron = 722; + t2.Iacute = 278; + t2.plusminus = 584; + t2.brokenbar = 280; + t2.registered = 737; + t2.Gbreve = 778; + t2.Idotaccent = 278; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 389; + t2.omacron = 611; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 722; + t2.lcommaaccent = 278; + t2.tcaron = 389; + t2.eogonek = 556; + t2.Uogonek = 722; + t2.Aacute = 722; + t2.Adieresis = 722; + t2.egrave = 556; + t2.zacute = 500; + t2.iogonek = 278; + t2.Oacute = 778; + t2.oacute = 611; + t2.amacron = 556; + t2.sacute = 556; + t2.idieresis = 278; + t2.Ocircumflex = 778; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 611; + t2.twosuperior = 333; + t2.Odieresis = 778; + t2.mu = 611; + t2.igrave = 278; + t2.ohungarumlaut = 611; + t2.Eogonek = 667; + t2.dcroat = 611; + t2.threequarters = 834; + t2.Scedilla = 667; + t2.lcaron = 400; + t2.Kcommaaccent = 722; + t2.Lacute = 611; + t2.trademark = 1e3; + t2.edotaccent = 556; + t2.Igrave = 278; + t2.Imacron = 278; + t2.Lcaron = 611; + t2.onehalf = 834; + t2.lessequal = 549; + t2.ocircumflex = 611; + t2.ntilde = 611; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 556; + t2.gbreve = 611; + t2.onequarter = 834; + t2.Scaron = 667; + t2.Scommaaccent = 667; + t2.Ohungarumlaut = 778; + t2.degree = 400; + t2.ograve = 611; + t2.Ccaron = 722; + t2.ugrave = 611; + t2.radical = 549; + t2.Dcaron = 722; + t2.rcommaaccent = 389; + t2.Ntilde = 722; + t2.otilde = 611; + t2.Rcommaaccent = 722; + t2.Lcommaaccent = 611; + t2.Atilde = 722; + t2.Aogonek = 722; + t2.Aring = 722; + t2.Otilde = 778; + t2.zdotaccent = 500; + t2.Ecaron = 667; + t2.Iogonek = 278; + t2.kcommaaccent = 556; + t2.minus = 584; + t2.Icircumflex = 278; + t2.ncaron = 611; + t2.tcommaaccent = 333; + t2.logicalnot = 584; + t2.odieresis = 611; + t2.udieresis = 611; + t2.notequal = 549; + t2.gcommaaccent = 611; + t2.eth = 611; + t2.zcaron = 500; + t2.ncommaaccent = 611; + t2.onesuperior = 333; + t2.imacron = 278; + t2.Euro = 556; + }); + t["Helvetica-Oblique"] = getLookupTableFactory(function(t2) { + t2.space = 278; + t2.exclam = 278; + t2.quotedbl = 355; + t2.numbersign = 556; + t2.dollar = 556; + t2.percent = 889; + t2.ampersand = 667; + t2.quoteright = 222; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 389; + t2.plus = 584; + t2.comma = 278; + t2.hyphen = 333; + t2.period = 278; + t2.slash = 278; + t2.zero = 556; + t2.one = 556; + t2.two = 556; + t2.three = 556; + t2.four = 556; + t2.five = 556; + t2.six = 556; + t2.seven = 556; + t2.eight = 556; + t2.nine = 556; + t2.colon = 278; + t2.semicolon = 278; + t2.less = 584; + t2.equal = 584; + t2.greater = 584; + t2.question = 556; + t2.at = 1015; + t2.A = 667; + t2.B = 667; + t2.C = 722; + t2.D = 722; + t2.E = 667; + t2.F = 611; + t2.G = 778; + t2.H = 722; + t2.I = 278; + t2.J = 500; + t2.K = 667; + t2.L = 556; + t2.M = 833; + t2.N = 722; + t2.O = 778; + t2.P = 667; + t2.Q = 778; + t2.R = 722; + t2.S = 667; + t2.T = 611; + t2.U = 722; + t2.V = 667; + t2.W = 944; + t2.X = 667; + t2.Y = 667; + t2.Z = 611; + t2.bracketleft = 278; + t2.backslash = 278; + t2.bracketright = 278; + t2.asciicircum = 469; + t2.underscore = 556; + t2.quoteleft = 222; + t2.a = 556; + t2.b = 556; + t2.c = 500; + t2.d = 556; + t2.e = 556; + t2.f = 278; + t2.g = 556; + t2.h = 556; + t2.i = 222; + t2.j = 222; + t2.k = 500; + t2.l = 222; + t2.m = 833; + t2.n = 556; + t2.o = 556; + t2.p = 556; + t2.q = 556; + t2.r = 333; + t2.s = 500; + t2.t = 278; + t2.u = 556; + t2.v = 500; + t2.w = 722; + t2.x = 500; + t2.y = 500; + t2.z = 500; + t2.braceleft = 334; + t2.bar = 260; + t2.braceright = 334; + t2.asciitilde = 584; + t2.exclamdown = 333; + t2.cent = 556; + t2.sterling = 556; + t2.fraction = 167; + t2.yen = 556; + t2.florin = 556; + t2.section = 556; + t2.currency = 556; + t2.quotesingle = 191; + t2.quotedblleft = 333; + t2.guillemotleft = 556; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 500; + t2.fl = 500; + t2.endash = 556; + t2.dagger = 556; + t2.daggerdbl = 556; + t2.periodcentered = 278; + t2.paragraph = 537; + t2.bullet = 350; + t2.quotesinglbase = 222; + t2.quotedblbase = 333; + t2.quotedblright = 333; + t2.guillemotright = 556; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 611; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 1e3; + t2.ordfeminine = 370; + t2.Lslash = 556; + t2.Oslash = 778; + t2.OE = 1e3; + t2.ordmasculine = 365; + t2.ae = 889; + t2.dotlessi = 278; + t2.lslash = 222; + t2.oslash = 611; + t2.oe = 944; + t2.germandbls = 611; + t2.Idieresis = 278; + t2.eacute = 556; + t2.abreve = 556; + t2.uhungarumlaut = 556; + t2.ecaron = 556; + t2.Ydieresis = 667; + t2.divide = 584; + t2.Yacute = 667; + t2.Acircumflex = 667; + t2.aacute = 556; + t2.Ucircumflex = 722; + t2.yacute = 500; + t2.scommaaccent = 500; + t2.ecircumflex = 556; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 556; + t2.Uacute = 722; + t2.uogonek = 556; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 737; + t2.Emacron = 667; + t2.ccaron = 500; + t2.aring = 556; + t2.Ncommaaccent = 722; + t2.lacute = 222; + t2.agrave = 556; + t2.Tcommaaccent = 611; + t2.Cacute = 722; + t2.atilde = 556; + t2.Edotaccent = 667; + t2.scaron = 500; + t2.scedilla = 500; + t2.iacute = 278; + t2.lozenge = 471; + t2.Rcaron = 722; + t2.Gcommaaccent = 778; + t2.ucircumflex = 556; + t2.acircumflex = 556; + t2.Amacron = 667; + t2.rcaron = 333; + t2.ccedilla = 500; + t2.Zdotaccent = 611; + t2.Thorn = 667; + t2.Omacron = 778; + t2.Racute = 722; + t2.Sacute = 667; + t2.dcaron = 643; + t2.Umacron = 722; + t2.uring = 556; + t2.threesuperior = 333; + t2.Ograve = 778; + t2.Agrave = 667; + t2.Abreve = 667; + t2.multiply = 584; + t2.uacute = 556; + t2.Tcaron = 611; + t2.partialdiff = 476; + t2.ydieresis = 500; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 556; + t2.edieresis = 556; + t2.cacute = 500; + t2.nacute = 556; + t2.umacron = 556; + t2.Ncaron = 722; + t2.Iacute = 278; + t2.plusminus = 584; + t2.brokenbar = 260; + t2.registered = 737; + t2.Gbreve = 778; + t2.Idotaccent = 278; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 333; + t2.omacron = 556; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 722; + t2.lcommaaccent = 222; + t2.tcaron = 317; + t2.eogonek = 556; + t2.Uogonek = 722; + t2.Aacute = 667; + t2.Adieresis = 667; + t2.egrave = 556; + t2.zacute = 500; + t2.iogonek = 222; + t2.Oacute = 778; + t2.oacute = 556; + t2.amacron = 556; + t2.sacute = 500; + t2.idieresis = 278; + t2.Ocircumflex = 778; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 556; + t2.twosuperior = 333; + t2.Odieresis = 778; + t2.mu = 556; + t2.igrave = 278; + t2.ohungarumlaut = 556; + t2.Eogonek = 667; + t2.dcroat = 556; + t2.threequarters = 834; + t2.Scedilla = 667; + t2.lcaron = 299; + t2.Kcommaaccent = 667; + t2.Lacute = 556; + t2.trademark = 1e3; + t2.edotaccent = 556; + t2.Igrave = 278; + t2.Imacron = 278; + t2.Lcaron = 556; + t2.onehalf = 834; + t2.lessequal = 549; + t2.ocircumflex = 556; + t2.ntilde = 556; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 556; + t2.gbreve = 556; + t2.onequarter = 834; + t2.Scaron = 667; + t2.Scommaaccent = 667; + t2.Ohungarumlaut = 778; + t2.degree = 400; + t2.ograve = 556; + t2.Ccaron = 722; + t2.ugrave = 556; + t2.radical = 453; + t2.Dcaron = 722; + t2.rcommaaccent = 333; + t2.Ntilde = 722; + t2.otilde = 556; + t2.Rcommaaccent = 722; + t2.Lcommaaccent = 556; + t2.Atilde = 667; + t2.Aogonek = 667; + t2.Aring = 667; + t2.Otilde = 778; + t2.zdotaccent = 500; + t2.Ecaron = 667; + t2.Iogonek = 278; + t2.kcommaaccent = 500; + t2.minus = 584; + t2.Icircumflex = 278; + t2.ncaron = 556; + t2.tcommaaccent = 278; + t2.logicalnot = 584; + t2.odieresis = 556; + t2.udieresis = 556; + t2.notequal = 549; + t2.gcommaaccent = 556; + t2.eth = 556; + t2.zcaron = 500; + t2.ncommaaccent = 556; + t2.onesuperior = 333; + t2.imacron = 278; + t2.Euro = 556; + }); + t.Symbol = getLookupTableFactory(function(t2) { + t2.space = 250; + t2.exclam = 333; + t2.universal = 713; + t2.numbersign = 500; + t2.existential = 549; + t2.percent = 833; + t2.ampersand = 778; + t2.suchthat = 439; + t2.parenleft = 333; + t2.parenright = 333; + t2.asteriskmath = 500; + t2.plus = 549; + t2.comma = 250; + t2.minus = 549; + t2.period = 250; + t2.slash = 278; + t2.zero = 500; + t2.one = 500; + t2.two = 500; + t2.three = 500; + t2.four = 500; + t2.five = 500; + t2.six = 500; + t2.seven = 500; + t2.eight = 500; + t2.nine = 500; + t2.colon = 278; + t2.semicolon = 278; + t2.less = 549; + t2.equal = 549; + t2.greater = 549; + t2.question = 444; + t2.congruent = 549; + t2.Alpha = 722; + t2.Beta = 667; + t2.Chi = 722; + t2.Delta = 612; + t2.Epsilon = 611; + t2.Phi = 763; + t2.Gamma = 603; + t2.Eta = 722; + t2.Iota = 333; + t2.theta1 = 631; + t2.Kappa = 722; + t2.Lambda = 686; + t2.Mu = 889; + t2.Nu = 722; + t2.Omicron = 722; + t2.Pi = 768; + t2.Theta = 741; + t2.Rho = 556; + t2.Sigma = 592; + t2.Tau = 611; + t2.Upsilon = 690; + t2.sigma1 = 439; + t2.Omega = 768; + t2.Xi = 645; + t2.Psi = 795; + t2.Zeta = 611; + t2.bracketleft = 333; + t2.therefore = 863; + t2.bracketright = 333; + t2.perpendicular = 658; + t2.underscore = 500; + t2.radicalex = 500; + t2.alpha = 631; + t2.beta = 549; + t2.chi = 549; + t2.delta = 494; + t2.epsilon = 439; + t2.phi = 521; + t2.gamma = 411; + t2.eta = 603; + t2.iota = 329; + t2.phi1 = 603; + t2.kappa = 549; + t2.lambda = 549; + t2.mu = 576; + t2.nu = 521; + t2.omicron = 549; + t2.pi = 549; + t2.theta = 521; + t2.rho = 549; + t2.sigma = 603; + t2.tau = 439; + t2.upsilon = 576; + t2.omega1 = 713; + t2.omega = 686; + t2.xi = 493; + t2.psi = 686; + t2.zeta = 494; + t2.braceleft = 480; + t2.bar = 200; + t2.braceright = 480; + t2.similar = 549; + t2.Euro = 750; + t2.Upsilon1 = 620; + t2.minute = 247; + t2.lessequal = 549; + t2.fraction = 167; + t2.infinity = 713; + t2.florin = 500; + t2.club = 753; + t2.diamond = 753; + t2.heart = 753; + t2.spade = 753; + t2.arrowboth = 1042; + t2.arrowleft = 987; + t2.arrowup = 603; + t2.arrowright = 987; + t2.arrowdown = 603; + t2.degree = 400; + t2.plusminus = 549; + t2.second = 411; + t2.greaterequal = 549; + t2.multiply = 549; + t2.proportional = 713; + t2.partialdiff = 494; + t2.bullet = 460; + t2.divide = 549; + t2.notequal = 549; + t2.equivalence = 549; + t2.approxequal = 549; + t2.ellipsis = 1e3; + t2.arrowvertex = 603; + t2.arrowhorizex = 1e3; + t2.carriagereturn = 658; + t2.aleph = 823; + t2.Ifraktur = 686; + t2.Rfraktur = 795; + t2.weierstrass = 987; + t2.circlemultiply = 768; + t2.circleplus = 768; + t2.emptyset = 823; + t2.intersection = 768; + t2.union = 768; + t2.propersuperset = 713; + t2.reflexsuperset = 713; + t2.notsubset = 713; + t2.propersubset = 713; + t2.reflexsubset = 713; + t2.element = 713; + t2.notelement = 713; + t2.angle = 768; + t2.gradient = 713; + t2.registerserif = 790; + t2.copyrightserif = 790; + t2.trademarkserif = 890; + t2.product = 823; + t2.radical = 549; + t2.dotmath = 250; + t2.logicalnot = 713; + t2.logicaland = 603; + t2.logicalor = 603; + t2.arrowdblboth = 1042; + t2.arrowdblleft = 987; + t2.arrowdblup = 603; + t2.arrowdblright = 987; + t2.arrowdbldown = 603; + t2.lozenge = 494; + t2.angleleft = 329; + t2.registersans = 790; + t2.copyrightsans = 790; + t2.trademarksans = 786; + t2.summation = 713; + t2.parenlefttp = 384; + t2.parenleftex = 384; + t2.parenleftbt = 384; + t2.bracketlefttp = 384; + t2.bracketleftex = 384; + t2.bracketleftbt = 384; + t2.bracelefttp = 494; + t2.braceleftmid = 494; + t2.braceleftbt = 494; + t2.braceex = 494; + t2.angleright = 329; + t2.integral = 274; + t2.integraltp = 686; + t2.integralex = 686; + t2.integralbt = 686; + t2.parenrighttp = 384; + t2.parenrightex = 384; + t2.parenrightbt = 384; + t2.bracketrighttp = 384; + t2.bracketrightex = 384; + t2.bracketrightbt = 384; + t2.bracerighttp = 494; + t2.bracerightmid = 494; + t2.bracerightbt = 494; + t2.apple = 790; + }); + t["Times-Roman"] = getLookupTableFactory(function(t2) { + t2.space = 250; + t2.exclam = 333; + t2.quotedbl = 408; + t2.numbersign = 500; + t2.dollar = 500; + t2.percent = 833; + t2.ampersand = 778; + t2.quoteright = 333; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 500; + t2.plus = 564; + t2.comma = 250; + t2.hyphen = 333; + t2.period = 250; + t2.slash = 278; + t2.zero = 500; + t2.one = 500; + t2.two = 500; + t2.three = 500; + t2.four = 500; + t2.five = 500; + t2.six = 500; + t2.seven = 500; + t2.eight = 500; + t2.nine = 500; + t2.colon = 278; + t2.semicolon = 278; + t2.less = 564; + t2.equal = 564; + t2.greater = 564; + t2.question = 444; + t2.at = 921; + t2.A = 722; + t2.B = 667; + t2.C = 667; + t2.D = 722; + t2.E = 611; + t2.F = 556; + t2.G = 722; + t2.H = 722; + t2.I = 333; + t2.J = 389; + t2.K = 722; + t2.L = 611; + t2.M = 889; + t2.N = 722; + t2.O = 722; + t2.P = 556; + t2.Q = 722; + t2.R = 667; + t2.S = 556; + t2.T = 611; + t2.U = 722; + t2.V = 722; + t2.W = 944; + t2.X = 722; + t2.Y = 722; + t2.Z = 611; + t2.bracketleft = 333; + t2.backslash = 278; + t2.bracketright = 333; + t2.asciicircum = 469; + t2.underscore = 500; + t2.quoteleft = 333; + t2.a = 444; + t2.b = 500; + t2.c = 444; + t2.d = 500; + t2.e = 444; + t2.f = 333; + t2.g = 500; + t2.h = 500; + t2.i = 278; + t2.j = 278; + t2.k = 500; + t2.l = 278; + t2.m = 778; + t2.n = 500; + t2.o = 500; + t2.p = 500; + t2.q = 500; + t2.r = 333; + t2.s = 389; + t2.t = 278; + t2.u = 500; + t2.v = 500; + t2.w = 722; + t2.x = 500; + t2.y = 500; + t2.z = 444; + t2.braceleft = 480; + t2.bar = 200; + t2.braceright = 480; + t2.asciitilde = 541; + t2.exclamdown = 333; + t2.cent = 500; + t2.sterling = 500; + t2.fraction = 167; + t2.yen = 500; + t2.florin = 500; + t2.section = 500; + t2.currency = 500; + t2.quotesingle = 180; + t2.quotedblleft = 444; + t2.guillemotleft = 500; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 556; + t2.fl = 556; + t2.endash = 500; + t2.dagger = 500; + t2.daggerdbl = 500; + t2.periodcentered = 250; + t2.paragraph = 453; + t2.bullet = 350; + t2.quotesinglbase = 333; + t2.quotedblbase = 444; + t2.quotedblright = 444; + t2.guillemotright = 500; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 444; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 889; + t2.ordfeminine = 276; + t2.Lslash = 611; + t2.Oslash = 722; + t2.OE = 889; + t2.ordmasculine = 310; + t2.ae = 667; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 500; + t2.oe = 722; + t2.germandbls = 500; + t2.Idieresis = 333; + t2.eacute = 444; + t2.abreve = 444; + t2.uhungarumlaut = 500; + t2.ecaron = 444; + t2.Ydieresis = 722; + t2.divide = 564; + t2.Yacute = 722; + t2.Acircumflex = 722; + t2.aacute = 444; + t2.Ucircumflex = 722; + t2.yacute = 500; + t2.scommaaccent = 389; + t2.ecircumflex = 444; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 444; + t2.Uacute = 722; + t2.uogonek = 500; + t2.Edieresis = 611; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 760; + t2.Emacron = 611; + t2.ccaron = 444; + t2.aring = 444; + t2.Ncommaaccent = 722; + t2.lacute = 278; + t2.agrave = 444; + t2.Tcommaaccent = 611; + t2.Cacute = 667; + t2.atilde = 444; + t2.Edotaccent = 611; + t2.scaron = 389; + t2.scedilla = 389; + t2.iacute = 278; + t2.lozenge = 471; + t2.Rcaron = 667; + t2.Gcommaaccent = 722; + t2.ucircumflex = 500; + t2.acircumflex = 444; + t2.Amacron = 722; + t2.rcaron = 333; + t2.ccedilla = 444; + t2.Zdotaccent = 611; + t2.Thorn = 556; + t2.Omacron = 722; + t2.Racute = 667; + t2.Sacute = 556; + t2.dcaron = 588; + t2.Umacron = 722; + t2.uring = 500; + t2.threesuperior = 300; + t2.Ograve = 722; + t2.Agrave = 722; + t2.Abreve = 722; + t2.multiply = 564; + t2.uacute = 500; + t2.Tcaron = 611; + t2.partialdiff = 476; + t2.ydieresis = 500; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 611; + t2.adieresis = 444; + t2.edieresis = 444; + t2.cacute = 444; + t2.nacute = 500; + t2.umacron = 500; + t2.Ncaron = 722; + t2.Iacute = 333; + t2.plusminus = 564; + t2.brokenbar = 200; + t2.registered = 760; + t2.Gbreve = 722; + t2.Idotaccent = 333; + t2.summation = 600; + t2.Egrave = 611; + t2.racute = 333; + t2.omacron = 500; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 667; + t2.lcommaaccent = 278; + t2.tcaron = 326; + t2.eogonek = 444; + t2.Uogonek = 722; + t2.Aacute = 722; + t2.Adieresis = 722; + t2.egrave = 444; + t2.zacute = 444; + t2.iogonek = 278; + t2.Oacute = 722; + t2.oacute = 500; + t2.amacron = 444; + t2.sacute = 389; + t2.idieresis = 278; + t2.Ocircumflex = 722; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 500; + t2.twosuperior = 300; + t2.Odieresis = 722; + t2.mu = 500; + t2.igrave = 278; + t2.ohungarumlaut = 500; + t2.Eogonek = 611; + t2.dcroat = 500; + t2.threequarters = 750; + t2.Scedilla = 556; + t2.lcaron = 344; + t2.Kcommaaccent = 722; + t2.Lacute = 611; + t2.trademark = 980; + t2.edotaccent = 444; + t2.Igrave = 333; + t2.Imacron = 333; + t2.Lcaron = 611; + t2.onehalf = 750; + t2.lessequal = 549; + t2.ocircumflex = 500; + t2.ntilde = 500; + t2.Uhungarumlaut = 722; + t2.Eacute = 611; + t2.emacron = 444; + t2.gbreve = 500; + t2.onequarter = 750; + t2.Scaron = 556; + t2.Scommaaccent = 556; + t2.Ohungarumlaut = 722; + t2.degree = 400; + t2.ograve = 500; + t2.Ccaron = 667; + t2.ugrave = 500; + t2.radical = 453; + t2.Dcaron = 722; + t2.rcommaaccent = 333; + t2.Ntilde = 722; + t2.otilde = 500; + t2.Rcommaaccent = 667; + t2.Lcommaaccent = 611; + t2.Atilde = 722; + t2.Aogonek = 722; + t2.Aring = 722; + t2.Otilde = 722; + t2.zdotaccent = 444; + t2.Ecaron = 611; + t2.Iogonek = 333; + t2.kcommaaccent = 500; + t2.minus = 564; + t2.Icircumflex = 333; + t2.ncaron = 500; + t2.tcommaaccent = 278; + t2.logicalnot = 564; + t2.odieresis = 500; + t2.udieresis = 500; + t2.notequal = 549; + t2.gcommaaccent = 500; + t2.eth = 500; + t2.zcaron = 444; + t2.ncommaaccent = 500; + t2.onesuperior = 300; + t2.imacron = 278; + t2.Euro = 500; + }); + t["Times-Bold"] = getLookupTableFactory(function(t2) { + t2.space = 250; + t2.exclam = 333; + t2.quotedbl = 555; + t2.numbersign = 500; + t2.dollar = 500; + t2.percent = 1e3; + t2.ampersand = 833; + t2.quoteright = 333; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 500; + t2.plus = 570; + t2.comma = 250; + t2.hyphen = 333; + t2.period = 250; + t2.slash = 278; + t2.zero = 500; + t2.one = 500; + t2.two = 500; + t2.three = 500; + t2.four = 500; + t2.five = 500; + t2.six = 500; + t2.seven = 500; + t2.eight = 500; + t2.nine = 500; + t2.colon = 333; + t2.semicolon = 333; + t2.less = 570; + t2.equal = 570; + t2.greater = 570; + t2.question = 500; + t2.at = 930; + t2.A = 722; + t2.B = 667; + t2.C = 722; + t2.D = 722; + t2.E = 667; + t2.F = 611; + t2.G = 778; + t2.H = 778; + t2.I = 389; + t2.J = 500; + t2.K = 778; + t2.L = 667; + t2.M = 944; + t2.N = 722; + t2.O = 778; + t2.P = 611; + t2.Q = 778; + t2.R = 722; + t2.S = 556; + t2.T = 667; + t2.U = 722; + t2.V = 722; + t2.W = 1e3; + t2.X = 722; + t2.Y = 722; + t2.Z = 667; + t2.bracketleft = 333; + t2.backslash = 278; + t2.bracketright = 333; + t2.asciicircum = 581; + t2.underscore = 500; + t2.quoteleft = 333; + t2.a = 500; + t2.b = 556; + t2.c = 444; + t2.d = 556; + t2.e = 444; + t2.f = 333; + t2.g = 500; + t2.h = 556; + t2.i = 278; + t2.j = 333; + t2.k = 556; + t2.l = 278; + t2.m = 833; + t2.n = 556; + t2.o = 500; + t2.p = 556; + t2.q = 556; + t2.r = 444; + t2.s = 389; + t2.t = 333; + t2.u = 556; + t2.v = 500; + t2.w = 722; + t2.x = 500; + t2.y = 500; + t2.z = 444; + t2.braceleft = 394; + t2.bar = 220; + t2.braceright = 394; + t2.asciitilde = 520; + t2.exclamdown = 333; + t2.cent = 500; + t2.sterling = 500; + t2.fraction = 167; + t2.yen = 500; + t2.florin = 500; + t2.section = 500; + t2.currency = 500; + t2.quotesingle = 278; + t2.quotedblleft = 500; + t2.guillemotleft = 500; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 556; + t2.fl = 556; + t2.endash = 500; + t2.dagger = 500; + t2.daggerdbl = 500; + t2.periodcentered = 250; + t2.paragraph = 540; + t2.bullet = 350; + t2.quotesinglbase = 333; + t2.quotedblbase = 500; + t2.quotedblright = 500; + t2.guillemotright = 500; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 500; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 1e3; + t2.ordfeminine = 300; + t2.Lslash = 667; + t2.Oslash = 778; + t2.OE = 1e3; + t2.ordmasculine = 330; + t2.ae = 722; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 500; + t2.oe = 722; + t2.germandbls = 556; + t2.Idieresis = 389; + t2.eacute = 444; + t2.abreve = 500; + t2.uhungarumlaut = 556; + t2.ecaron = 444; + t2.Ydieresis = 722; + t2.divide = 570; + t2.Yacute = 722; + t2.Acircumflex = 722; + t2.aacute = 500; + t2.Ucircumflex = 722; + t2.yacute = 500; + t2.scommaaccent = 389; + t2.ecircumflex = 444; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 500; + t2.Uacute = 722; + t2.uogonek = 556; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 747; + t2.Emacron = 667; + t2.ccaron = 444; + t2.aring = 500; + t2.Ncommaaccent = 722; + t2.lacute = 278; + t2.agrave = 500; + t2.Tcommaaccent = 667; + t2.Cacute = 722; + t2.atilde = 500; + t2.Edotaccent = 667; + t2.scaron = 389; + t2.scedilla = 389; + t2.iacute = 278; + t2.lozenge = 494; + t2.Rcaron = 722; + t2.Gcommaaccent = 778; + t2.ucircumflex = 556; + t2.acircumflex = 500; + t2.Amacron = 722; + t2.rcaron = 444; + t2.ccedilla = 444; + t2.Zdotaccent = 667; + t2.Thorn = 611; + t2.Omacron = 778; + t2.Racute = 722; + t2.Sacute = 556; + t2.dcaron = 672; + t2.Umacron = 722; + t2.uring = 556; + t2.threesuperior = 300; + t2.Ograve = 778; + t2.Agrave = 722; + t2.Abreve = 722; + t2.multiply = 570; + t2.uacute = 556; + t2.Tcaron = 667; + t2.partialdiff = 494; + t2.ydieresis = 500; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 500; + t2.edieresis = 444; + t2.cacute = 444; + t2.nacute = 556; + t2.umacron = 556; + t2.Ncaron = 722; + t2.Iacute = 389; + t2.plusminus = 570; + t2.brokenbar = 220; + t2.registered = 747; + t2.Gbreve = 778; + t2.Idotaccent = 389; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 444; + t2.omacron = 500; + t2.Zacute = 667; + t2.Zcaron = 667; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 722; + t2.lcommaaccent = 278; + t2.tcaron = 416; + t2.eogonek = 444; + t2.Uogonek = 722; + t2.Aacute = 722; + t2.Adieresis = 722; + t2.egrave = 444; + t2.zacute = 444; + t2.iogonek = 278; + t2.Oacute = 778; + t2.oacute = 500; + t2.amacron = 500; + t2.sacute = 389; + t2.idieresis = 278; + t2.Ocircumflex = 778; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 556; + t2.twosuperior = 300; + t2.Odieresis = 778; + t2.mu = 556; + t2.igrave = 278; + t2.ohungarumlaut = 500; + t2.Eogonek = 667; + t2.dcroat = 556; + t2.threequarters = 750; + t2.Scedilla = 556; + t2.lcaron = 394; + t2.Kcommaaccent = 778; + t2.Lacute = 667; + t2.trademark = 1e3; + t2.edotaccent = 444; + t2.Igrave = 389; + t2.Imacron = 389; + t2.Lcaron = 667; + t2.onehalf = 750; + t2.lessequal = 549; + t2.ocircumflex = 500; + t2.ntilde = 556; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 444; + t2.gbreve = 500; + t2.onequarter = 750; + t2.Scaron = 556; + t2.Scommaaccent = 556; + t2.Ohungarumlaut = 778; + t2.degree = 400; + t2.ograve = 500; + t2.Ccaron = 722; + t2.ugrave = 556; + t2.radical = 549; + t2.Dcaron = 722; + t2.rcommaaccent = 444; + t2.Ntilde = 722; + t2.otilde = 500; + t2.Rcommaaccent = 722; + t2.Lcommaaccent = 667; + t2.Atilde = 722; + t2.Aogonek = 722; + t2.Aring = 722; + t2.Otilde = 778; + t2.zdotaccent = 444; + t2.Ecaron = 667; + t2.Iogonek = 389; + t2.kcommaaccent = 556; + t2.minus = 570; + t2.Icircumflex = 389; + t2.ncaron = 556; + t2.tcommaaccent = 333; + t2.logicalnot = 570; + t2.odieresis = 500; + t2.udieresis = 556; + t2.notequal = 549; + t2.gcommaaccent = 500; + t2.eth = 500; + t2.zcaron = 444; + t2.ncommaaccent = 556; + t2.onesuperior = 300; + t2.imacron = 278; + t2.Euro = 500; + }); + t["Times-BoldItalic"] = getLookupTableFactory(function(t2) { + t2.space = 250; + t2.exclam = 389; + t2.quotedbl = 555; + t2.numbersign = 500; + t2.dollar = 500; + t2.percent = 833; + t2.ampersand = 778; + t2.quoteright = 333; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 500; + t2.plus = 570; + t2.comma = 250; + t2.hyphen = 333; + t2.period = 250; + t2.slash = 278; + t2.zero = 500; + t2.one = 500; + t2.two = 500; + t2.three = 500; + t2.four = 500; + t2.five = 500; + t2.six = 500; + t2.seven = 500; + t2.eight = 500; + t2.nine = 500; + t2.colon = 333; + t2.semicolon = 333; + t2.less = 570; + t2.equal = 570; + t2.greater = 570; + t2.question = 500; + t2.at = 832; + t2.A = 667; + t2.B = 667; + t2.C = 667; + t2.D = 722; + t2.E = 667; + t2.F = 667; + t2.G = 722; + t2.H = 778; + t2.I = 389; + t2.J = 500; + t2.K = 667; + t2.L = 611; + t2.M = 889; + t2.N = 722; + t2.O = 722; + t2.P = 611; + t2.Q = 722; + t2.R = 667; + t2.S = 556; + t2.T = 611; + t2.U = 722; + t2.V = 667; + t2.W = 889; + t2.X = 667; + t2.Y = 611; + t2.Z = 611; + t2.bracketleft = 333; + t2.backslash = 278; + t2.bracketright = 333; + t2.asciicircum = 570; + t2.underscore = 500; + t2.quoteleft = 333; + t2.a = 500; + t2.b = 500; + t2.c = 444; + t2.d = 500; + t2.e = 444; + t2.f = 333; + t2.g = 500; + t2.h = 556; + t2.i = 278; + t2.j = 278; + t2.k = 500; + t2.l = 278; + t2.m = 778; + t2.n = 556; + t2.o = 500; + t2.p = 500; + t2.q = 500; + t2.r = 389; + t2.s = 389; + t2.t = 278; + t2.u = 556; + t2.v = 444; + t2.w = 667; + t2.x = 500; + t2.y = 444; + t2.z = 389; + t2.braceleft = 348; + t2.bar = 220; + t2.braceright = 348; + t2.asciitilde = 570; + t2.exclamdown = 389; + t2.cent = 500; + t2.sterling = 500; + t2.fraction = 167; + t2.yen = 500; + t2.florin = 500; + t2.section = 500; + t2.currency = 500; + t2.quotesingle = 278; + t2.quotedblleft = 500; + t2.guillemotleft = 500; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 556; + t2.fl = 556; + t2.endash = 500; + t2.dagger = 500; + t2.daggerdbl = 500; + t2.periodcentered = 250; + t2.paragraph = 500; + t2.bullet = 350; + t2.quotesinglbase = 333; + t2.quotedblbase = 500; + t2.quotedblright = 500; + t2.guillemotright = 500; + t2.ellipsis = 1e3; + t2.perthousand = 1e3; + t2.questiondown = 500; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 1e3; + t2.AE = 944; + t2.ordfeminine = 266; + t2.Lslash = 611; + t2.Oslash = 722; + t2.OE = 944; + t2.ordmasculine = 300; + t2.ae = 722; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 500; + t2.oe = 722; + t2.germandbls = 500; + t2.Idieresis = 389; + t2.eacute = 444; + t2.abreve = 500; + t2.uhungarumlaut = 556; + t2.ecaron = 444; + t2.Ydieresis = 611; + t2.divide = 570; + t2.Yacute = 611; + t2.Acircumflex = 667; + t2.aacute = 500; + t2.Ucircumflex = 722; + t2.yacute = 444; + t2.scommaaccent = 389; + t2.ecircumflex = 444; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 500; + t2.Uacute = 722; + t2.uogonek = 556; + t2.Edieresis = 667; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 747; + t2.Emacron = 667; + t2.ccaron = 444; + t2.aring = 500; + t2.Ncommaaccent = 722; + t2.lacute = 278; + t2.agrave = 500; + t2.Tcommaaccent = 611; + t2.Cacute = 667; + t2.atilde = 500; + t2.Edotaccent = 667; + t2.scaron = 389; + t2.scedilla = 389; + t2.iacute = 278; + t2.lozenge = 494; + t2.Rcaron = 667; + t2.Gcommaaccent = 722; + t2.ucircumflex = 556; + t2.acircumflex = 500; + t2.Amacron = 667; + t2.rcaron = 389; + t2.ccedilla = 444; + t2.Zdotaccent = 611; + t2.Thorn = 611; + t2.Omacron = 722; + t2.Racute = 667; + t2.Sacute = 556; + t2.dcaron = 608; + t2.Umacron = 722; + t2.uring = 556; + t2.threesuperior = 300; + t2.Ograve = 722; + t2.Agrave = 667; + t2.Abreve = 667; + t2.multiply = 570; + t2.uacute = 556; + t2.Tcaron = 611; + t2.partialdiff = 494; + t2.ydieresis = 444; + t2.Nacute = 722; + t2.icircumflex = 278; + t2.Ecircumflex = 667; + t2.adieresis = 500; + t2.edieresis = 444; + t2.cacute = 444; + t2.nacute = 556; + t2.umacron = 556; + t2.Ncaron = 722; + t2.Iacute = 389; + t2.plusminus = 570; + t2.brokenbar = 220; + t2.registered = 747; + t2.Gbreve = 722; + t2.Idotaccent = 389; + t2.summation = 600; + t2.Egrave = 667; + t2.racute = 389; + t2.omacron = 500; + t2.Zacute = 611; + t2.Zcaron = 611; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 667; + t2.lcommaaccent = 278; + t2.tcaron = 366; + t2.eogonek = 444; + t2.Uogonek = 722; + t2.Aacute = 667; + t2.Adieresis = 667; + t2.egrave = 444; + t2.zacute = 389; + t2.iogonek = 278; + t2.Oacute = 722; + t2.oacute = 500; + t2.amacron = 500; + t2.sacute = 389; + t2.idieresis = 278; + t2.Ocircumflex = 722; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 500; + t2.twosuperior = 300; + t2.Odieresis = 722; + t2.mu = 576; + t2.igrave = 278; + t2.ohungarumlaut = 500; + t2.Eogonek = 667; + t2.dcroat = 500; + t2.threequarters = 750; + t2.Scedilla = 556; + t2.lcaron = 382; + t2.Kcommaaccent = 667; + t2.Lacute = 611; + t2.trademark = 1e3; + t2.edotaccent = 444; + t2.Igrave = 389; + t2.Imacron = 389; + t2.Lcaron = 611; + t2.onehalf = 750; + t2.lessequal = 549; + t2.ocircumflex = 500; + t2.ntilde = 556; + t2.Uhungarumlaut = 722; + t2.Eacute = 667; + t2.emacron = 444; + t2.gbreve = 500; + t2.onequarter = 750; + t2.Scaron = 556; + t2.Scommaaccent = 556; + t2.Ohungarumlaut = 722; + t2.degree = 400; + t2.ograve = 500; + t2.Ccaron = 667; + t2.ugrave = 556; + t2.radical = 549; + t2.Dcaron = 722; + t2.rcommaaccent = 389; + t2.Ntilde = 722; + t2.otilde = 500; + t2.Rcommaaccent = 667; + t2.Lcommaaccent = 611; + t2.Atilde = 667; + t2.Aogonek = 667; + t2.Aring = 667; + t2.Otilde = 722; + t2.zdotaccent = 389; + t2.Ecaron = 667; + t2.Iogonek = 389; + t2.kcommaaccent = 500; + t2.minus = 606; + t2.Icircumflex = 389; + t2.ncaron = 556; + t2.tcommaaccent = 278; + t2.logicalnot = 606; + t2.odieresis = 500; + t2.udieresis = 556; + t2.notequal = 549; + t2.gcommaaccent = 500; + t2.eth = 500; + t2.zcaron = 389; + t2.ncommaaccent = 556; + t2.onesuperior = 300; + t2.imacron = 278; + t2.Euro = 500; + }); + t["Times-Italic"] = getLookupTableFactory(function(t2) { + t2.space = 250; + t2.exclam = 333; + t2.quotedbl = 420; + t2.numbersign = 500; + t2.dollar = 500; + t2.percent = 833; + t2.ampersand = 778; + t2.quoteright = 333; + t2.parenleft = 333; + t2.parenright = 333; + t2.asterisk = 500; + t2.plus = 675; + t2.comma = 250; + t2.hyphen = 333; + t2.period = 250; + t2.slash = 278; + t2.zero = 500; + t2.one = 500; + t2.two = 500; + t2.three = 500; + t2.four = 500; + t2.five = 500; + t2.six = 500; + t2.seven = 500; + t2.eight = 500; + t2.nine = 500; + t2.colon = 333; + t2.semicolon = 333; + t2.less = 675; + t2.equal = 675; + t2.greater = 675; + t2.question = 500; + t2.at = 920; + t2.A = 611; + t2.B = 611; + t2.C = 667; + t2.D = 722; + t2.E = 611; + t2.F = 611; + t2.G = 722; + t2.H = 722; + t2.I = 333; + t2.J = 444; + t2.K = 667; + t2.L = 556; + t2.M = 833; + t2.N = 667; + t2.O = 722; + t2.P = 611; + t2.Q = 722; + t2.R = 611; + t2.S = 500; + t2.T = 556; + t2.U = 722; + t2.V = 611; + t2.W = 833; + t2.X = 611; + t2.Y = 556; + t2.Z = 556; + t2.bracketleft = 389; + t2.backslash = 278; + t2.bracketright = 389; + t2.asciicircum = 422; + t2.underscore = 500; + t2.quoteleft = 333; + t2.a = 500; + t2.b = 500; + t2.c = 444; + t2.d = 500; + t2.e = 444; + t2.f = 278; + t2.g = 500; + t2.h = 500; + t2.i = 278; + t2.j = 278; + t2.k = 444; + t2.l = 278; + t2.m = 722; + t2.n = 500; + t2.o = 500; + t2.p = 500; + t2.q = 500; + t2.r = 389; + t2.s = 389; + t2.t = 278; + t2.u = 500; + t2.v = 444; + t2.w = 667; + t2.x = 444; + t2.y = 444; + t2.z = 389; + t2.braceleft = 400; + t2.bar = 275; + t2.braceright = 400; + t2.asciitilde = 541; + t2.exclamdown = 389; + t2.cent = 500; + t2.sterling = 500; + t2.fraction = 167; + t2.yen = 500; + t2.florin = 500; + t2.section = 500; + t2.currency = 500; + t2.quotesingle = 214; + t2.quotedblleft = 556; + t2.guillemotleft = 500; + t2.guilsinglleft = 333; + t2.guilsinglright = 333; + t2.fi = 500; + t2.fl = 500; + t2.endash = 500; + t2.dagger = 500; + t2.daggerdbl = 500; + t2.periodcentered = 250; + t2.paragraph = 523; + t2.bullet = 350; + t2.quotesinglbase = 333; + t2.quotedblbase = 556; + t2.quotedblright = 556; + t2.guillemotright = 500; + t2.ellipsis = 889; + t2.perthousand = 1e3; + t2.questiondown = 500; + t2.grave = 333; + t2.acute = 333; + t2.circumflex = 333; + t2.tilde = 333; + t2.macron = 333; + t2.breve = 333; + t2.dotaccent = 333; + t2.dieresis = 333; + t2.ring = 333; + t2.cedilla = 333; + t2.hungarumlaut = 333; + t2.ogonek = 333; + t2.caron = 333; + t2.emdash = 889; + t2.AE = 889; + t2.ordfeminine = 276; + t2.Lslash = 556; + t2.Oslash = 722; + t2.OE = 944; + t2.ordmasculine = 310; + t2.ae = 667; + t2.dotlessi = 278; + t2.lslash = 278; + t2.oslash = 500; + t2.oe = 667; + t2.germandbls = 500; + t2.Idieresis = 333; + t2.eacute = 444; + t2.abreve = 500; + t2.uhungarumlaut = 500; + t2.ecaron = 444; + t2.Ydieresis = 556; + t2.divide = 675; + t2.Yacute = 556; + t2.Acircumflex = 611; + t2.aacute = 500; + t2.Ucircumflex = 722; + t2.yacute = 444; + t2.scommaaccent = 389; + t2.ecircumflex = 444; + t2.Uring = 722; + t2.Udieresis = 722; + t2.aogonek = 500; + t2.Uacute = 722; + t2.uogonek = 500; + t2.Edieresis = 611; + t2.Dcroat = 722; + t2.commaaccent = 250; + t2.copyright = 760; + t2.Emacron = 611; + t2.ccaron = 444; + t2.aring = 500; + t2.Ncommaaccent = 667; + t2.lacute = 278; + t2.agrave = 500; + t2.Tcommaaccent = 556; + t2.Cacute = 667; + t2.atilde = 500; + t2.Edotaccent = 611; + t2.scaron = 389; + t2.scedilla = 389; + t2.iacute = 278; + t2.lozenge = 471; + t2.Rcaron = 611; + t2.Gcommaaccent = 722; + t2.ucircumflex = 500; + t2.acircumflex = 500; + t2.Amacron = 611; + t2.rcaron = 389; + t2.ccedilla = 444; + t2.Zdotaccent = 556; + t2.Thorn = 611; + t2.Omacron = 722; + t2.Racute = 611; + t2.Sacute = 500; + t2.dcaron = 544; + t2.Umacron = 722; + t2.uring = 500; + t2.threesuperior = 300; + t2.Ograve = 722; + t2.Agrave = 611; + t2.Abreve = 611; + t2.multiply = 675; + t2.uacute = 500; + t2.Tcaron = 556; + t2.partialdiff = 476; + t2.ydieresis = 444; + t2.Nacute = 667; + t2.icircumflex = 278; + t2.Ecircumflex = 611; + t2.adieresis = 500; + t2.edieresis = 444; + t2.cacute = 444; + t2.nacute = 500; + t2.umacron = 500; + t2.Ncaron = 667; + t2.Iacute = 333; + t2.plusminus = 675; + t2.brokenbar = 275; + t2.registered = 760; + t2.Gbreve = 722; + t2.Idotaccent = 333; + t2.summation = 600; + t2.Egrave = 611; + t2.racute = 389; + t2.omacron = 500; + t2.Zacute = 556; + t2.Zcaron = 556; + t2.greaterequal = 549; + t2.Eth = 722; + t2.Ccedilla = 667; + t2.lcommaaccent = 278; + t2.tcaron = 300; + t2.eogonek = 444; + t2.Uogonek = 722; + t2.Aacute = 611; + t2.Adieresis = 611; + t2.egrave = 444; + t2.zacute = 389; + t2.iogonek = 278; + t2.Oacute = 722; + t2.oacute = 500; + t2.amacron = 500; + t2.sacute = 389; + t2.idieresis = 278; + t2.Ocircumflex = 722; + t2.Ugrave = 722; + t2.Delta = 612; + t2.thorn = 500; + t2.twosuperior = 300; + t2.Odieresis = 722; + t2.mu = 500; + t2.igrave = 278; + t2.ohungarumlaut = 500; + t2.Eogonek = 611; + t2.dcroat = 500; + t2.threequarters = 750; + t2.Scedilla = 500; + t2.lcaron = 300; + t2.Kcommaaccent = 667; + t2.Lacute = 556; + t2.trademark = 980; + t2.edotaccent = 444; + t2.Igrave = 333; + t2.Imacron = 333; + t2.Lcaron = 611; + t2.onehalf = 750; + t2.lessequal = 549; + t2.ocircumflex = 500; + t2.ntilde = 500; + t2.Uhungarumlaut = 722; + t2.Eacute = 611; + t2.emacron = 444; + t2.gbreve = 500; + t2.onequarter = 750; + t2.Scaron = 500; + t2.Scommaaccent = 500; + t2.Ohungarumlaut = 722; + t2.degree = 400; + t2.ograve = 500; + t2.Ccaron = 667; + t2.ugrave = 500; + t2.radical = 453; + t2.Dcaron = 722; + t2.rcommaaccent = 389; + t2.Ntilde = 667; + t2.otilde = 500; + t2.Rcommaaccent = 611; + t2.Lcommaaccent = 556; + t2.Atilde = 611; + t2.Aogonek = 611; + t2.Aring = 611; + t2.Otilde = 722; + t2.zdotaccent = 389; + t2.Ecaron = 611; + t2.Iogonek = 333; + t2.kcommaaccent = 444; + t2.minus = 675; + t2.Icircumflex = 333; + t2.ncaron = 500; + t2.tcommaaccent = 278; + t2.logicalnot = 675; + t2.odieresis = 500; + t2.udieresis = 500; + t2.notequal = 549; + t2.gcommaaccent = 500; + t2.eth = 500; + t2.zcaron = 389; + t2.ncommaaccent = 500; + t2.onesuperior = 300; + t2.imacron = 278; + t2.Euro = 500; + }); + t.ZapfDingbats = getLookupTableFactory(function(t2) { + t2.space = 278; + t2.a1 = 974; + t2.a2 = 961; + t2.a202 = 974; + t2.a3 = 980; + t2.a4 = 719; + t2.a5 = 789; + t2.a119 = 790; + t2.a118 = 791; + t2.a117 = 690; + t2.a11 = 960; + t2.a12 = 939; + t2.a13 = 549; + t2.a14 = 855; + t2.a15 = 911; + t2.a16 = 933; + t2.a105 = 911; + t2.a17 = 945; + t2.a18 = 974; + t2.a19 = 755; + t2.a20 = 846; + t2.a21 = 762; + t2.a22 = 761; + t2.a23 = 571; + t2.a24 = 677; + t2.a25 = 763; + t2.a26 = 760; + t2.a27 = 759; + t2.a28 = 754; + t2.a6 = 494; + t2.a7 = 552; + t2.a8 = 537; + t2.a9 = 577; + t2.a10 = 692; + t2.a29 = 786; + t2.a30 = 788; + t2.a31 = 788; + t2.a32 = 790; + t2.a33 = 793; + t2.a34 = 794; + t2.a35 = 816; + t2.a36 = 823; + t2.a37 = 789; + t2.a38 = 841; + t2.a39 = 823; + t2.a40 = 833; + t2.a41 = 816; + t2.a42 = 831; + t2.a43 = 923; + t2.a44 = 744; + t2.a45 = 723; + t2.a46 = 749; + t2.a47 = 790; + t2.a48 = 792; + t2.a49 = 695; + t2.a50 = 776; + t2.a51 = 768; + t2.a52 = 792; + t2.a53 = 759; + t2.a54 = 707; + t2.a55 = 708; + t2.a56 = 682; + t2.a57 = 701; + t2.a58 = 826; + t2.a59 = 815; + t2.a60 = 789; + t2.a61 = 789; + t2.a62 = 707; + t2.a63 = 687; + t2.a64 = 696; + t2.a65 = 689; + t2.a66 = 786; + t2.a67 = 787; + t2.a68 = 713; + t2.a69 = 791; + t2.a70 = 785; + t2.a71 = 791; + t2.a72 = 873; + t2.a73 = 761; + t2.a74 = 762; + t2.a203 = 762; + t2.a75 = 759; + t2.a204 = 759; + t2.a76 = 892; + t2.a77 = 892; + t2.a78 = 788; + t2.a79 = 784; + t2.a81 = 438; + t2.a82 = 138; + t2.a83 = 277; + t2.a84 = 415; + t2.a97 = 392; + t2.a98 = 392; + t2.a99 = 668; + t2.a100 = 668; + t2.a89 = 390; + t2.a90 = 390; + t2.a93 = 317; + t2.a94 = 317; + t2.a91 = 276; + t2.a92 = 276; + t2.a205 = 509; + t2.a85 = 509; + t2.a206 = 410; + t2.a86 = 410; + t2.a87 = 234; + t2.a88 = 234; + t2.a95 = 334; + t2.a96 = 334; + t2.a101 = 732; + t2.a102 = 544; + t2.a103 = 544; + t2.a104 = 910; + t2.a106 = 667; + t2.a107 = 760; + t2.a108 = 760; + t2.a112 = 776; + t2.a111 = 595; + t2.a110 = 694; + t2.a109 = 626; + t2.a120 = 788; + t2.a121 = 788; + t2.a122 = 788; + t2.a123 = 788; + t2.a124 = 788; + t2.a125 = 788; + t2.a126 = 788; + t2.a127 = 788; + t2.a128 = 788; + t2.a129 = 788; + t2.a130 = 788; + t2.a131 = 788; + t2.a132 = 788; + t2.a133 = 788; + t2.a134 = 788; + t2.a135 = 788; + t2.a136 = 788; + t2.a137 = 788; + t2.a138 = 788; + t2.a139 = 788; + t2.a140 = 788; + t2.a141 = 788; + t2.a142 = 788; + t2.a143 = 788; + t2.a144 = 788; + t2.a145 = 788; + t2.a146 = 788; + t2.a147 = 788; + t2.a148 = 788; + t2.a149 = 788; + t2.a150 = 788; + t2.a151 = 788; + t2.a152 = 788; + t2.a153 = 788; + t2.a154 = 788; + t2.a155 = 788; + t2.a156 = 788; + t2.a157 = 788; + t2.a158 = 788; + t2.a159 = 788; + t2.a160 = 894; + t2.a161 = 838; + t2.a163 = 1016; + t2.a164 = 458; + t2.a196 = 748; + t2.a165 = 924; + t2.a192 = 748; + t2.a166 = 918; + t2.a167 = 927; + t2.a168 = 928; + t2.a169 = 928; + t2.a170 = 834; + t2.a171 = 873; + t2.a172 = 828; + t2.a173 = 924; + t2.a162 = 924; + t2.a174 = 917; + t2.a175 = 930; + t2.a176 = 931; + t2.a177 = 463; + t2.a178 = 883; + t2.a179 = 836; + t2.a193 = 836; + t2.a180 = 867; + t2.a199 = 867; + t2.a181 = 696; + t2.a200 = 696; + t2.a182 = 874; + t2.a201 = 874; + t2.a183 = 760; + t2.a184 = 946; + t2.a197 = 771; + t2.a185 = 865; + t2.a194 = 771; + t2.a198 = 888; + t2.a186 = 967; + t2.a195 = 888; + t2.a187 = 831; + t2.a188 = 873; + t2.a189 = 927; + t2.a190 = 970; + t2.a191 = 918; + }); + }); + getFontBasicMetrics = getLookupTableFactory(function(t) { + t.Courier = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: -426 + }; + t["Courier-Bold"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 439 + }; + t["Courier-Oblique"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 426 + }; + t["Courier-BoldOblique"] = { + ascent: 629, + descent: -157, + capHeight: 562, + xHeight: 426 + }; + t.Helvetica = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 523 + }; + t["Helvetica-Bold"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 532 + }; + t["Helvetica-Oblique"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 523 + }; + t["Helvetica-BoldOblique"] = { + ascent: 718, + descent: -207, + capHeight: 718, + xHeight: 532 + }; + t["Times-Roman"] = { + ascent: 683, + descent: -217, + capHeight: 662, + xHeight: 450 + }; + t["Times-Bold"] = { + ascent: 683, + descent: -217, + capHeight: 676, + xHeight: 461 + }; + t["Times-Italic"] = { + ascent: 683, + descent: -217, + capHeight: 653, + xHeight: 441 + }; + t["Times-BoldItalic"] = { + ascent: 683, + descent: -217, + capHeight: 669, + xHeight: 462 + }; + t.Symbol = { + ascent: Math.NaN, + descent: Math.NaN, + capHeight: Math.NaN, + xHeight: Math.NaN + }; + t.ZapfDingbats = { + ascent: Math.NaN, + descent: Math.NaN, + capHeight: Math.NaN, + xHeight: Math.NaN + }; + }); + ON_CURVE_POINT = 1 << 0; + X_SHORT_VECTOR = 1 << 1; + Y_SHORT_VECTOR = 1 << 2; + REPEAT_FLAG = 1 << 3; + X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR = 1 << 4; + Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR = 1 << 5; + OVERLAP_SIMPLE = 1 << 6; + ARG_1_AND_2_ARE_WORDS = 1 << 0; + ARGS_ARE_XY_VALUES = 1 << 1; + WE_HAVE_A_SCALE = 1 << 3; + MORE_COMPONENTS = 1 << 5; + WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; + WE_HAVE_A_TWO_BY_TWO = 1 << 7; + WE_HAVE_INSTRUCTIONS = 1 << 8; + GlyfTable = class { + constructor({ + glyfTable, + isGlyphLocationsLong, + locaTable, + numGlyphs + }) { + this.glyphs = []; + const loca = new DataView(locaTable.buffer, locaTable.byteOffset, locaTable.byteLength); + const glyf = new DataView(glyfTable.buffer, glyfTable.byteOffset, glyfTable.byteLength); + const offsetSize = isGlyphLocationsLong ? 4 : 2; + let prev = isGlyphLocationsLong ? loca.getUint32(0) : 2 * loca.getUint16(0); + let pos = 0; + for (let i = 0; i < numGlyphs; i++) { + pos += offsetSize; + const next = isGlyphLocationsLong ? loca.getUint32(pos) : 2 * loca.getUint16(pos); + if (next === prev) { + this.glyphs.push(new Glyph({})); + continue; + } + const glyph = Glyph.parse(prev, glyf); + this.glyphs.push(glyph); + prev = next; + } + } + getSize() { + return Math.sumPrecise(this.glyphs.map((g) => g.getSize() + 3 & ~3)); + } + write() { + const totalSize = this.getSize(); + const glyfTable = new DataView(new ArrayBuffer(totalSize)); + const isLocationLong = totalSize > 131070; + const offsetSize = isLocationLong ? 4 : 2; + const locaTable = new DataView(new ArrayBuffer((this.glyphs.length + 1) * offsetSize)); + if (isLocationLong) { + locaTable.setUint32(0, 0); + } else { + locaTable.setUint16(0, 0); + } + let pos = 0; + let locaIndex = 0; + for (const glyph of this.glyphs) { + pos += glyph.write(pos, glyfTable); + pos = pos + 3 & ~3; + locaIndex += offsetSize; + if (isLocationLong) { + locaTable.setUint32(locaIndex, pos); + } else { + locaTable.setUint16(locaIndex, pos >> 1); + } + } + return { + isLocationLong, + loca: new Uint8Array(locaTable.buffer), + glyf: new Uint8Array(glyfTable.buffer) + }; + } + scale(factors) { + for (let i = 0, ii = this.glyphs.length; i < ii; i++) { + this.glyphs[i].scale(factors[i]); + } + } + }; + Glyph = class _Glyph { + constructor({ + header = null, + simple = null, + composites = null + }) { + this.header = header; + this.simple = simple; + this.composites = composites; + } + static parse(pos, glyf) { + const [read, header] = GlyphHeader.parse(pos, glyf); + pos += read; + if (header.numberOfContours < 0) { + const composites = []; + while (true) { + const [n, composite] = CompositeGlyph.parse(pos, glyf); + pos += n; + composites.push(composite); + if (!(composite.flags & MORE_COMPONENTS)) { + break; + } + } + return new _Glyph({ + header, + composites + }); + } + const simple = SimpleGlyph.parse(pos, glyf, header.numberOfContours); + return new _Glyph({ + header, + simple + }); + } + getSize() { + if (!this.header) { + return 0; + } + const size3 = this.simple ? this.simple.getSize() : Math.sumPrecise(this.composites.map((c) => c.getSize())); + return this.header.getSize() + size3; + } + write(pos, buf) { + if (!this.header) { + return 0; + } + const spos = pos; + pos += this.header.write(pos, buf); + if (this.simple) { + pos += this.simple.write(pos, buf); + } else { + for (const composite of this.composites) { + pos += composite.write(pos, buf); + } + } + return pos - spos; + } + scale(factor) { + if (!this.header) { + return; + } + const xMiddle = (this.header.xMin + this.header.xMax) / 2; + this.header.scale(xMiddle, factor); + if (this.simple) { + this.simple.scale(xMiddle, factor); + } else { + for (const composite of this.composites) { + composite.scale(xMiddle, factor); + } + } + } + }; + GlyphHeader = class _GlyphHeader { + constructor({ + numberOfContours, + xMin, + yMin, + xMax, + yMax + }) { + this.numberOfContours = numberOfContours; + this.xMin = xMin; + this.yMin = yMin; + this.xMax = xMax; + this.yMax = yMax; + } + static parse(pos, glyf) { + return [10, new _GlyphHeader({ + numberOfContours: glyf.getInt16(pos), + xMin: glyf.getInt16(pos + 2), + yMin: glyf.getInt16(pos + 4), + xMax: glyf.getInt16(pos + 6), + yMax: glyf.getInt16(pos + 8) + })]; + } + getSize() { + return 10; + } + write(pos, buf) { + buf.setInt16(pos, this.numberOfContours); + buf.setInt16(pos + 2, this.xMin); + buf.setInt16(pos + 4, this.yMin); + buf.setInt16(pos + 6, this.xMax); + buf.setInt16(pos + 8, this.yMax); + return 10; + } + scale(x, factor) { + this.xMin = Math.round(x + (this.xMin - x) * factor); + this.xMax = Math.round(x + (this.xMax - x) * factor); + } + }; + Contour = class { + constructor({ + flags, + xCoordinates, + yCoordinates + }) { + this.xCoordinates = xCoordinates; + this.yCoordinates = yCoordinates; + this.flags = flags; + } + }; + SimpleGlyph = class _SimpleGlyph { + constructor({ + contours, + instructions + }) { + this.contours = contours; + this.instructions = instructions; + } + static parse(pos, glyf, numberOfContours) { + const endPtsOfContours = []; + for (let i = 0; i < numberOfContours; i++) { + const endPt = glyf.getUint16(pos); + pos += 2; + endPtsOfContours.push(endPt); + } + const numberOfPt = endPtsOfContours[numberOfContours - 1] + 1; + const instructionLength = glyf.getUint16(pos); + pos += 2; + const instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); + pos += instructionLength; + const flags = []; + for (let i = 0; i < numberOfPt; pos++, i++) { + let flag = glyf.getUint8(pos); + flags.push(flag); + if (flag & REPEAT_FLAG) { + const count = glyf.getUint8(++pos); + flag ^= REPEAT_FLAG; + for (let m = 0; m < count; m++) { + flags.push(flag); + } + i += count; + } + } + const allXCoordinates = []; + let xCoordinates = []; + let yCoordinates = []; + let pointFlags = []; + const contours = []; + let endPtsOfContoursIndex = 0; + let lastCoordinate = 0; + for (let i = 0; i < numberOfPt; i++) { + const flag = flags[i]; + if (flag & X_SHORT_VECTOR) { + const x = glyf.getUint8(pos++); + lastCoordinate += flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR ? x : -x; + xCoordinates.push(lastCoordinate); + } else if (flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR) { + xCoordinates.push(lastCoordinate); + } else { + lastCoordinate += glyf.getInt16(pos); + pos += 2; + xCoordinates.push(lastCoordinate); + } + if (endPtsOfContours[endPtsOfContoursIndex] === i) { + endPtsOfContoursIndex++; + allXCoordinates.push(xCoordinates); + xCoordinates = []; + } + } + lastCoordinate = 0; + endPtsOfContoursIndex = 0; + for (let i = 0; i < numberOfPt; i++) { + const flag = flags[i]; + if (flag & Y_SHORT_VECTOR) { + const y = glyf.getUint8(pos++); + lastCoordinate += flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR ? y : -y; + yCoordinates.push(lastCoordinate); + } else if (flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR) { + yCoordinates.push(lastCoordinate); + } else { + lastCoordinate += glyf.getInt16(pos); + pos += 2; + yCoordinates.push(lastCoordinate); + } + pointFlags.push(flag & ON_CURVE_POINT | flag & OVERLAP_SIMPLE); + if (endPtsOfContours[endPtsOfContoursIndex] === i) { + xCoordinates = allXCoordinates[endPtsOfContoursIndex]; + endPtsOfContoursIndex++; + contours.push(new Contour({ + flags: pointFlags, + xCoordinates, + yCoordinates + })); + yCoordinates = []; + pointFlags = []; + } + } + return new _SimpleGlyph({ + contours, + instructions + }); + } + getSize() { + let size3 = this.contours.length * 2 + 2 + this.instructions.length; + let lastX = 0; + let lastY = 0; + for (const contour of this.contours) { + size3 += contour.flags.length; + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + const x = contour.xCoordinates[i]; + const y = contour.yCoordinates[i]; + let abs = Math.abs(x - lastX); + if (abs > 255) { + size3 += 2; + } else if (abs > 0) { + size3 += 1; + } + lastX = x; + abs = Math.abs(y - lastY); + if (abs > 255) { + size3 += 2; + } else if (abs > 0) { + size3 += 1; + } + lastY = y; + } + } + return size3; + } + write(pos, buf) { + const spos = pos; + const xCoordinates = []; + const yCoordinates = []; + const flags = []; + let lastX = 0; + let lastY = 0; + for (const contour of this.contours) { + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + let flag = contour.flags[i]; + const x = contour.xCoordinates[i]; + let delta = x - lastX; + if (delta === 0) { + flag |= X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR; + xCoordinates.push(0); + } else { + const abs = Math.abs(delta); + if (abs <= 255) { + flag |= delta >= 0 ? X_SHORT_VECTOR | X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR : X_SHORT_VECTOR; + xCoordinates.push(abs); + } else { + xCoordinates.push(delta); + } + } + lastX = x; + const y = contour.yCoordinates[i]; + delta = y - lastY; + if (delta === 0) { + flag |= Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR; + yCoordinates.push(0); + } else { + const abs = Math.abs(delta); + if (abs <= 255) { + flag |= delta >= 0 ? Y_SHORT_VECTOR | Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR : Y_SHORT_VECTOR; + yCoordinates.push(abs); + } else { + yCoordinates.push(delta); + } + } + lastY = y; + flags.push(flag); + } + buf.setUint16(pos, xCoordinates.length - 1); + pos += 2; + } + buf.setUint16(pos, this.instructions.length); + pos += 2; + if (this.instructions.length) { + new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); + pos += this.instructions.length; + } + for (const flag of flags) { + buf.setUint8(pos++, flag); + } + for (let i = 0, ii = xCoordinates.length; i < ii; i++) { + const x = xCoordinates[i]; + const flag = flags[i]; + if (flag & X_SHORT_VECTOR) { + buf.setUint8(pos++, x); + } else if (!(flag & X_IS_SAME_OR_POSITIVE_X_SHORT_VECTOR)) { + buf.setInt16(pos, x); + pos += 2; + } + } + for (let i = 0, ii = yCoordinates.length; i < ii; i++) { + const y = yCoordinates[i]; + const flag = flags[i]; + if (flag & Y_SHORT_VECTOR) { + buf.setUint8(pos++, y); + } else if (!(flag & Y_IS_SAME_OR_POSITIVE_Y_SHORT_VECTOR)) { + buf.setInt16(pos, y); + pos += 2; + } + } + return pos - spos; + } + scale(x, factor) { + for (const contour of this.contours) { + if (contour.xCoordinates.length === 0) { + continue; + } + for (let i = 0, ii = contour.xCoordinates.length; i < ii; i++) { + contour.xCoordinates[i] = Math.round(x + (contour.xCoordinates[i] - x) * factor); + } + } + } + }; + CompositeGlyph = class _CompositeGlyph { + constructor({ + flags, + glyphIndex, + argument1, + argument2, + transf, + instructions + }) { + this.flags = flags; + this.glyphIndex = glyphIndex; + this.argument1 = argument1; + this.argument2 = argument2; + this.transf = transf; + this.instructions = instructions; + } + static parse(pos, glyf) { + const spos = pos; + const transf = []; + let flags = glyf.getUint16(pos); + const glyphIndex = glyf.getUint16(pos + 2); + pos += 4; + let argument1, argument2; + if (flags & ARG_1_AND_2_ARE_WORDS) { + if (flags & ARGS_ARE_XY_VALUES) { + argument1 = glyf.getInt16(pos); + argument2 = glyf.getInt16(pos + 2); + } else { + argument1 = glyf.getUint16(pos); + argument2 = glyf.getUint16(pos + 2); + } + pos += 4; + flags ^= ARG_1_AND_2_ARE_WORDS; + } else { + if (flags & ARGS_ARE_XY_VALUES) { + argument1 = glyf.getInt8(pos); + argument2 = glyf.getInt8(pos + 1); + } else { + argument1 = glyf.getUint8(pos); + argument2 = glyf.getUint8(pos + 1); + } + pos += 2; + } + if (flags & WE_HAVE_A_SCALE) { + transf.push(glyf.getUint16(pos)); + pos += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2)); + pos += 4; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { + transf.push(glyf.getUint16(pos), glyf.getUint16(pos + 2), glyf.getUint16(pos + 4), glyf.getUint16(pos + 6)); + pos += 8; + } + let instructions = null; + if (flags & WE_HAVE_INSTRUCTIONS) { + const instructionLength = glyf.getUint16(pos); + pos += 2; + instructions = new Uint8Array(glyf).slice(pos, pos + instructionLength); + pos += instructionLength; + } + return [pos - spos, new _CompositeGlyph({ + flags, + glyphIndex, + argument1, + argument2, + transf, + instructions + })]; + } + getSize() { + let size3 = 2 + 2 + this.transf.length * 2; + if (this.flags & WE_HAVE_INSTRUCTIONS) { + size3 += 2 + this.instructions.length; + } + size3 += 2; + if (this.flags & 2) { + if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { + size3 += 2; + } + } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { + size3 += 2; + } + return size3; + } + write(pos, buf) { + const spos = pos; + if (this.flags & ARGS_ARE_XY_VALUES) { + if (!(this.argument1 >= -128 && this.argument1 <= 127 && this.argument2 >= -128 && this.argument2 <= 127)) { + this.flags |= ARG_1_AND_2_ARE_WORDS; + } + } else if (!(this.argument1 >= 0 && this.argument1 <= 255 && this.argument2 >= 0 && this.argument2 <= 255)) { + this.flags |= ARG_1_AND_2_ARE_WORDS; + } + buf.setUint16(pos, this.flags); + buf.setUint16(pos + 2, this.glyphIndex); + pos += 4; + if (this.flags & ARG_1_AND_2_ARE_WORDS) { + if (this.flags & ARGS_ARE_XY_VALUES) { + buf.setInt16(pos, this.argument1); + buf.setInt16(pos + 2, this.argument2); + } else { + buf.setUint16(pos, this.argument1); + buf.setUint16(pos + 2, this.argument2); + } + pos += 4; + } else { + buf.setUint8(pos, this.argument1); + buf.setUint8(pos + 1, this.argument2); + pos += 2; + } + if (this.flags & WE_HAVE_INSTRUCTIONS) { + buf.setUint16(pos, this.instructions.length); + pos += 2; + if (this.instructions.length) { + new Uint8Array(buf.buffer, 0, buf.buffer.byteLength).set(this.instructions, pos); + pos += this.instructions.length; + } + } + return pos - spos; + } + scale(x, factor) { + } + }; + OTF_HEADER_SIZE = 12; + OTF_TABLE_ENTRY_SIZE = 16; + OpenTypeFileBuilder = class _OpenTypeFileBuilder { + constructor(sfnt) { + this.sfnt = sfnt; + this.tables = /* @__PURE__ */ Object.create(null); + } + static getSearchParams(entriesCount, entrySize) { + let maxPower2 = 1, log22 = 0; + while ((maxPower2 ^ entriesCount) > maxPower2) { + maxPower2 <<= 1; + log22++; + } + const searchRange = maxPower2 * entrySize; + return { + range: searchRange, + entry: log22, + rangeShift: entrySize * entriesCount - searchRange + }; + } + toArray() { + let sfnt = this.sfnt; + const tables = this.tables; + const tablesNames = Object.keys(tables); + tablesNames.sort(); + const numTables = tablesNames.length; + let i, j, jj, table2, tableName; + let offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE; + const tableOffsets = [offset]; + for (i = 0; i < numTables; i++) { + table2 = tables[tablesNames[i]]; + const paddedLength = (table2.length + 3 & ~3) >>> 0; + offset += paddedLength; + tableOffsets.push(offset); + } + const file2 = new Uint8Array(offset); + for (i = 0; i < numTables; i++) { + table2 = tables[tablesNames[i]]; + writeData(file2, tableOffsets[i], table2); + } + if (sfnt === "true") { + sfnt = string322(65536); + } + file2[0] = sfnt.charCodeAt(0) & 255; + file2[1] = sfnt.charCodeAt(1) & 255; + file2[2] = sfnt.charCodeAt(2) & 255; + file2[3] = sfnt.charCodeAt(3) & 255; + writeInt16(file2, 4, numTables); + const searchParams = _OpenTypeFileBuilder.getSearchParams(numTables, 16); + writeInt16(file2, 6, searchParams.range); + writeInt16(file2, 8, searchParams.entry); + writeInt16(file2, 10, searchParams.rangeShift); + offset = OTF_HEADER_SIZE; + for (i = 0; i < numTables; i++) { + tableName = tablesNames[i]; + file2[offset] = tableName.charCodeAt(0) & 255; + file2[offset + 1] = tableName.charCodeAt(1) & 255; + file2[offset + 2] = tableName.charCodeAt(2) & 255; + file2[offset + 3] = tableName.charCodeAt(3) & 255; + let checksum = 0; + for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) { + const quad = readUint32(file2, j); + checksum = checksum + quad >>> 0; + } + writeInt32(file2, offset + 4, checksum); + writeInt32(file2, offset + 8, tableOffsets[i]); + writeInt32(file2, offset + 12, tables[tableName].length); + offset += OTF_TABLE_ENTRY_SIZE; + } + return file2; + } + addTable(tag2, data) { + if (tag2 in this.tables) { + throw new Error("Table " + tag2 + " already exists"); + } + this.tables[tag2] = data; + } + }; + HINTING_ENABLED = false; + COMMAND_MAP = { + hstem: [1], + vstem: [3], + vmoveto: [4], + rlineto: [5], + hlineto: [6], + vlineto: [7], + rrcurveto: [8], + callsubr: [10], + flex: [12, 35], + drop: [12, 18], + endchar: [14], + rmoveto: [21], + hmoveto: [22], + vhcurveto: [30], + hvcurveto: [31] + }; + Type1CharString = class { + constructor() { + this.width = 0; + this.lsb = 0; + this.flexing = false; + this.output = []; + this.stack = []; + } + convert(encoded, subrs, seacAnalysisEnabled) { + const count = encoded.length; + let error62 = false; + let wx, sbx, subrNumber; + for (let i = 0; i < count; i++) { + let value = encoded[i]; + if (value < 32) { + if (value === 12) { + value = (value << 8) + encoded[++i]; + } + switch (value) { + case 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error62 = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case 3: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error62 = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case 4: + if (this.flexing) { + if (this.stack.length < 1) { + error62 = true; + break; + } + const dy = this.stack.pop(); + this.stack.push(0, dy); + break; + } + error62 = this.executeCommand(1, COMMAND_MAP.vmoveto); + break; + case 5: + error62 = this.executeCommand(2, COMMAND_MAP.rlineto); + break; + case 6: + error62 = this.executeCommand(1, COMMAND_MAP.hlineto); + break; + case 7: + error62 = this.executeCommand(1, COMMAND_MAP.vlineto); + break; + case 8: + error62 = this.executeCommand(6, COMMAND_MAP.rrcurveto); + break; + case 9: + this.stack = []; + break; + case 10: + if (this.stack.length < 1) { + error62 = true; + break; + } + subrNumber = this.stack.pop(); + if (!subrs[subrNumber]) { + error62 = true; + break; + } + error62 = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled); + break; + case 11: + return error62; + case 13: + if (this.stack.length < 2) { + error62 = true; + break; + } + wx = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx); + error62 = this.executeCommand(2, COMMAND_MAP.hmoveto); + break; + case 14: + this.output.push(COMMAND_MAP.endchar[0]); + break; + case 21: + if (this.flexing) { + break; + } + error62 = this.executeCommand(2, COMMAND_MAP.rmoveto); + break; + case 22: + if (this.flexing) { + this.stack.push(0); + break; + } + error62 = this.executeCommand(1, COMMAND_MAP.hmoveto); + break; + case 30: + error62 = this.executeCommand(4, COMMAND_MAP.vhcurveto); + break; + case 31: + error62 = this.executeCommand(4, COMMAND_MAP.hvcurveto); + break; + case (12 << 8) + 0: + this.stack = []; + break; + case (12 << 8) + 1: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error62 = this.executeCommand(2, COMMAND_MAP.vstem); + break; + case (12 << 8) + 2: + if (!HINTING_ENABLED) { + this.stack = []; + break; + } + error62 = this.executeCommand(2, COMMAND_MAP.hstem); + break; + case (12 << 8) + 6: + if (seacAnalysisEnabled) { + const asb = this.stack.at(-5); + this.seac = this.stack.splice(-4, 4); + this.seac[0] += this.lsb - asb; + error62 = this.executeCommand(0, COMMAND_MAP.endchar); + } else { + error62 = this.executeCommand(4, COMMAND_MAP.endchar); + } + break; + case (12 << 8) + 7: + if (this.stack.length < 4) { + error62 = true; + break; + } + this.stack.pop(); + wx = this.stack.pop(); + const sby = this.stack.pop(); + sbx = this.stack.pop(); + this.lsb = sbx; + this.width = wx; + this.stack.push(wx, sbx, sby); + error62 = this.executeCommand(3, COMMAND_MAP.rmoveto); + break; + case (12 << 8) + 12: + if (this.stack.length < 2) { + error62 = true; + break; + } + const num2 = this.stack.pop(); + const num1 = this.stack.pop(); + this.stack.push(num1 / num2); + break; + case (12 << 8) + 16: + if (this.stack.length < 2) { + error62 = true; + break; + } + subrNumber = this.stack.pop(); + const numArgs = this.stack.pop(); + if (subrNumber === 0 && numArgs === 3) { + const flexArgs = this.stack.splice(-17, 17); + this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]); + error62 = this.executeCommand(13, COMMAND_MAP.flex, true); + this.flexing = false; + this.stack.push(flexArgs[15], flexArgs[16]); + } else if (subrNumber === 1 && numArgs === 0) { + this.flexing = true; + } + break; + case (12 << 8) + 17: + break; + case (12 << 8) + 33: + this.stack = []; + break; + default: + warn2('Unknown type 1 charstring command of "' + value + '"'); + break; + } + if (error62) { + break; + } + continue; + } else if (value <= 246) { + value -= 139; + } else if (value <= 250) { + value = (value - 247) * 256 + encoded[++i] + 108; + } else if (value <= 254) { + value = -((value - 251) * 256) - encoded[++i] - 108; + } else { + value = (encoded[++i] & 255) << 24 | (encoded[++i] & 255) << 16 | (encoded[++i] & 255) << 8 | (encoded[++i] & 255) << 0; + } + this.stack.push(value); + } + return error62; + } + executeCommand(howManyArgs, command, keepStack) { + const stackLength = this.stack.length; + if (howManyArgs > stackLength) { + return true; + } + const start = stackLength - howManyArgs; + for (let i = start; i < stackLength; i++) { + let value = this.stack[i]; + if (Number.isInteger(value)) { + this.output.push(28, value >> 8 & 255, value & 255); + } else { + value = 65536 * value | 0; + this.output.push(255, value >> 24 & 255, value >> 16 & 255, value >> 8 & 255, value & 255); + } + } + this.output.push(...command); + if (keepStack) { + this.stack.splice(start, howManyArgs); + } else { + this.stack.length = 0; + } + return false; + } + }; + EEXEC_ENCRYPT_KEY = 55665; + CHAR_STRS_ENCRYPT_KEY = 4330; + Type1Parser = class { + constructor(stream, encrypted, seacAnalysisEnabled) { + if (encrypted) { + const data = stream.getBytes(); + const isBinary = !((isHexDigit(data[0]) || isWhiteSpace(data[0])) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]) && isHexDigit(data[4]) && isHexDigit(data[5]) && isHexDigit(data[6]) && isHexDigit(data[7])); + stream = new Stream3(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)); + } + this.seacAnalysisEnabled = !!seacAnalysisEnabled; + this.stream = stream; + this.nextChar(); + } + readNumberArray() { + this.getToken(); + const array2 = []; + while (true) { + const token = this.getToken(); + if (token === null || token === "]" || token === "}") { + break; + } + array2.push(parseFloat(token || 0)); + } + return array2; + } + readNumber() { + const token = this.getToken(); + return parseFloat(token || 0); + } + readInt() { + const token = this.getToken(); + return parseInt(token || 0, 10) | 0; + } + readBoolean() { + const token = this.getToken(); + return token === "true" ? 1 : 0; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + prevChar() { + this.stream.skip(-2); + return this.currentChar = this.stream.getByte(); + } + getToken() { + let comment = false; + let ch2 = this.currentChar; + while (true) { + if (ch2 === -1) { + return null; + } + if (comment) { + if (ch2 === 10 || ch2 === 13) { + comment = false; + } + } else if (ch2 === 37) { + comment = true; + } else if (!isWhiteSpace(ch2)) { + break; + } + ch2 = this.nextChar(); + } + if (isSpecial(ch2)) { + this.nextChar(); + return String.fromCharCode(ch2); + } + let token = ""; + do { + token += String.fromCharCode(ch2); + ch2 = this.nextChar(); + } while (ch2 >= 0 && !isWhiteSpace(ch2) && !isSpecial(ch2)); + return token; + } + readCharStrings(bytes, lenIV) { + if (lenIV === -1) { + return bytes; + } + return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV); + } + extractFontProgram(properties) { + const stream = this.stream; + const subrs = [], charstrings = []; + const privateData = /* @__PURE__ */ Object.create(null); + privateData.lenIV = 4; + const program = { + subrs: [], + charstrings: [], + properties: { + privateData + } + }; + let token, length, data, lenIV; + while ((token = this.getToken()) !== null) { + if (token !== "/") { + continue; + } + token = this.getToken(); + switch (token) { + case "CharStrings": + this.getToken(); + this.getToken(); + this.getToken(); + this.getToken(); + while (true) { + token = this.getToken(); + if (token === null || token === "end") { + break; + } + if (token !== "/") { + continue; + } + const glyph = this.getToken(); + length = this.readInt(); + this.getToken(); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); + lenIV = program.properties.privateData.lenIV; + const encoded = this.readCharStrings(data, lenIV); + this.nextChar(); + token = this.getToken(); + if (token === "noaccess") { + this.getToken(); + } else if (token === "/") { + this.prevChar(); + } + charstrings.push({ + glyph, + encoded + }); + } + break; + case "Subrs": + this.readInt(); + this.getToken(); + while (this.getToken() === "dup") { + const index2 = this.readInt(); + length = this.readInt(); + this.getToken(); + data = length > 0 ? stream.getBytes(length) : new Uint8Array(0); + lenIV = program.properties.privateData.lenIV; + const encoded = this.readCharStrings(data, lenIV); + this.nextChar(); + token = this.getToken(); + if (token === "noaccess") { + this.getToken(); + } + subrs[index2] = encoded; + } + break; + case "BlueValues": + case "OtherBlues": + case "FamilyBlues": + case "FamilyOtherBlues": + const blueArray = this.readNumberArray(); + if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) { + program.properties.privateData[token] = blueArray; + } + break; + case "StemSnapH": + case "StemSnapV": + program.properties.privateData[token] = this.readNumberArray(); + break; + case "StdHW": + case "StdVW": + program.properties.privateData[token] = this.readNumberArray()[0]; + break; + case "BlueShift": + case "lenIV": + case "BlueFuzz": + case "BlueScale": + case "LanguageGroup": + program.properties.privateData[token] = this.readNumber(); + break; + case "ExpansionFactor": + program.properties.privateData[token] = this.readNumber() || 0.06; + break; + case "ForceBold": + program.properties.privateData[token] = this.readBoolean(); + break; + } + } + for (const { + encoded, + glyph + } of charstrings) { + const charString = new Type1CharString(); + const error62 = charString.convert(encoded, subrs, this.seacAnalysisEnabled); + let output2 = charString.output; + if (error62) { + output2 = [14]; + } + const charStringObject = { + glyphName: glyph, + charstring: output2, + width: charString.width, + lsb: charString.lsb, + seac: charString.seac + }; + if (glyph === ".notdef") { + program.charstrings.unshift(charStringObject); + } else { + program.charstrings.push(charStringObject); + } + if (properties.builtInEncoding) { + const index2 = properties.builtInEncoding.indexOf(glyph); + if (index2 > -1 && properties.widths[index2] === void 0 && index2 >= properties.firstChar && index2 <= properties.lastChar) { + properties.widths[index2] = charString.width; + } + } + } + return program; + } + extractFontHeader(properties) { + let token; + while ((token = this.getToken()) !== null) { + if (token !== "/") { + continue; + } + token = this.getToken(); + switch (token) { + case "FontMatrix": + const matrix = this.readNumberArray(); + properties.fontMatrix = matrix; + break; + case "Encoding": + const encodingArg = this.getToken(); + let encoding; + if (!/^\d+$/.test(encodingArg)) { + encoding = getEncoding(encodingArg); + } else { + encoding = []; + const size3 = parseInt(encodingArg, 10) | 0; + this.getToken(); + for (let j = 0; j < size3; j++) { + token = this.getToken(); + while (token !== "dup" && token !== "def") { + token = this.getToken(); + if (token === null) { + return; + } + } + if (token === "def") { + break; + } + const index2 = this.readInt(); + this.getToken(); + const glyph = this.getToken(); + encoding[index2] = glyph; + this.getToken(); + } + } + properties.builtInEncoding = encoding; + break; + case "FontBBox": + const fontBBox = this.readNumberArray(); + properties.ascent = Math.max(fontBBox[3], fontBBox[1]); + properties.descent = Math.min(fontBBox[1], fontBBox[3]); + properties.ascentScaled = true; + break; + } + } + } + }; + Type1Font = class { + constructor(name, file2, properties) { + const PFB_HEADER_SIZE = 6; + let headerBlockLength = properties.length1; + let eexecBlockLength = properties.length2; + let pfbHeader = file2.peekBytes(PFB_HEADER_SIZE); + const pfbHeaderPresent = pfbHeader[0] === 128 && pfbHeader[1] === 1; + if (pfbHeaderPresent) { + file2.skip(PFB_HEADER_SIZE); + headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + const headerBlock = getHeaderBlock(file2, headerBlockLength); + const headerBlockParser = new Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED); + headerBlockParser.extractFontHeader(properties); + if (pfbHeaderPresent) { + pfbHeader = file2.getBytes(PFB_HEADER_SIZE); + eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2]; + } + const eexecBlock = getEexecBlock(file2, eexecBlockLength); + const eexecBlockParser = new Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED); + const data = eexecBlockParser.extractFontProgram(properties); + for (const key in data.properties) { + properties[key] = data.properties[key]; + } + const charstrings = data.charstrings; + const type2Charstrings = this.getType2Charstrings(charstrings); + const subrs = this.getType2Subrs(data.subrs); + this.charstrings = charstrings; + this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties); + this.seacs = this.getSeacs(data.charstrings); + } + get numGlyphs() { + return this.charstrings.length + 1; + } + getCharset() { + const charset = [".notdef"]; + for (const { + glyphName + } of this.charstrings) { + charset.push(glyphName); + } + return charset; + } + getGlyphMapping(properties) { + const charstrings = this.charstrings; + if (properties.composite) { + const charCodeToGlyphId = /* @__PURE__ */ Object.create(null); + for (let glyphId2 = 0, charstringsLen = charstrings.length; glyphId2 < charstringsLen; glyphId2++) { + const charCode = properties.cMap.charCodeOf(glyphId2); + charCodeToGlyphId[charCode] = glyphId2 + 1; + } + return charCodeToGlyphId; + } + const glyphNames = [".notdef"]; + let builtInEncoding, glyphId; + for (glyphId = 0; glyphId < charstrings.length; glyphId++) { + glyphNames.push(charstrings[glyphId].glyphName); + } + const encoding = properties.builtInEncoding; + if (encoding) { + builtInEncoding = /* @__PURE__ */ Object.create(null); + for (const charCode in encoding) { + glyphId = glyphNames.indexOf(encoding[charCode]); + if (glyphId >= 0) { + builtInEncoding[charCode] = glyphId; + } + } + } + return type1FontGlyphMapping(properties, builtInEncoding, glyphNames); + } + hasGlyphId(id) { + if (id < 0 || id >= this.numGlyphs) { + return false; + } + if (id === 0) { + return true; + } + const glyph = this.charstrings[id - 1]; + return glyph.charstring.length > 0; + } + getSeacs(charstrings) { + const seacMap = []; + for (let i = 0, ii = charstrings.length; i < ii; i++) { + const charstring = charstrings[i]; + if (charstring.seac) { + seacMap[i + 1] = charstring.seac; + } + } + return seacMap; + } + getType2Charstrings(type1Charstrings) { + const type2Charstrings = []; + for (const type1Charstring of type1Charstrings) { + type2Charstrings.push(type1Charstring.charstring); + } + return type2Charstrings; + } + getType2Subrs(type1Subrs) { + let bias = 0; + const count = type1Subrs.length; + if (count < 1133) { + bias = 107; + } else if (count < 33769) { + bias = 1131; + } else { + bias = 32768; + } + const type2Subrs = []; + let i; + for (i = 0; i < bias; i++) { + type2Subrs.push([11]); + } + for (i = 0; i < count; i++) { + type2Subrs.push(type1Subrs[i]); + } + return type2Subrs; + } + wrap(name, glyphs, charstrings, subrs, properties) { + const cff = new CFF(); + cff.header = new CFFHeader(1, 0, 4, 4); + cff.names = [name]; + const topDict = new CFFTopDict(); + topDict.setByName("version", 391); + topDict.setByName("Notice", 392); + topDict.setByName("FullName", 393); + topDict.setByName("FamilyName", 394); + topDict.setByName("Weight", 395); + topDict.setByName("Encoding", null); + topDict.setByName("FontMatrix", properties.fontMatrix); + topDict.setByName("FontBBox", properties.bbox); + topDict.setByName("charset", null); + topDict.setByName("CharStrings", null); + topDict.setByName("Private", null); + cff.topDict = topDict; + const strings = new CFFStrings(); + strings.add("Version 0.11"); + strings.add("See original notice"); + strings.add(name); + strings.add(name); + strings.add("Medium"); + cff.strings = strings; + cff.globalSubrIndex = new CFFIndex(); + const count = glyphs.length; + const charsetArray = [".notdef"]; + let i, ii; + for (i = 0; i < count; i++) { + const glyphName = charstrings[i].glyphName; + const index2 = CFFStandardStrings.indexOf(glyphName); + if (index2 === -1) { + strings.add(glyphName); + } + charsetArray.push(glyphName); + } + cff.charset = new CFFCharset(false, 0, charsetArray); + const charStringsIndex = new CFFIndex(); + charStringsIndex.add([139, 14]); + for (i = 0; i < count; i++) { + charStringsIndex.add(glyphs[i]); + } + cff.charStrings = charStringsIndex; + const privateDict = new CFFPrivateDict(); + privateDict.setByName("Subrs", null); + const fields = ["BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", "StemSnapH", "StemSnapV", "BlueShift", "BlueFuzz", "BlueScale", "LanguageGroup", "ExpansionFactor", "ForceBold", "StdHW", "StdVW"]; + for (i = 0, ii = fields.length; i < ii; i++) { + const field = fields[i]; + if (!(field in properties.privateData)) { + continue; + } + const value = properties.privateData[field]; + if (Array.isArray(value)) { + for (let j = value.length - 1; j > 0; j--) { + value[j] -= value[j - 1]; + } + } + privateDict.setByName(field, value); + } + cff.topDict.privateDict = privateDict; + const subrIndex = new CFFIndex(); + for (i = 0, ii = subrs.length; i < ii; i++) { + subrIndex.add(subrs[i]); + } + privateDict.subrsIndex = subrIndex; + const compiler = new CFFCompiler(cff); + return compiler.compile(); + } + }; + PRIVATE_USE_AREAS = [[57344, 63743], [1048576, 1114109]]; + PDF_GLYPH_SPACE_UNITS = 1e3; + EXPORT_DATA_PROPERTIES = ["ascent", "bbox", "black", "bold", "charProcOperatorList", "cssFontInfo", "data", "defaultVMetrics", "defaultWidth", "descent", "disableFontFace", "fallbackName", "fontExtraProperties", "fontMatrix", "isInvalidPDFjsFont", "isType3Font", "italic", "loadedName", "mimetype", "missingFile", "name", "remeasure", "systemFontInfo", "vertical"]; + EXPORT_DATA_EXTRA_PROPERTIES = ["cMap", "composite", "defaultEncoding", "differences", "isMonospace", "isSerifFont", "isSymbolicFont", "seacMap", "subtype", "toFontChar", "toUnicode", "type", "vmetrics", "widths"]; + fonts_Glyph = class { + constructor(originalCharCode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) { + this.originalCharCode = originalCharCode; + this.fontChar = fontChar; + this.unicode = unicode; + this.accent = accent; + this.width = width; + this.vmetric = vmetric; + this.operatorListId = operatorListId; + this.isSpace = isSpace; + this.isInFont = isInFont; + } + get category() { + return shadow2(this, "category", getCharUnicodeCategory(this.unicode), true); + } + }; + Font = class { + constructor(name, file2, properties, evaluatorOptions) { + this.name = name; + this.psName = null; + this.mimetype = null; + this.disableFontFace = evaluatorOptions.disableFontFace; + this.fontExtraProperties = evaluatorOptions.fontExtraProperties; + this.loadedName = properties.loadedName; + this.isType3Font = properties.isType3Font; + this.missingFile = false; + this.cssFontInfo = properties.cssFontInfo; + this._charsCache = /* @__PURE__ */ Object.create(null); + this._glyphCache = /* @__PURE__ */ Object.create(null); + let isSerifFont = !!(properties.flags & FontFlags.Serif); + if (!isSerifFont && !properties.isSimulatedFlags) { + const stdFontMap = getStdFontMap(), nonStdFontMap = getNonStdFontMap(), serifFonts = getSerifFonts(); + for (const namePart of name.split("+")) { + let fontName = namePart.replaceAll(/[,_]/g, "-"); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + fontName = fontName.split("-", 1)[0]; + if (serifFonts[fontName]) { + isSerifFont = true; + break; + } + } + } + this.isSerifFont = isSerifFont; + this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + this.isMonospace = !!(properties.flags & FontFlags.FixedPitch); + let { + type, + subtype + } = properties; + this.type = type; + this.subtype = subtype; + this.systemFontInfo = properties.systemFontInfo; + const matches = name.match(/^InvalidPDFjsFont_(.*)_\d+$/); + this.isInvalidPDFjsFont = !!matches; + if (this.isInvalidPDFjsFont) { + this.fallbackName = matches[1]; + } else if (this.isMonospace) { + this.fallbackName = "monospace"; + } else if (this.isSerifFont) { + this.fallbackName = "serif"; + } else { + this.fallbackName = "sans-serif"; + } + if (this.systemFontInfo?.guessFallback) { + this.systemFontInfo.guessFallback = false; + this.systemFontInfo.css += `,${this.fallbackName}`; + } + this.differences = properties.differences; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.composite = properties.composite; + this.cMap = properties.cMap; + this.capHeight = properties.capHeight / PDF_GLYPH_SPACE_UNITS; + this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS; + this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS; + this.lineHeight = this.ascent - this.descent; + this.fontMatrix = properties.fontMatrix; + this.bbox = properties.bbox; + this.defaultEncoding = properties.defaultEncoding; + this.toUnicode = properties.toUnicode; + this.toFontChar = []; + if (properties.type === "Type3") { + for (let charCode = 0; charCode < 256; charCode++) { + this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode]; + } + return; + } + this.cidEncoding = properties.cidEncoding || ""; + this.vertical = !!properties.vertical; + if (this.vertical) { + this.vmetrics = properties.vmetrics; + this.defaultVMetrics = properties.defaultVMetrics; + } + if (!file2 || file2.isEmpty) { + if (file2) { + warn2('Font file is empty in "' + name + '" (' + this.loadedName + ")"); + } + this.fallbackToSystemFont(properties); + return; + } + [type, subtype] = getFontFileType(file2, properties); + if (type !== this.type || subtype !== this.subtype) { + info2(`Inconsistent font file Type/SubType, expected: ${this.type}/${this.subtype} but found: ${type}/${subtype}.`); + } + let data; + try { + switch (type) { + case "MMType1": + info2("MMType1 font (" + name + "), falling back to Type1."); + case "Type1": + case "CIDFontType0": + this.mimetype = "font/opentype"; + const cff = subtype === "Type1C" || subtype === "CIDFontType0C" ? new CFFFont(file2, properties) : new Type1Font(name, file2, properties); + adjustWidths(properties); + data = this.convert(name, cff, properties); + break; + case "OpenType": + case "TrueType": + case "CIDFontType2": + this.mimetype = "font/opentype"; + data = this.checkAndRepair(name, file2, properties); + adjustWidths(properties); + if (this.isOpenType) { + type = "OpenType"; + } + break; + default: + throw new FormatError3(`Font ${type} is not supported`); + } + } catch (e) { + warn2(e); + this.fallbackToSystemFont(properties); + return; + } + amendFallbackToUnicode(properties); + this.data = data; + this.type = type; + this.subtype = subtype; + this.fontMatrix = properties.fontMatrix; + this.widths = properties.widths; + this.defaultWidth = properties.defaultWidth; + this.toUnicode = properties.toUnicode; + this.seacMap = properties.seacMap; + } + get renderer() { + const renderer = FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED); + return shadow2(this, "renderer", renderer); + } + exportData() { + const data = /* @__PURE__ */ Object.create(null); + for (const prop of EXPORT_DATA_PROPERTIES) { + const value = this[prop]; + if (value !== void 0) { + data[prop] = value; + } + } + if (!this.fontExtraProperties) { + return { + data + }; + } + const extra = /* @__PURE__ */ Object.create(null); + for (const prop of EXPORT_DATA_EXTRA_PROPERTIES) { + const value = this[prop]; + if (value !== void 0) { + extra[prop] = value; + } + } + return { + data, + extra + }; + } + fallbackToSystemFont(properties) { + this.missingFile = true; + const { + name, + type + } = this; + let fontName = normalizeFontName(name); + const stdFontMap = getStdFontMap(), nonStdFontMap = getNonStdFontMap(); + const isStandardFont = !!stdFontMap[fontName]; + const isMappedToStandardFont = !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]); + fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName; + const fontBasicMetricsMap = getFontBasicMetrics(); + const metrics2 = fontBasicMetricsMap[fontName]; + if (metrics2) { + if (isNaN(this.ascent)) { + this.ascent = metrics2.ascent / PDF_GLYPH_SPACE_UNITS; + } + if (isNaN(this.descent)) { + this.descent = metrics2.descent / PDF_GLYPH_SPACE_UNITS; + } + if (isNaN(this.capHeight)) { + this.capHeight = metrics2.capHeight / PDF_GLYPH_SPACE_UNITS; + } + } + this.bold = /bold/gi.test(fontName); + this.italic = /oblique|italic/gi.test(fontName); + this.black = /Black/g.test(name); + const isNarrow = /Narrow/g.test(name); + this.remeasure = (!isStandardFont || isNarrow) && Object.keys(this.widths).length > 0; + if ((isStandardFont || isMappedToStandardFont) && type === "CIDFontType2" && this.cidEncoding.startsWith("Identity-")) { + const cidToGidMap = properties.cidToGidMap; + const map3 = []; + applyStandardFontGlyphMap(map3, getGlyphMapForStandardFonts()); + if (/Arial-?Black/i.test(name)) { + applyStandardFontGlyphMap(map3, getSupplementalGlyphMapForArialBlack()); + } else if (/Calibri/i.test(name)) { + applyStandardFontGlyphMap(map3, getSupplementalGlyphMapForCalibri()); + } + if (cidToGidMap) { + for (const charCode in map3) { + const cid = map3[charCode]; + if (cidToGidMap[cid] !== void 0) { + map3[+charCode] = cidToGidMap[cid]; + } + } + if (cidToGidMap.length !== this.toUnicode.length && properties.hasIncludedToUnicodeMap && this.toUnicode instanceof IdentityToUnicodeMap) { + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + const cid = map3[charCode]; + if (cidToGidMap[cid] === void 0) { + map3[+charCode] = unicodeCharCode; + } + }); + } + } + if (!(this.toUnicode instanceof IdentityToUnicodeMap)) { + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + map3[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map3; + this.toUnicode = new ToUnicodeMap(map3); + } else if (/Symbol/i.test(fontName)) { + this.toFontChar = buildToFontChar(SymbolSetEncoding, getGlyphsUnicode(), this.differences); + } else if (/Dingbats/i.test(fontName)) { + this.toFontChar = buildToFontChar(ZapfDingbatsEncoding, getDingbatsGlyphsUnicode(), this.differences); + } else if (isStandardFont || isMappedToStandardFont) { + const map3 = buildToFontChar(this.defaultEncoding, getGlyphsUnicode(), this.differences); + if (type === "CIDFontType2" && !this.cidEncoding.startsWith("Identity-") && !(this.toUnicode instanceof IdentityToUnicodeMap)) { + this.toUnicode.forEach(function(charCode, unicodeCharCode) { + map3[+charCode] = unicodeCharCode; + }); + } + this.toFontChar = map3; + } else { + const glyphsUnicodeMap = getGlyphsUnicode(); + const map3 = []; + this.toUnicode.forEach((charCode, unicodeCharCode) => { + if (!this.composite) { + const glyphName = this.differences[charCode] || this.defaultEncoding[charCode]; + const unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + unicodeCharCode = unicode; + } + } + map3[+charCode] = unicodeCharCode; + }); + if (this.composite && this.toUnicode instanceof IdentityToUnicodeMap) { + if (/Tahoma|Verdana/i.test(name)) { + applyStandardFontGlyphMap(map3, getGlyphMapForStandardFonts()); + } + } + this.toFontChar = map3; + } + amendFallbackToUnicode(properties); + this.loadedName = fontName.split("-", 1)[0]; + } + checkAndRepair(name, font, properties) { + const VALID_TABLES = ["OS/2", "cmap", "head", "hhea", "hmtx", "maxp", "name", "post", "loca", "glyf", "fpgm", "prep", "cvt ", "CFF "]; + function readTables(file2, numTables) { + const tables2 = /* @__PURE__ */ Object.create(null); + tables2["OS/2"] = null; + tables2.cmap = null; + tables2.head = null; + tables2.hhea = null; + tables2.hmtx = null; + tables2.maxp = null; + tables2.name = null; + tables2.post = null; + for (let i = 0; i < numTables; i++) { + const table2 = readTableEntry(file2); + if (!VALID_TABLES.includes(table2.tag)) { + continue; + } + if (table2.length === 0) { + continue; + } + tables2[table2.tag] = table2; + } + return tables2; + } + function readTableEntry(file2) { + const tag2 = file2.getString(4); + const checksum = file2.getInt32() >>> 0; + const offset = file2.getInt32() >>> 0; + const length = file2.getInt32() >>> 0; + const previousPosition = file2.pos; + file2.pos = file2.start || 0; + file2.skip(offset); + const data = file2.getBytes(length); + file2.pos = previousPosition; + if (tag2 === "head") { + data[8] = data[9] = data[10] = data[11] = 0; + data[17] |= 32; + } + return { + tag: tag2, + checksum, + length, + offset, + data + }; + } + function readOpenTypeHeader(ttf) { + return { + version: ttf.getString(4), + numTables: ttf.getUint16(), + searchRange: ttf.getUint16(), + entrySelector: ttf.getUint16(), + rangeShift: ttf.getUint16() + }; + } + function readTrueTypeCollectionHeader(ttc) { + const ttcTag = ttc.getString(4); + assert3(ttcTag === "ttcf", "Must be a TrueType Collection font."); + const majorVersion = ttc.getUint16(); + const minorVersion = ttc.getUint16(); + const numFonts = ttc.getInt32() >>> 0; + const offsetTable = []; + for (let i = 0; i < numFonts; i++) { + offsetTable.push(ttc.getInt32() >>> 0); + } + const header2 = { + ttcTag, + majorVersion, + minorVersion, + numFonts, + offsetTable + }; + switch (majorVersion) { + case 1: + return header2; + case 2: + header2.dsigTag = ttc.getInt32() >>> 0; + header2.dsigLength = ttc.getInt32() >>> 0; + header2.dsigOffset = ttc.getInt32() >>> 0; + return header2; + } + throw new FormatError3(`Invalid TrueType Collection majorVersion: ${majorVersion}.`); + } + function readTrueTypeCollectionData(ttc, fontName) { + const { + numFonts, + offsetTable + } = readTrueTypeCollectionHeader(ttc); + const fontNameParts = fontName.split("+"); + let fallbackData; + for (let i = 0; i < numFonts; i++) { + ttc.pos = (ttc.start || 0) + offsetTable[i]; + const potentialHeader = readOpenTypeHeader(ttc); + const potentialTables = readTables(ttc, potentialHeader.numTables); + if (!potentialTables.name) { + throw new FormatError3('TrueType Collection font must contain a "name" table.'); + } + const [nameTable] = readNameTable(potentialTables.name); + for (let j = 0, jj = nameTable.length; j < jj; j++) { + for (let k = 0, kk = nameTable[j].length; k < kk; k++) { + const nameEntry = nameTable[j][k]?.replaceAll(/\s/g, ""); + if (!nameEntry) { + continue; + } + if (nameEntry === fontName) { + return { + header: potentialHeader, + tables: potentialTables + }; + } + if (fontNameParts.length < 2) { + continue; + } + for (const part of fontNameParts) { + if (nameEntry === part) { + fallbackData = { + name: part, + header: potentialHeader, + tables: potentialTables + }; + } + } + } + } + } + if (fallbackData) { + warn2(`TrueType Collection does not contain "${fontName}" font, falling back to "${fallbackData.name}" font instead.`); + return { + header: fallbackData.header, + tables: fallbackData.tables + }; + } + throw new FormatError3(`TrueType Collection does not contain "${fontName}" font.`); + } + function readCmapTable(cmap, file2, isSymbolicFont, hasEncoding) { + if (!cmap) { + warn2("No cmap table available."); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + let segment; + let start = (file2.start || 0) + cmap.offset; + file2.pos = start; + file2.skip(2); + const numTables = file2.getUint16(); + let potentialTable; + let canBreak = false; + for (let i = 0; i < numTables; i++) { + const platformId = file2.getUint16(); + const encodingId = file2.getUint16(); + const offset = file2.getInt32() >>> 0; + let useTable = false; + if (potentialTable?.platformId === platformId && potentialTable?.encodingId === encodingId) { + continue; + } + if (platformId === 0 && (encodingId === 0 || encodingId === 1 || encodingId === 3)) { + useTable = true; + } else if (platformId === 1 && encodingId === 0) { + useTable = true; + } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) { + useTable = true; + if (!isSymbolicFont) { + canBreak = true; + } + } else if (isSymbolicFont && platformId === 3 && encodingId === 0) { + useTable = true; + let correctlySorted = true; + if (i < numTables - 1) { + const nextBytes = file2.peekBytes(2), nextPlatformId = int16(nextBytes[0], nextBytes[1]); + if (nextPlatformId < platformId) { + correctlySorted = false; + } + } + if (correctlySorted) { + canBreak = true; + } + } + if (useTable) { + potentialTable = { + platformId, + encodingId, + offset + }; + } + if (canBreak) { + break; + } + } + if (potentialTable) { + file2.pos = start + potentialTable.offset; + } + if (!potentialTable || file2.peekByte() === -1) { + warn2("Could not find a preferred cmap table."); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + const format = file2.getUint16(); + let hasShortCmap = false; + const mappings = []; + let j, glyphId; + if (format === 0) { + file2.skip(2 + 2); + for (j = 0; j < 256; j++) { + const index2 = file2.getByte(); + if (!index2) { + continue; + } + mappings.push({ + charCode: j, + glyphId: index2 + }); + } + hasShortCmap = true; + } else if (format === 2) { + file2.skip(2 + 2); + const subHeaderKeys = []; + let maxSubHeaderKey = 0; + for (let i = 0; i < 256; i++) { + const subHeaderKey = file2.getUint16() >> 3; + subHeaderKeys.push(subHeaderKey); + maxSubHeaderKey = Math.max(subHeaderKey, maxSubHeaderKey); + } + const subHeaders = []; + for (let i = 0; i <= maxSubHeaderKey; i++) { + subHeaders.push({ + firstCode: file2.getUint16(), + entryCount: file2.getUint16(), + idDelta: signedInt16(file2.getByte(), file2.getByte()), + idRangePos: file2.pos + file2.getUint16() + }); + } + for (let i = 0; i < 256; i++) { + if (subHeaderKeys[i] === 0) { + file2.pos = subHeaders[0].idRangePos + 2 * i; + glyphId = file2.getUint16(); + mappings.push({ + charCode: i, + glyphId + }); + } else { + const s = subHeaders[subHeaderKeys[i]]; + for (j = 0; j < s.entryCount; j++) { + const charCode = (i << 8) + j + s.firstCode; + file2.pos = s.idRangePos + 2 * j; + glyphId = file2.getUint16(); + if (glyphId !== 0) { + glyphId = (glyphId + s.idDelta) % 65536; + } + mappings.push({ + charCode, + glyphId + }); + } + } + } + } else if (format === 4) { + file2.skip(2 + 2); + const segCount = file2.getUint16() >> 1; + file2.skip(6); + const segments = []; + let segIndex; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments.push({ + end: file2.getUint16() + }); + } + file2.skip(2); + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].start = file2.getUint16(); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segments[segIndex].delta = file2.getUint16(); + } + let offsetsCount = 0, offsetIndex; + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + const rangeOffset = file2.getUint16(); + if (!rangeOffset) { + segment.offsetIndex = -1; + continue; + } + offsetIndex = (rangeOffset >> 1) - (segCount - segIndex); + segment.offsetIndex = offsetIndex; + offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1); + } + const offsets = []; + for (j = 0; j < offsetsCount; j++) { + offsets.push(file2.getUint16()); + } + for (segIndex = 0; segIndex < segCount; segIndex++) { + segment = segments[segIndex]; + start = segment.start; + const end = segment.end; + const delta = segment.delta; + offsetIndex = segment.offsetIndex; + for (j = start; j <= end; j++) { + if (j === 65535) { + continue; + } + glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start]; + glyphId = glyphId + delta & 65535; + mappings.push({ + charCode: j, + glyphId + }); + } + } + } else if (format === 6) { + file2.skip(2 + 2); + const firstCode = file2.getUint16(); + const entryCount = file2.getUint16(); + for (j = 0; j < entryCount; j++) { + glyphId = file2.getUint16(); + const charCode = firstCode + j; + mappings.push({ + charCode, + glyphId + }); + } + } else if (format === 12) { + file2.skip(2 + 4 + 4); + const nGroups = file2.getInt32() >>> 0; + for (j = 0; j < nGroups; j++) { + const startCharCode = file2.getInt32() >>> 0; + const endCharCode = file2.getInt32() >>> 0; + let glyphCode = file2.getInt32() >>> 0; + for (let charCode = startCharCode; charCode <= endCharCode; charCode++) { + mappings.push({ + charCode, + glyphId: glyphCode++ + }); + } + } + } else { + warn2("cmap table has unsupported format: " + format); + return { + platformId: -1, + encodingId: -1, + mappings: [], + hasShortCmap: false + }; + } + mappings.sort((a, b2) => a.charCode - b2.charCode); + const finalMappings = [], seenCharCodes = /* @__PURE__ */ new Set(); + for (const map3 of mappings) { + const { + charCode + } = map3; + if (seenCharCodes.has(charCode)) { + continue; + } + seenCharCodes.add(charCode); + finalMappings.push(map3); + } + return { + platformId: potentialTable.platformId, + encodingId: potentialTable.encodingId, + mappings: finalMappings, + hasShortCmap + }; + } + function sanitizeMetrics(file2, header2, metrics2, headTable, numGlyphs2, dupFirstEntry2) { + if (!header2) { + if (metrics2) { + metrics2.data = null; + } + return; + } + file2.pos = (file2.start || 0) + header2.offset; + file2.pos += 4; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + file2.pos += 2; + const caretOffset = file2.getUint16(); + file2.pos += 8; + file2.pos += 2; + let numOfMetrics = file2.getUint16(); + if (caretOffset !== 0) { + const macStyle = int16(headTable.data[44], headTable.data[45]); + if (!(macStyle & 2)) { + header2.data[22] = 0; + header2.data[23] = 0; + } + } + if (numOfMetrics > numGlyphs2) { + info2(`The numOfMetrics (${numOfMetrics}) should not be greater than the numGlyphs (${numGlyphs2}).`); + numOfMetrics = numGlyphs2; + header2.data[34] = (numOfMetrics & 65280) >> 8; + header2.data[35] = numOfMetrics & 255; + } + const numOfSidebearings = numGlyphs2 - numOfMetrics; + const numMissing = numOfSidebearings - (metrics2.length - numOfMetrics * 4 >> 1); + if (numMissing > 0) { + const entries = new Uint8Array(metrics2.length + numMissing * 2); + entries.set(metrics2.data); + if (dupFirstEntry2) { + entries[metrics2.length] = metrics2.data[2]; + entries[metrics2.length + 1] = metrics2.data[3]; + } + metrics2.data = entries; + } + } + function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid2) { + const glyphProfile = { + length: 0, + sizeOfInstructions: 0 + }; + if (sourceStart < 0 || sourceStart >= source.length || sourceEnd > source.length || sourceEnd - sourceStart <= 12) { + return glyphProfile; + } + const glyf = source.subarray(sourceStart, sourceEnd); + const xMin = signedInt16(glyf[2], glyf[3]); + const yMin = signedInt16(glyf[4], glyf[5]); + const xMax = signedInt16(glyf[6], glyf[7]); + const yMax = signedInt16(glyf[8], glyf[9]); + if (xMin > xMax) { + writeSignedInt16(glyf, 2, xMax); + writeSignedInt16(glyf, 6, xMin); + } + if (yMin > yMax) { + writeSignedInt16(glyf, 4, yMax); + writeSignedInt16(glyf, 8, yMin); + } + const contoursCount = signedInt16(glyf[0], glyf[1]); + if (contoursCount < 0) { + if (contoursCount < -1) { + return glyphProfile; + } + dest.set(glyf, destStart); + glyphProfile.length = glyf.length; + return glyphProfile; + } + let i, j = 10, flagsCount = 0; + for (i = 0; i < contoursCount; i++) { + const endPoint = glyf[j] << 8 | glyf[j + 1]; + flagsCount = endPoint + 1; + j += 2; + } + const instructionsStart = j; + const instructionsLength = glyf[j] << 8 | glyf[j + 1]; + glyphProfile.sizeOfInstructions = instructionsLength; + j += 2 + instructionsLength; + const instructionsEnd = j; + let coordinatesLength = 0; + for (i = 0; i < flagsCount; i++) { + const flag = glyf[j++]; + if (flag & 192) { + glyf[j - 1] = flag & 63; + } + let xLength = 2; + if (flag & 2) { + xLength = 1; + } else if (flag & 16) { + xLength = 0; + } + let yLength = 2; + if (flag & 4) { + yLength = 1; + } else if (flag & 32) { + yLength = 0; + } + const xyLength = xLength + yLength; + coordinatesLength += xyLength; + if (flag & 8) { + const repeat = glyf[j++]; + if (repeat === 0) { + glyf[j - 1] ^= 8; + } + i += repeat; + coordinatesLength += repeat * xyLength; + } + } + if (coordinatesLength === 0) { + return glyphProfile; + } + let glyphDataLength = j + coordinatesLength; + if (glyphDataLength > glyf.length) { + return glyphProfile; + } + if (!hintsValid2 && instructionsLength > 0) { + dest.set(glyf.subarray(0, instructionsStart), destStart); + dest.set([0, 0], destStart + instructionsStart); + dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2); + glyphDataLength -= instructionsLength; + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + } + glyphProfile.length = glyphDataLength; + return glyphProfile; + } + if (glyf.length - glyphDataLength > 3) { + glyphDataLength = glyphDataLength + 3 & ~3; + dest.set(glyf.subarray(0, glyphDataLength), destStart); + glyphProfile.length = glyphDataLength; + return glyphProfile; + } + dest.set(glyf, destStart); + glyphProfile.length = glyf.length; + return glyphProfile; + } + function sanitizeHead(head, numGlyphs2, locaLength) { + const data = head.data; + const version5 = int322(data[0], data[1], data[2], data[3]); + if (version5 >> 16 !== 1) { + info2("Attempting to fix invalid version in head table: " + version5); + data[0] = 0; + data[1] = 1; + data[2] = 0; + data[3] = 0; + } + const indexToLocFormat = int16(data[50], data[51]); + if (indexToLocFormat < 0 || indexToLocFormat > 1) { + info2("Attempting to fix invalid indexToLocFormat in head table: " + indexToLocFormat); + const numGlyphsPlusOne = numGlyphs2 + 1; + if (locaLength === numGlyphsPlusOne << 1) { + data[50] = 0; + data[51] = 0; + } else if (locaLength === numGlyphsPlusOne << 2) { + data[50] = 0; + data[51] = 1; + } else { + throw new FormatError3("Could not fix indexToLocFormat: " + indexToLocFormat); + } + } + } + function sanitizeGlyphLocations(loca, glyf, numGlyphs2, isGlyphLocationsLong, hintsValid2, dupFirstEntry2, maxSizeOfInstructions2) { + let itemSize, itemDecode, itemEncode; + if (isGlyphLocationsLong) { + itemSize = 4; + itemDecode = function fontItemDecodeLong(data, offset) { + return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]; + }; + itemEncode = function fontItemEncodeLong(data, offset, value) { + data[offset] = value >>> 24 & 255; + data[offset + 1] = value >> 16 & 255; + data[offset + 2] = value >> 8 & 255; + data[offset + 3] = value & 255; + }; + } else { + itemSize = 2; + itemDecode = function fontItemDecode(data, offset) { + return data[offset] << 9 | data[offset + 1] << 1; + }; + itemEncode = function fontItemEncode(data, offset, value) { + data[offset] = value >> 9 & 255; + data[offset + 1] = value >> 1 & 255; + }; + } + const numGlyphsOut2 = dupFirstEntry2 ? numGlyphs2 + 1 : numGlyphs2; + const locaDataSize = itemSize * (1 + numGlyphsOut2); + const locaData = new Uint8Array(locaDataSize); + locaData.set(loca.data.subarray(0, locaDataSize)); + loca.data = locaData; + const oldGlyfData = glyf.data; + const oldGlyfDataLength = oldGlyfData.length; + const newGlyfData = new Uint8Array(oldGlyfDataLength); + let i, j; + const locaEntries = []; + for (i = 0, j = 0; i < numGlyphs2 + 1; i++, j += itemSize) { + let offset = itemDecode(locaData, j); + if (offset > oldGlyfDataLength) { + offset = oldGlyfDataLength; + } + locaEntries.push({ + index: i, + offset, + endOffset: 0 + }); + } + locaEntries.sort((a, b2) => a.offset - b2.offset); + for (i = 0; i < numGlyphs2; i++) { + locaEntries[i].endOffset = locaEntries[i + 1].offset; + } + locaEntries.sort((a, b2) => a.index - b2.index); + for (i = 0; i < numGlyphs2; i++) { + const { + offset, + endOffset + } = locaEntries[i]; + if (offset !== 0 || endOffset !== 0) { + break; + } + const nextOffset = locaEntries[i + 1].offset; + if (nextOffset === 0) { + continue; + } + locaEntries[i].endOffset = nextOffset; + break; + } + const last2 = locaEntries.at(-2); + if (last2.offset !== 0 && last2.endOffset === 0) { + last2.endOffset = oldGlyfDataLength; + } + const missingGlyphs2 = /* @__PURE__ */ Object.create(null); + let writeOffset = 0; + itemEncode(locaData, 0, writeOffset); + for (i = 0, j = itemSize; i < numGlyphs2; i++, j += itemSize) { + const glyphProfile = sanitizeGlyph(oldGlyfData, locaEntries[i].offset, locaEntries[i].endOffset, newGlyfData, writeOffset, hintsValid2); + const newLength = glyphProfile.length; + if (newLength === 0) { + missingGlyphs2[i] = true; + } + if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions2) { + maxSizeOfInstructions2 = glyphProfile.sizeOfInstructions; + } + writeOffset += newLength; + itemEncode(locaData, j, writeOffset); + } + if (writeOffset === 0) { + const simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]); + for (i = 0, j = itemSize; i < numGlyphsOut2; i++, j += itemSize) { + itemEncode(locaData, j, simpleGlyph.length); + } + glyf.data = simpleGlyph; + } else if (dupFirstEntry2) { + const firstEntryLength = itemDecode(locaData, itemSize); + if (newGlyfData.length > firstEntryLength + writeOffset) { + glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset); + } else { + glyf.data = new Uint8Array(firstEntryLength + writeOffset); + glyf.data.set(newGlyfData.subarray(0, writeOffset)); + } + glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset); + itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength); + } else { + glyf.data = newGlyfData.subarray(0, writeOffset); + } + return { + missingGlyphs: missingGlyphs2, + maxSizeOfInstructions: maxSizeOfInstructions2 + }; + } + function readPostScriptTable(post, propertiesObj, maxpNumGlyphs) { + const start = (font.start || 0) + post.offset; + font.pos = start; + const length = post.length, end = start + length; + const version5 = font.getInt32(); + font.skip(28); + let glyphNames; + let valid = true; + let i; + switch (version5) { + case 65536: + glyphNames = MacStandardGlyphOrdering; + break; + case 131072: + const numGlyphs2 = font.getUint16(); + if (numGlyphs2 !== maxpNumGlyphs) { + valid = false; + break; + } + const glyphNameIndexes = []; + for (i = 0; i < numGlyphs2; ++i) { + const index2 = font.getUint16(); + if (index2 >= 32768) { + valid = false; + break; + } + glyphNameIndexes.push(index2); + } + if (!valid) { + break; + } + const customNames = [], strBuf = []; + while (font.pos < end) { + const stringLength = font.getByte(); + strBuf.length = stringLength; + for (i = 0; i < stringLength; ++i) { + strBuf[i] = String.fromCharCode(font.getByte()); + } + customNames.push(strBuf.join("")); + } + glyphNames = []; + for (i = 0; i < numGlyphs2; ++i) { + const j = glyphNameIndexes[i]; + if (j < 258) { + glyphNames.push(MacStandardGlyphOrdering[j]); + continue; + } + glyphNames.push(customNames[j - 258]); + } + break; + case 196608: + break; + default: + warn2("Unknown/unsupported post table version " + version5); + valid = false; + if (propertiesObj.defaultEncoding) { + glyphNames = propertiesObj.defaultEncoding; + } + break; + } + propertiesObj.glyphNames = glyphNames; + return valid; + } + function readNameTable(nameTable) { + const start = (font.start || 0) + nameTable.offset; + font.pos = start; + const names = [[], []], records = []; + const length = nameTable.length, end = start + length; + const format = font.getUint16(); + const FORMAT_0_HEADER_LENGTH = 6; + if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) { + return [names, records]; + } + const numRecords = font.getUint16(); + const stringsStart = font.getUint16(); + const NAME_RECORD_LENGTH = 12; + let i, ii; + for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) { + const r = { + platform: font.getUint16(), + encoding: font.getUint16(), + language: font.getUint16(), + name: font.getUint16(), + length: font.getUint16(), + offset: font.getUint16() + }; + if (isMacNameRecord(r) || isWinNameRecord(r)) { + records.push(r); + } + } + for (i = 0, ii = records.length; i < ii; i++) { + const record2 = records[i]; + if (record2.length <= 0) { + continue; + } + const pos = start + stringsStart + record2.offset; + if (pos + record2.length > end) { + continue; + } + font.pos = pos; + const nameIndex = record2.name; + if (record2.encoding) { + let str = ""; + for (let j = 0, jj = record2.length; j < jj; j += 2) { + str += String.fromCharCode(font.getUint16()); + } + names[1][nameIndex] = str; + } else { + names[0][nameIndex] = font.getString(record2.length); + } + } + return [names, records]; + } + const TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2]; + function sanitizeTTProgram(table2, ttContext) { + let data = table2.data; + let i = 0, j, n, b2, funcId, pc, lastEndf = 0, lastDeff = 0; + const stack = []; + const callstack = []; + const functionsCalled = []; + let tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions; + let inFDEF = false, ifLevel = 0, inELSE = 0; + for (let ii = data.length; i < ii; ) { + const op = data[i++]; + if (op === 64) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if (op === 65) { + n = data[i++]; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b2 = data[i++]; + stack.push(b2 << 8 | data[i++]); + } + } + } else if ((op & 248) === 176) { + n = op - 176 + 1; + if (inFDEF || inELSE) { + i += n; + } else { + for (j = 0; j < n; j++) { + stack.push(data[i++]); + } + } + } else if ((op & 248) === 184) { + n = op - 184 + 1; + if (inFDEF || inELSE) { + i += n * 2; + } else { + for (j = 0; j < n; j++) { + b2 = data[i++]; + stack.push(signedInt16(b2, data[i++])); + } + } + } else if (op === 43 && !tooComplexToFollowFunctions) { + if (!inFDEF && !inELSE) { + funcId = stack.at(-1); + if (isNaN(funcId)) { + info2("TT: CALL empty stack (or invalid entry)."); + } else { + ttContext.functionsUsed[funcId] = true; + if (funcId in ttContext.functionsStackDeltas) { + const newStackLength = stack.length + ttContext.functionsStackDeltas[funcId]; + if (newStackLength < 0) { + warn2("TT: CALL invalid functions stack delta."); + ttContext.hintsValid = false; + return; + } + stack.length = newStackLength; + } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) { + callstack.push({ + data, + i, + stackTop: stack.length - 1 + }); + functionsCalled.push(funcId); + pc = ttContext.functionsDefined[funcId]; + if (!pc) { + warn2("TT: CALL non-existent function"); + ttContext.hintsValid = false; + return; + } + data = pc.data; + i = pc.i; + } + } + } + } else if (op === 44 && !tooComplexToFollowFunctions) { + if (inFDEF || inELSE) { + warn2("TT: nested FDEFs not allowed"); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + funcId = stack.pop(); + ttContext.functionsDefined[funcId] = { + data, + i + }; + } else if (op === 45) { + if (inFDEF) { + inFDEF = false; + lastEndf = i; + } else { + pc = callstack.pop(); + if (!pc) { + warn2("TT: ENDF bad stack"); + ttContext.hintsValid = false; + return; + } + funcId = functionsCalled.pop(); + data = pc.data; + i = pc.i; + ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop; + } + } else if (op === 137) { + if (inFDEF || inELSE) { + warn2("TT: nested IDEFs not allowed"); + tooComplexToFollowFunctions = true; + } + inFDEF = true; + lastDeff = i; + } else if (op === 88) { + ++ifLevel; + } else if (op === 27) { + inELSE = ifLevel; + } else if (op === 89) { + if (inELSE === ifLevel) { + inELSE = 0; + } + --ifLevel; + } else if (op === 28) { + if (!inFDEF && !inELSE) { + const offset = stack.at(-1); + if (offset > 0) { + i += offset - 1; + } + } + } + if (!inFDEF && !inELSE) { + let stackDelta = 0; + if (op <= 142) { + stackDelta = TTOpsStackDeltas[op]; + } else if (op >= 192 && op <= 223) { + stackDelta = -1; + } else if (op >= 224) { + stackDelta = -2; + } + if (op >= 113 && op <= 117) { + n = stack.pop(); + if (!isNaN(n)) { + stackDelta = -n * 2; + } + } + while (stackDelta < 0 && stack.length > 0) { + stack.pop(); + stackDelta++; + } + while (stackDelta > 0) { + stack.push(NaN); + stackDelta--; + } + } + } + ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions; + const content = [data]; + if (i > data.length) { + content.push(new Uint8Array(i - data.length)); + } + if (lastDeff > lastEndf) { + warn2("TT: complementing a missing function tail"); + content.push(new Uint8Array([34, 45])); + } + foldTTTable(table2, content); + } + function checkInvalidFunctions(ttContext, maxFunctionDefs2) { + if (ttContext.tooComplexToFollowFunctions) { + return; + } + if (ttContext.functionsDefined.length > maxFunctionDefs2) { + warn2("TT: more functions defined than expected"); + ttContext.hintsValid = false; + return; + } + for (let j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) { + if (j > maxFunctionDefs2) { + warn2("TT: invalid function id: " + j); + ttContext.hintsValid = false; + return; + } + if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) { + warn2("TT: undefined function: " + j); + ttContext.hintsValid = false; + return; + } + } + } + function foldTTTable(table2, content) { + if (content.length > 1) { + let newLength = 0; + let j, jj; + for (j = 0, jj = content.length; j < jj; j++) { + newLength += content[j].length; + } + newLength = newLength + 3 & ~3; + const result2 = new Uint8Array(newLength); + let pos = 0; + for (j = 0, jj = content.length; j < jj; j++) { + result2.set(content[j], pos); + pos += content[j].length; + } + table2.data = result2; + table2.length = newLength; + } + } + function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs2) { + const ttContext = { + functionsDefined: [], + functionsUsed: [], + functionsStackDeltas: [], + tooComplexToFollowFunctions: false, + hintsValid: true + }; + if (fpgm) { + sanitizeTTProgram(fpgm, ttContext); + } + if (prep) { + sanitizeTTProgram(prep, ttContext); + } + if (fpgm) { + checkInvalidFunctions(ttContext, maxFunctionDefs2); + } + if (cvt && cvt.length & 1) { + const cvtData = new Uint8Array(cvt.length + 1); + cvtData.set(cvt.data); + cvt.data = cvtData; + } + return ttContext.hintsValid; + } + font = new Stream3(new Uint8Array(font.getBytes())); + let header, tables; + if (isTrueTypeCollectionFile(font)) { + const ttcData = readTrueTypeCollectionData(font, this.name); + header = ttcData.header; + tables = ttcData.tables; + } else { + header = readOpenTypeHeader(font); + tables = readTables(font, header.numTables); + } + let cff, cffFile; + const isTrueType = !tables["CFF "]; + if (!isTrueType) { + const isComposite = properties.composite && (properties.cidToGidMap?.length > 0 || !(properties.cMap instanceof IdentityCMap)); + if (header.version === "OTTO" && !isComposite || !tables.head || !tables.hhea || !tables.maxp || !tables.post) { + cffFile = new Stream3(tables["CFF "].data); + cff = new CFFFont(cffFile, properties); + return this.convert(name, cff, properties); + } + delete tables.glyf; + delete tables.loca; + delete tables.fpgm; + delete tables.prep; + delete tables["cvt "]; + this.isOpenType = true; + } else { + if (!tables.loca) { + throw new FormatError3('Required "loca" table is not found'); + } + if (!tables.glyf) { + warn2('Required "glyf" table is not found -- trying to recover.'); + tables.glyf = { + tag: "glyf", + data: new Uint8Array(0) + }; + } + this.isOpenType = false; + } + if (!tables.maxp) { + throw new FormatError3('Required "maxp" table is not found'); + } + font.pos = (font.start || 0) + tables.maxp.offset; + let version4 = font.getInt32(); + const numGlyphs = font.getUint16(); + if (version4 !== 65536 && version4 !== 20480) { + if (tables.maxp.length === 6) { + version4 = 20480; + } else if (tables.maxp.length >= 32) { + version4 = 65536; + } else { + throw new FormatError3(`"maxp" table has a wrong version number`); + } + writeUint32(tables.maxp.data, 0, version4); + } + if (properties.scaleFactors?.length === numGlyphs && isTrueType) { + const { + scaleFactors + } = properties; + const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); + const glyphs = new GlyfTable({ + glyfTable: tables.glyf.data, + isGlyphLocationsLong, + locaTable: tables.loca.data, + numGlyphs + }); + glyphs.scale(scaleFactors); + const { + glyf, + loca, + isLocationLong + } = glyphs.write(); + tables.glyf.data = glyf; + tables.loca.data = loca; + if (isLocationLong !== !!isGlyphLocationsLong) { + tables.head.data[50] = 0; + tables.head.data[51] = isLocationLong ? 1 : 0; + } + const metrics2 = tables.hmtx.data; + for (let i = 0; i < numGlyphs; i++) { + const j = 4 * i; + const advanceWidth = Math.round(scaleFactors[i] * int16(metrics2[j], metrics2[j + 1])); + metrics2[j] = advanceWidth >> 8 & 255; + metrics2[j + 1] = advanceWidth & 255; + const lsb = Math.round(scaleFactors[i] * signedInt16(metrics2[j + 2], metrics2[j + 3])); + writeSignedInt16(metrics2, j + 2, lsb); + } + } + let numGlyphsOut = numGlyphs + 1; + let dupFirstEntry = true; + if (numGlyphsOut > 65535) { + dupFirstEntry = false; + numGlyphsOut = numGlyphs; + warn2("Not enough space in glyfs to duplicate first glyph."); + } + let maxFunctionDefs = 0; + let maxSizeOfInstructions = 0; + if (version4 >= 65536 && tables.maxp.length >= 32) { + font.pos += 8; + const maxZones = font.getUint16(); + if (maxZones > 2) { + tables.maxp.data[14] = 0; + tables.maxp.data[15] = 2; + } + font.pos += 4; + maxFunctionDefs = font.getUint16(); + font.pos += 4; + maxSizeOfInstructions = font.getUint16(); + } + tables.maxp.data[4] = numGlyphsOut >> 8; + tables.maxp.data[5] = numGlyphsOut & 255; + const hintsValid = sanitizeTTPrograms(tables.fpgm, tables.prep, tables["cvt "], maxFunctionDefs); + if (!hintsValid) { + delete tables.fpgm; + delete tables.prep; + delete tables["cvt "]; + } + sanitizeMetrics(font, tables.hhea, tables.hmtx, tables.head, numGlyphsOut, dupFirstEntry); + if (!tables.head) { + throw new FormatError3('Required "head" table is not found'); + } + sanitizeHead(tables.head, numGlyphs, isTrueType ? tables.loca.length : 0); + let missingGlyphs = /* @__PURE__ */ Object.create(null); + if (isTrueType) { + const isGlyphLocationsLong = int16(tables.head.data[50], tables.head.data[51]); + const glyphsInfo = sanitizeGlyphLocations(tables.loca, tables.glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions); + missingGlyphs = glyphsInfo.missingGlyphs; + if (version4 >= 65536 && tables.maxp.length >= 32) { + tables.maxp.data[26] = glyphsInfo.maxSizeOfInstructions >> 8; + tables.maxp.data[27] = glyphsInfo.maxSizeOfInstructions & 255; + } + } + if (!tables.hhea) { + throw new FormatError3('Required "hhea" table is not found'); + } + if (tables.hhea.data[10] === 0 && tables.hhea.data[11] === 0) { + tables.hhea.data[10] = 255; + tables.hhea.data[11] = 255; + } + const metricsOverride = { + unitsPerEm: int16(tables.head.data[18], tables.head.data[19]), + yMax: signedInt16(tables.head.data[42], tables.head.data[43]), + yMin: signedInt16(tables.head.data[38], tables.head.data[39]), + ascent: signedInt16(tables.hhea.data[4], tables.hhea.data[5]), + descent: signedInt16(tables.hhea.data[6], tables.hhea.data[7]), + lineGap: signedInt16(tables.hhea.data[8], tables.hhea.data[9]) + }; + this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm; + this.descent = metricsOverride.descent / metricsOverride.unitsPerEm; + this.lineGap = metricsOverride.lineGap / metricsOverride.unitsPerEm; + if (this.cssFontInfo?.lineHeight) { + this.lineHeight = this.cssFontInfo.metrics.lineHeight; + this.lineGap = this.cssFontInfo.metrics.lineGap; + } else { + this.lineHeight = this.ascent - this.descent + this.lineGap; + } + if (tables.post) { + readPostScriptTable(tables.post, properties, numGlyphs); + } + tables.post = { + tag: "post", + data: createPostTable(properties) + }; + const charCodeToGlyphId = /* @__PURE__ */ Object.create(null); + function hasGlyph(glyphId) { + return !missingGlyphs[glyphId]; + } + if (properties.composite) { + const cidToGidMap = properties.cidToGidMap || []; + const isCidToGidMapEmpty = cidToGidMap.length === 0; + properties.cMap.forEach(function(charCode, cid) { + if (typeof cid === "string") { + cid = convertCidString(charCode, cid, true); + } + if (cid > 65535) { + throw new FormatError3("Max size of CID is 65,535"); + } + let glyphId = -1; + if (isCidToGidMapEmpty) { + glyphId = cid; + } else if (cidToGidMap[cid] !== void 0) { + glyphId = cidToGidMap[cid]; + } + if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) { + charCodeToGlyphId[charCode] = glyphId; + } + }); + } else { + const cmapTable = readCmapTable(tables.cmap, font, this.isSymbolicFont, properties.hasEncoding); + const cmapPlatformId = cmapTable.platformId; + const cmapEncodingId = cmapTable.encodingId; + const cmapMappings = cmapTable.mappings; + let baseEncoding = [], forcePostTable = false; + if (properties.hasEncoding && (properties.baseEncodingName === "MacRomanEncoding" || properties.baseEncodingName === "WinAnsiEncoding")) { + baseEncoding = getEncoding(properties.baseEncodingName); + } + if (properties.hasEncoding && !this.isSymbolicFont && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0)) { + const glyphsUnicodeMap = getGlyphsUnicode(); + for (let charCode = 0; charCode < 256; charCode++) { + let glyphName; + if (this.differences[charCode] !== void 0) { + glyphName = this.differences[charCode]; + } else if (baseEncoding.length && baseEncoding[charCode] !== "") { + glyphName = baseEncoding[charCode]; + } else { + glyphName = StandardEncoding[charCode]; + } + if (!glyphName) { + continue; + } + const standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap); + let unicodeOrCharCode; + if (cmapPlatformId === 3 && cmapEncodingId === 1) { + unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName]; + } else if (cmapPlatformId === 1 && cmapEncodingId === 0) { + unicodeOrCharCode = MacRomanEncoding.indexOf(standardGlyphName); + } + if (unicodeOrCharCode === void 0) { + if (!properties.glyphNames && properties.hasIncludedToUnicodeMap && !(this.toUnicode instanceof IdentityToUnicodeMap)) { + const unicode = this.toUnicode.get(charCode); + if (unicode) { + unicodeOrCharCode = unicode.codePointAt(0); + } + } + if (unicodeOrCharCode === void 0) { + continue; + } + } + for (const mapping of cmapMappings) { + if (mapping.charCode !== unicodeOrCharCode) { + continue; + } + charCodeToGlyphId[charCode] = mapping.glyphId; + break; + } + } + } else if (cmapPlatformId === 0) { + for (const mapping of cmapMappings) { + charCodeToGlyphId[mapping.charCode] = mapping.glyphId; + } + forcePostTable = true; + } else if (cmapPlatformId === 3 && cmapEncodingId === 0) { + for (const mapping of cmapMappings) { + let charCode = mapping.charCode; + if (charCode >= 61440 && charCode <= 61695) { + charCode &= 255; + } + charCodeToGlyphId[charCode] = mapping.glyphId; + } + } else { + for (const mapping of cmapMappings) { + charCodeToGlyphId[mapping.charCode] = mapping.glyphId; + } + } + if (properties.glyphNames && (baseEncoding.length || this.differences.length)) { + for (let i = 0; i < 256; ++i) { + if (!forcePostTable && charCodeToGlyphId[i] !== void 0) { + continue; + } + const glyphName = this.differences[i] || baseEncoding[i]; + if (!glyphName) { + continue; + } + const glyphId = properties.glyphNames.indexOf(glyphName); + if (glyphId > 0 && hasGlyph(glyphId)) { + charCodeToGlyphId[i] = glyphId; + } + } + } + } + if (charCodeToGlyphId.length === 0) { + charCodeToGlyphId[0] = 0; + } + let glyphZeroId = numGlyphsOut - 1; + if (!dupFirstEntry) { + glyphZeroId = 0; + } + if (!properties.cssFontInfo) { + const newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId, this.toUnicode); + this.toFontChar = newMapping.toFontChar; + tables.cmap = { + tag: "cmap", + data: createCmapTable(newMapping.charCodeToGlyphId, newMapping.toUnicodeExtraMap, numGlyphsOut) + }; + if (!tables["OS/2"] || !validateOS2Table(tables["OS/2"], font)) { + tables["OS/2"] = { + tag: "OS/2", + data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride) + }; + } + } + if (!isTrueType) { + try { + cffFile = new Stream3(tables["CFF "].data); + const parser = new CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED); + cff = parser.parse(); + cff.duplicateFirstGlyph(); + const compiler = new CFFCompiler(cff); + tables["CFF "].data = compiler.compile(); + } catch { + warn2("Failed to compile font " + properties.loadedName); + } + } + if (!tables.name) { + tables.name = { + tag: "name", + data: createNameTable(this.name) + }; + } else { + const [namePrototype, nameRecords] = readNameTable(tables.name); + tables.name.data = createNameTable(name, namePrototype); + this.psName = namePrototype[0][6] || null; + if (!properties.composite) { + adjustTrueTypeToUnicode(properties, this.isSymbolicFont, nameRecords); + } + } + const builder = new OpenTypeFileBuilder(header.version); + for (const tableTag in tables) { + builder.addTable(tableTag, tables[tableTag].data); + } + return builder.toArray(); + } + convert(fontName, font, properties) { + properties.fixedPitch = false; + if (properties.builtInEncoding) { + adjustType1ToUnicode(properties, properties.builtInEncoding); + } + let glyphZeroId = 1; + if (font instanceof CFFFont) { + glyphZeroId = font.numGlyphs - 1; + } + const mapping = font.getGlyphMapping(properties); + let newMapping = null; + let newCharCodeToGlyphId = mapping; + let toUnicodeExtraMap = null; + if (!properties.cssFontInfo) { + newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId, this.toUnicode); + this.toFontChar = newMapping.toFontChar; + newCharCodeToGlyphId = newMapping.charCodeToGlyphId; + toUnicodeExtraMap = newMapping.toUnicodeExtraMap; + } + const numGlyphs = font.numGlyphs; + function getCharCodes(charCodeToGlyphId, glyphId) { + let charCodes = null; + for (const charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + (charCodes ||= []).push(charCode | 0); + } + } + return charCodes; + } + function createCharCode(charCodeToGlyphId, glyphId) { + for (const charCode in charCodeToGlyphId) { + if (glyphId === charCodeToGlyphId[charCode]) { + return charCode | 0; + } + } + newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId; + return newMapping.nextAvailableFontCharCode++; + } + const seacs = font.seacs; + if (newMapping && SEAC_ANALYSIS_ENABLED && seacs?.length) { + const matrix = properties.fontMatrix || FONT_IDENTITY_MATRIX2; + const charset = font.getCharset(); + const seacMap = /* @__PURE__ */ Object.create(null); + for (let glyphId in seacs) { + glyphId |= 0; + const seac = seacs[glyphId]; + const baseGlyphName = StandardEncoding[seac[2]]; + const accentGlyphName = StandardEncoding[seac[3]]; + const baseGlyphId = charset.indexOf(baseGlyphName); + const accentGlyphId = charset.indexOf(accentGlyphName); + if (baseGlyphId < 0 || accentGlyphId < 0) { + continue; + } + const accentOffset = { + x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4], + y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5] + }; + const charCodes = getCharCodes(mapping, glyphId); + if (!charCodes) { + continue; + } + for (const charCode of charCodes) { + const charCodeToGlyphId = newMapping.charCodeToGlyphId; + const baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId); + const accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId); + seacMap[charCode] = { + baseFontCharCode, + accentFontCharCode, + accentOffset + }; + } + } + properties.seacMap = seacMap; + } + const unitsPerEm = properties.fontMatrix ? 1 / Math.max(...properties.fontMatrix.slice(0, 4).map(Math.abs)) : 1e3; + const builder = new OpenTypeFileBuilder("OTTO"); + builder.addTable("CFF ", font.data); + builder.addTable("OS/2", createOS2Table(properties, newCharCodeToGlyphId)); + builder.addTable("cmap", createCmapTable(newCharCodeToGlyphId, toUnicodeExtraMap, numGlyphs)); + builder.addTable("head", "\0\0\0\0\0\0\0\0\0\0_<\xF5\0\0" + safeString16(unitsPerEm) + "\0\0\0\0\x9E\v~'\0\0\0\0\x9E\v~'\0\0" + safeString16(properties.descent) + "\xFF" + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + "\0\0\0\0\0\0\0"); + builder.addTable("hhea", "\0\0\0" + safeString16(properties.ascent) + safeString16(properties.descent) + "\0\0\xFF\xFF\0\0\0\0\0\0" + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + "\0\0\0\0\0\0\0\0\0\0\0\0" + string16(numGlyphs)); + builder.addTable("hmtx", function fontFieldsHmtx() { + const charstrings = font.charstrings; + const cffWidths = font.cff ? font.cff.widths : null; + let hmtx = "\0\0\0\0"; + for (let i = 1, ii = numGlyphs; i < ii; i++) { + let width = 0; + if (charstrings) { + const charstring = charstrings[i - 1]; + width = "width" in charstring ? charstring.width : 0; + } else if (cffWidths) { + width = Math.ceil(cffWidths[i] || 0); + } + hmtx += string16(width) + string16(0); + } + return hmtx; + }()); + builder.addTable("maxp", "\0\0P\0" + string16(numGlyphs)); + builder.addTable("name", createNameTable(fontName)); + builder.addTable("post", createPostTable(properties)); + return builder.toArray(); + } + get _spaceWidth() { + const possibleSpaceReplacements = ["space", "minus", "one", "i", "I"]; + let width; + for (const glyphName of possibleSpaceReplacements) { + if (glyphName in this.widths) { + width = this.widths[glyphName]; + break; + } + const glyphsUnicodeMap = getGlyphsUnicode(); + const glyphUnicode = glyphsUnicodeMap[glyphName]; + let charcode = 0; + if (this.composite && this.cMap.contains(glyphUnicode)) { + charcode = this.cMap.lookup(glyphUnicode); + if (typeof charcode === "string") { + charcode = convertCidString(glyphUnicode, charcode); + } + } + if (!charcode && this.toUnicode) { + charcode = this.toUnicode.charCodeOf(glyphUnicode); + } + if (charcode <= 0) { + charcode = glyphUnicode; + } + width = this.widths[charcode]; + if (width) { + break; + } + } + return shadow2(this, "_spaceWidth", width || this.defaultWidth); + } + _charToGlyph(charcode, isSpace = false) { + let glyph = this._glyphCache[charcode]; + if (glyph?.isSpace === isSpace) { + return glyph; + } + let fontCharCode, width, operatorListId; + let widthCode = charcode; + if (this.cMap?.contains(charcode)) { + widthCode = this.cMap.lookup(charcode); + if (typeof widthCode === "string") { + widthCode = convertCidString(charcode, widthCode); + } + } + width = this.widths[widthCode]; + if (typeof width !== "number") { + width = this.defaultWidth; + } + const vmetric = this.vmetrics?.[widthCode]; + let unicode = this.toUnicode.get(charcode) || charcode; + if (typeof unicode === "number") { + unicode = String.fromCharCode(unicode); + } + let isInFont = this.toFontChar[charcode] !== void 0; + fontCharCode = this.toFontChar[charcode] || charcode; + if (this.missingFile) { + const glyphName = this.differences[charcode] || this.defaultEncoding[charcode]; + if ((glyphName === ".notdef" || glyphName === "") && this.type === "Type1") { + fontCharCode = 32; + if (glyphName === "") { + width ||= this._spaceWidth; + unicode = String.fromCharCode(fontCharCode); + } + } + fontCharCode = mapSpecialUnicodeValues(fontCharCode); + } + if (this.isType3Font) { + operatorListId = fontCharCode; + } + let accent = null; + if (this.seacMap?.[charcode]) { + isInFont = true; + const seac = this.seacMap[charcode]; + fontCharCode = seac.baseFontCharCode; + accent = { + fontChar: String.fromCodePoint(seac.accentFontCharCode), + offset: seac.accentOffset + }; + } + let fontChar = ""; + if (typeof fontCharCode === "number") { + if (fontCharCode <= 1114111) { + fontChar = String.fromCodePoint(fontCharCode); + } else { + warn2(`charToGlyph - invalid fontCharCode: ${fontCharCode}`); + } + } + if (this.missingFile && this.vertical && fontChar.length === 1) { + const vertical = getVerticalPresentationForm()[fontChar.charCodeAt(0)]; + if (vertical) { + fontChar = unicode = String.fromCharCode(vertical); + } + } + glyph = new fonts_Glyph(charcode, fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont); + return this._glyphCache[charcode] = glyph; + } + charsToGlyphs(chars2) { + let glyphs = this._charsCache[chars2]; + if (glyphs) { + return glyphs; + } + glyphs = []; + if (this.cMap) { + const c = /* @__PURE__ */ Object.create(null), ii = chars2.length; + let i = 0; + while (i < ii) { + this.cMap.readCharCode(chars2, i, c); + const { + charcode, + length + } = c; + i += length; + const glyph = this._charToGlyph(charcode, length === 1 && chars2.charCodeAt(i - 1) === 32); + glyphs.push(glyph); + } + } else { + for (let i = 0, ii = chars2.length; i < ii; ++i) { + const charcode = chars2.charCodeAt(i); + const glyph = this._charToGlyph(charcode, charcode === 32); + glyphs.push(glyph); + } + } + return this._charsCache[chars2] = glyphs; + } + getCharPositions(chars2) { + const positions = []; + if (this.cMap) { + const c = /* @__PURE__ */ Object.create(null); + let i = 0; + while (i < chars2.length) { + this.cMap.readCharCode(chars2, i, c); + const length = c.length; + positions.push([i, i + length]); + i += length; + } + } else { + for (let i = 0, ii = chars2.length; i < ii; ++i) { + positions.push([i, i + 1]); + } + } + return positions; + } + get glyphCacheValues() { + return Object.values(this._glyphCache); + } + encodeString(str) { + const buffers = []; + const currentBuf = []; + const hasCurrentBufErrors = () => buffers.length % 2 === 1; + const getCharCode = this.toUnicode instanceof IdentityToUnicodeMap ? (unicode) => this.toUnicode.charCodeOf(unicode) : (unicode) => this.toUnicode.charCodeOf(String.fromCodePoint(unicode)); + for (let i = 0, ii = str.length; i < ii; i++) { + const unicode = str.codePointAt(i); + if (unicode > 55295 && (unicode < 57344 || unicode > 65533)) { + i++; + } + if (this.toUnicode) { + const charCode = getCharCode(unicode); + if (charCode !== -1) { + if (hasCurrentBufErrors()) { + buffers.push(currentBuf.join("")); + currentBuf.length = 0; + } + const charCodeLength = this.cMap ? this.cMap.getCharCodeLength(charCode) : 1; + for (let j = charCodeLength - 1; j >= 0; j--) { + currentBuf.push(String.fromCharCode(charCode >> 8 * j & 255)); + } + continue; + } + } + if (!hasCurrentBufErrors()) { + buffers.push(currentBuf.join("")); + currentBuf.length = 0; + } + currentBuf.push(String.fromCodePoint(unicode)); + } + buffers.push(currentBuf.join("")); + return buffers; + } + }; + ErrorFont = class { + constructor(error62) { + this.error = error62; + this.loadedName = "g_font_error"; + this.missingFile = true; + } + charsToGlyphs() { + return []; + } + encodeString(chars2) { + return [chars2]; + } + exportData() { + return { + error: this.error + }; + } + }; + ShadingType = { + FUNCTION_BASED: 1, + AXIAL: 2, + RADIAL: 3, + FREE_FORM_MESH: 4, + LATTICE_FORM_MESH: 5, + COONS_PATCH_MESH: 6, + TENSOR_PATCH_MESH: 7 + }; + Pattern = class { + constructor() { + unreachable2("Cannot initialize Pattern."); + } + static parseShading(shading, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + const dict = shading instanceof BaseStream ? shading.dict : shading; + const type = dict.get("ShadingType"); + try { + switch (type) { + case ShadingType.AXIAL: + case ShadingType.RADIAL: + return new RadialAxialShading(dict, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache); + case ShadingType.FREE_FORM_MESH: + case ShadingType.LATTICE_FORM_MESH: + case ShadingType.COONS_PATCH_MESH: + case ShadingType.TENSOR_PATCH_MESH: + return new MeshShading(shading, xref, res, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache); + default: + throw new FormatError3("Unsupported ShadingType: " + type); + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(ex); + return new DummyShading(); + } + } + }; + BaseShading = class { + static SMALL_NUMBER = 1e-6; + getIR() { + unreachable2("Abstract method `getIR` called."); + } + }; + RadialAxialShading = class extends BaseShading { + constructor(dict, xref, resources, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + super(); + this.shadingType = dict.get("ShadingType"); + let coordsLen = 0; + if (this.shadingType === ShadingType.AXIAL) { + coordsLen = 4; + } else if (this.shadingType === ShadingType.RADIAL) { + coordsLen = 6; + } + this.coordsArr = dict.getArray("Coords"); + if (!isNumberArray(this.coordsArr, coordsLen)) { + throw new FormatError3("RadialAxialShading: Invalid /Coords array."); + } + const cs = ColorSpaceUtils.parse({ + cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.bbox = lookupNormalRect(dict.getArray("BBox"), null); + let t0 = 0, t1 = 1; + const domainArr = dict.getArray("Domain"); + if (isNumberArray(domainArr, 2)) { + [t0, t1] = domainArr; + } + let extendStart = false, extendEnd = false; + const extendArr = dict.getArray("Extend"); + if (isBooleanArray(extendArr, 2)) { + [extendStart, extendEnd] = extendArr; + } + if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) { + const [x1, y1, r1, x2, y2, r2] = this.coordsArr; + const distance = Math.hypot(x1 - x2, y1 - y2); + if (r1 <= r2 + distance && r2 <= r1 + distance) { + warn2("Unsupported radial gradient."); + } + } + this.extendStart = extendStart; + this.extendEnd = extendEnd; + const fnObj = dict.getRaw("Function"); + const fn = pdfFunctionFactory.create(fnObj, true); + const NUMBER_OF_SAMPLES = 840; + const step = (t1 - t0) / NUMBER_OF_SAMPLES; + const colorStops = this.colorStops = []; + if (t0 >= t1 || step <= 0) { + info2("Bad shading domain."); + return; + } + const color = new Float32Array(cs.numComps), ratio = new Float32Array(1); + let iBase = 0; + ratio[0] = t0; + fn(ratio, 0, color, 0); + const rgbBuffer = new Uint8ClampedArray(3); + cs.getRgb(color, 0, rgbBuffer); + let [rBase, gBase, bBase] = rgbBuffer; + colorStops.push([0, Util2.makeHexColor(rBase, gBase, bBase)]); + let iPrev = 1; + ratio[0] = t0 + step; + fn(ratio, 0, color, 0); + cs.getRgb(color, 0, rgbBuffer); + let [rPrev, gPrev, bPrev] = rgbBuffer; + let maxSlopeR = rPrev - rBase + 1; + let maxSlopeG = gPrev - gBase + 1; + let maxSlopeB = bPrev - bBase + 1; + let minSlopeR = rPrev - rBase - 1; + let minSlopeG = gPrev - gBase - 1; + let minSlopeB = bPrev - bBase - 1; + for (let i = 2; i < NUMBER_OF_SAMPLES; i++) { + ratio[0] = t0 + i * step; + fn(ratio, 0, color, 0); + cs.getRgb(color, 0, rgbBuffer); + const [r, g, b2] = rgbBuffer; + const run = i - iBase; + maxSlopeR = Math.min(maxSlopeR, (r - rBase + 1) / run); + maxSlopeG = Math.min(maxSlopeG, (g - gBase + 1) / run); + maxSlopeB = Math.min(maxSlopeB, (b2 - bBase + 1) / run); + minSlopeR = Math.max(minSlopeR, (r - rBase - 1) / run); + minSlopeG = Math.max(minSlopeG, (g - gBase - 1) / run); + minSlopeB = Math.max(minSlopeB, (b2 - bBase - 1) / run); + const slopesExist = minSlopeR <= maxSlopeR && minSlopeG <= maxSlopeG && minSlopeB <= maxSlopeB; + if (!slopesExist) { + const cssColor = Util2.makeHexColor(rPrev, gPrev, bPrev); + colorStops.push([iPrev / NUMBER_OF_SAMPLES, cssColor]); + maxSlopeR = r - rPrev + 1; + maxSlopeG = g - gPrev + 1; + maxSlopeB = b2 - bPrev + 1; + minSlopeR = r - rPrev - 1; + minSlopeG = g - gPrev - 1; + minSlopeB = b2 - bPrev - 1; + iBase = iPrev; + rBase = rPrev; + gBase = gPrev; + bBase = bPrev; + } + iPrev = i; + rPrev = r; + gPrev = g; + bPrev = b2; + } + colorStops.push([1, Util2.makeHexColor(rPrev, gPrev, bPrev)]); + let background = "transparent"; + if (dict.has("Background")) { + background = cs.getRgbHex(dict.get("Background"), 0); + } + if (!extendStart) { + colorStops.unshift([0, background]); + colorStops[1][0] += BaseShading.SMALL_NUMBER; + } + if (!extendEnd) { + colorStops.at(-1)[0] -= BaseShading.SMALL_NUMBER; + colorStops.push([1, background]); + } + this.colorStops = colorStops; + } + getIR() { + const { + coordsArr, + shadingType + } = this; + let type, p0, p1, r0, r1; + if (shadingType === ShadingType.AXIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[2], coordsArr[3]]; + r0 = null; + r1 = null; + type = "axial"; + } else if (shadingType === ShadingType.RADIAL) { + p0 = [coordsArr[0], coordsArr[1]]; + p1 = [coordsArr[3], coordsArr[4]]; + r0 = coordsArr[2]; + r1 = coordsArr[5]; + type = "radial"; + } else { + unreachable2(`getPattern type unknown: ${shadingType}`); + } + return ["RadialAxial", type, this.bbox, this.colorStops, p0, p1, r0, r1]; + } + }; + MeshStreamReader = class { + constructor(stream, context2) { + this.stream = stream; + this.context = context2; + this.buffer = 0; + this.bufferLength = 0; + const numComps = context2.numComps; + this.tmpCompsBuf = new Float32Array(numComps); + const csNumComps = context2.colorSpace.numComps; + this.tmpCsCompsBuf = context2.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf; + } + get hasData() { + if (this.stream.end) { + return this.stream.pos < this.stream.end; + } + if (this.bufferLength > 0) { + return true; + } + const nextByte = this.stream.getByte(); + if (nextByte < 0) { + return false; + } + this.buffer = nextByte; + this.bufferLength = 8; + return true; + } + readBits(n) { + const { + stream + } = this; + let { + buffer: buffer2, + bufferLength + } = this; + if (n === 32) { + if (bufferLength === 0) { + return stream.getInt32() >>> 0; + } + buffer2 = buffer2 << 24 | stream.getByte() << 16 | stream.getByte() << 8 | stream.getByte(); + const nextByte = stream.getByte(); + this.buffer = nextByte & (1 << bufferLength) - 1; + return (buffer2 << 8 - bufferLength | (nextByte & 255) >> bufferLength) >>> 0; + } + if (n === 8 && bufferLength === 0) { + return stream.getByte(); + } + while (bufferLength < n) { + buffer2 = buffer2 << 8 | stream.getByte(); + bufferLength += 8; + } + bufferLength -= n; + this.bufferLength = bufferLength; + this.buffer = buffer2 & (1 << bufferLength) - 1; + return buffer2 >> bufferLength; + } + align() { + this.buffer = 0; + this.bufferLength = 0; + } + readFlag() { + return this.readBits(this.context.bitsPerFlag); + } + readCoordinate() { + const { + bitsPerCoordinate, + decode: decode4 + } = this.context; + const xi = this.readBits(bitsPerCoordinate); + const yi = this.readBits(bitsPerCoordinate); + const scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 23283064365386963e-26; + return [xi * scale * (decode4[1] - decode4[0]) + decode4[0], yi * scale * (decode4[3] - decode4[2]) + decode4[2]]; + } + readComponents() { + const { + bitsPerComponent, + colorFn, + colorSpace, + decode: decode4, + numComps + } = this.context; + const scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 23283064365386963e-26; + const components = this.tmpCompsBuf; + for (let i = 0, j = 4; i < numComps; i++, j += 2) { + const ci = this.readBits(bitsPerComponent); + components[i] = ci * scale * (decode4[j + 1] - decode4[j]) + decode4[j]; + } + const color = this.tmpCsCompsBuf; + colorFn?.(components, 0, color, 0); + return colorSpace.getRgb(color, 0); + } + }; + bCache = /* @__PURE__ */ Object.create(null); + MeshShading = class _MeshShading extends BaseShading { + static MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3; + static MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20; + static TRIANGLE_DENSITY = 20; + constructor(stream, xref, resources, pdfFunctionFactory, globalColorSpaceCache, localColorSpaceCache) { + super(); + if (!(stream instanceof BaseStream)) { + throw new FormatError3("Mesh data is not a stream"); + } + const dict = stream.dict; + this.shadingType = dict.get("ShadingType"); + this.bbox = lookupNormalRect(dict.getArray("BBox"), null); + const cs = ColorSpaceUtils.parse({ + cs: dict.getRaw("CS") || dict.getRaw("ColorSpace"), + xref, + resources, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.background = dict.has("Background") ? cs.getRgb(dict.get("Background"), 0) : null; + const fnObj = dict.getRaw("Function"); + const fn = fnObj ? pdfFunctionFactory.create(fnObj, true) : null; + this.coords = []; + this.colors = []; + this.figures = []; + const decodeContext = { + bitsPerCoordinate: dict.get("BitsPerCoordinate"), + bitsPerComponent: dict.get("BitsPerComponent"), + bitsPerFlag: dict.get("BitsPerFlag"), + decode: dict.getArray("Decode"), + colorFn: fn, + colorSpace: cs, + numComps: fn ? 1 : cs.numComps + }; + const reader = new MeshStreamReader(stream, decodeContext); + let patchMesh = false; + switch (this.shadingType) { + case ShadingType.FREE_FORM_MESH: + this._decodeType4Shading(reader); + break; + case ShadingType.LATTICE_FORM_MESH: + const verticesPerRow = dict.get("VerticesPerRow") | 0; + if (verticesPerRow < 2) { + throw new FormatError3("Invalid VerticesPerRow"); + } + this._decodeType5Shading(reader, verticesPerRow); + break; + case ShadingType.COONS_PATCH_MESH: + this._decodeType6Shading(reader); + patchMesh = true; + break; + case ShadingType.TENSOR_PATCH_MESH: + this._decodeType7Shading(reader); + patchMesh = true; + break; + default: + unreachable2("Unsupported mesh type."); + break; + } + if (patchMesh) { + this._updateBounds(); + for (let i = 0, ii = this.figures.length; i < ii; i++) { + this._buildFigureFromPatch(i); + } + } + this._updateBounds(); + this._packData(); + } + _decodeType4Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const operators2 = []; + const ps = []; + let verticesLeft = 0; + while (reader.hasData) { + const f = reader.readFlag(); + const coord = reader.readCoordinate(); + const color = reader.readComponents(); + if (verticesLeft === 0) { + if (!(0 <= f && f <= 2)) { + throw new FormatError3("Unknown type4 flag"); + } + switch (f) { + case 0: + verticesLeft = 3; + break; + case 1: + ps.push(ps.at(-2), ps.at(-1)); + verticesLeft = 1; + break; + case 2: + ps.push(ps.at(-3), ps.at(-1)); + verticesLeft = 1; + break; + } + operators2.push(f); + } + ps.push(coords.length); + coords.push(coord); + colors.push(color); + verticesLeft--; + reader.align(); + } + this.figures.push({ + type: "triangles", + coords: new Int32Array(ps), + colors: new Int32Array(ps) + }); + } + _decodeType5Shading(reader, verticesPerRow) { + const coords = this.coords; + const colors = this.colors; + const ps = []; + while (reader.hasData) { + const coord = reader.readCoordinate(); + const color = reader.readComponents(); + ps.push(coords.length); + coords.push(coord); + colors.push(color); + } + this.figures.push({ + type: "lattice", + coords: new Int32Array(ps), + colors: new Int32Array(ps), + verticesPerRow + }); + } + _decodeType6Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const ps = new Int32Array(16); + const cs = new Int32Array(4); + while (reader.hasData) { + const f = reader.readFlag(); + if (!(0 <= f && f <= 3)) { + throw new FormatError3("Unknown type6 flag"); + } + const pi = coords.length; + for (let i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + const ci = colors.length; + for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + let tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + ps[5] = coords.length; + coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]); + ps[6] = coords.length; + coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]); + ps[9] = coords.length; + coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]); + ps[10] = coords.length; + coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]); + this.figures.push({ + type: "patch", + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + _decodeType7Shading(reader) { + const coords = this.coords; + const colors = this.colors; + const ps = new Int32Array(16); + const cs = new Int32Array(4); + while (reader.hasData) { + const f = reader.readFlag(); + if (!(0 <= f && f <= 3)) { + throw new FormatError3("Unknown type7 flag"); + } + const pi = coords.length; + for (let i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) { + coords.push(reader.readCoordinate()); + } + const ci = colors.length; + for (let i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) { + colors.push(reader.readComponents()); + } + let tmp1, tmp2, tmp3, tmp4; + switch (f) { + case 0: + ps[12] = pi + 3; + ps[13] = pi + 4; + ps[14] = pi + 5; + ps[15] = pi + 6; + ps[8] = pi + 2; + ps[9] = pi + 13; + ps[10] = pi + 14; + ps[11] = pi + 7; + ps[4] = pi + 1; + ps[5] = pi + 12; + ps[6] = pi + 15; + ps[7] = pi + 8; + ps[0] = pi; + ps[1] = pi + 11; + ps[2] = pi + 10; + ps[3] = pi + 9; + cs[2] = ci + 1; + cs[3] = ci + 2; + cs[0] = ci; + cs[1] = ci + 3; + break; + case 1: + tmp1 = ps[12]; + tmp2 = ps[13]; + tmp3 = ps[14]; + tmp4 = ps[15]; + ps[12] = tmp4; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = tmp3; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[2]; + tmp2 = cs[3]; + cs[2] = tmp2; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 2: + tmp1 = ps[15]; + tmp2 = ps[11]; + ps[12] = ps[3]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[7]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = tmp2; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = tmp1; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + tmp1 = cs[3]; + cs[2] = cs[1]; + cs[3] = ci; + cs[0] = tmp1; + cs[1] = ci + 1; + break; + case 3: + ps[12] = ps[0]; + ps[13] = pi + 0; + ps[14] = pi + 1; + ps[15] = pi + 2; + ps[8] = ps[1]; + ps[9] = pi + 9; + ps[10] = pi + 10; + ps[11] = pi + 3; + ps[4] = ps[2]; + ps[5] = pi + 8; + ps[6] = pi + 11; + ps[7] = pi + 4; + ps[0] = ps[3]; + ps[1] = pi + 7; + ps[2] = pi + 6; + ps[3] = pi + 5; + cs[2] = cs[0]; + cs[3] = ci; + cs[0] = cs[1]; + cs[1] = ci + 1; + break; + } + this.figures.push({ + type: "patch", + coords: new Int32Array(ps), + colors: new Int32Array(cs) + }); + } + } + _buildFigureFromPatch(index2) { + const figure = this.figures[index2]; + assert3(figure.type === "patch", "Unexpected patch mesh figure"); + const coords = this.coords, colors = this.colors; + const pi = figure.coords; + const ci = figure.colors; + const figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + const figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + const figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]); + const figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]); + let splitXBy = Math.ceil((figureMaxX - figureMinX) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[2] - this.bounds[0])); + splitXBy = MathClamp2(splitXBy, _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT); + let splitYBy = Math.ceil((figureMaxY - figureMinY) * _MeshShading.TRIANGLE_DENSITY / (this.bounds[3] - this.bounds[1])); + splitYBy = MathClamp2(splitYBy, _MeshShading.MIN_SPLIT_PATCH_CHUNKS_AMOUNT, _MeshShading.MAX_SPLIT_PATCH_CHUNKS_AMOUNT); + const verticesPerRow = splitXBy + 1; + const figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow); + const figureColors = new Int32Array((splitYBy + 1) * verticesPerRow); + let k = 0; + const cl = new Uint8Array(3), cr = new Uint8Array(3); + const c0 = colors[ci[0]], c1 = colors[ci[1]], c2 = colors[ci[2]], c3 = colors[ci[3]]; + const bRow = getB(splitYBy), bCol = getB(splitXBy); + for (let row = 0; row <= splitYBy; row++) { + cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0; + cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0; + cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0; + cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0; + cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0; + cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0; + for (let col = 0; col <= splitXBy; col++, k++) { + if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) { + continue; + } + let x = 0, y = 0; + let q = 0; + for (let i = 0; i <= 3; i++) { + for (let j = 0; j <= 3; j++, q++) { + const m = bRow[row][i] * bCol[col][j]; + x += coords[pi[q]][0] * m; + y += coords[pi[q]][1] * m; + } + } + figureCoords[k] = coords.length; + coords.push([x, y]); + figureColors[k] = colors.length; + const newColor = new Uint8Array(3); + newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0; + newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0; + newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0; + colors.push(newColor); + } + } + figureCoords[0] = pi[0]; + figureColors[0] = ci[0]; + figureCoords[splitXBy] = pi[3]; + figureColors[splitXBy] = ci[1]; + figureCoords[verticesPerRow * splitYBy] = pi[12]; + figureColors[verticesPerRow * splitYBy] = ci[2]; + figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15]; + figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3]; + this.figures[index2] = { + type: "lattice", + coords: figureCoords, + colors: figureColors, + verticesPerRow + }; + } + _updateBounds() { + let minX = this.coords[0][0], minY = this.coords[0][1], maxX = minX, maxY = minY; + for (let i = 1, ii = this.coords.length; i < ii; i++) { + const x = this.coords[i][0], y = this.coords[i][1]; + minX = minX > x ? x : minX; + minY = minY > y ? y : minY; + maxX = maxX < x ? x : maxX; + maxY = maxY < y ? y : maxY; + } + this.bounds = [minX, minY, maxX, maxY]; + } + _packData() { + let i, ii, j, jj; + const coords = this.coords; + const coordsPacked = new Float32Array(coords.length * 2); + for (i = 0, j = 0, ii = coords.length; i < ii; i++) { + const xy = coords[i]; + coordsPacked[j++] = xy[0]; + coordsPacked[j++] = xy[1]; + } + this.coords = coordsPacked; + const colors = this.colors; + const colorsPacked = new Uint8Array(colors.length * 3); + for (i = 0, j = 0, ii = colors.length; i < ii; i++) { + const c = colors[i]; + colorsPacked[j++] = c[0]; + colorsPacked[j++] = c[1]; + colorsPacked[j++] = c[2]; + } + this.colors = colorsPacked; + const figures = this.figures; + for (i = 0, ii = figures.length; i < ii; i++) { + const figure = figures[i], ps = figure.coords, cs = figure.colors; + for (j = 0, jj = ps.length; j < jj; j++) { + ps[j] *= 2; + cs[j] *= 3; + } + } + } + getIR() { + const { + bounds + } = this; + if (bounds[2] - bounds[0] === 0 || bounds[3] - bounds[1] === 0) { + throw new FormatError3(`Invalid MeshShading bounds: [${bounds}].`); + } + return ["Mesh", this.shadingType, this.coords, this.colors, this.figures, bounds, this.bbox, this.background]; + } + }; + DummyShading = class extends BaseShading { + getIR() { + return ["Dummy"]; + } + }; + CalibriBoldFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.54657, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.73293, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.9121, 0.86943, 0.79795, 0.88198, 0.77958, 0.70864, 0.81055, 0.90399, 0.88653, 0.96017, 0.82577, 0.77892, 0.78257, 0.97507, 1.54657, 0.97507, 0.85284, 0.89552, 0.90176, 0.88762, 0.8785, 0.75241, 0.8785, 0.90518, 0.95015, 0.77618, 0.8785, 0.88401, 0.91916, 0.86304, 0.88401, 0.91488, 0.8785, 0.8801, 0.8785, 0.8785, 0.91343, 0.7173, 1.04106, 0.8785, 0.85075, 0.95794, 0.82616, 0.85162, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.12401, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.73293, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.9121, 0.86943, 0.86943, 0.86943, 0.86943, 0.86943, 0.85284, 0.87508, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.88762, 0.8715, 0.75241, 0.90518, 0.90518, 0.90518, 0.90518, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.8785, 0.8801, 0.8801, 0.8801, 0.8801, 0.8801, 0.90747, 0.89049, 0.8785, 0.8785, 0.8785, 0.8785, 0.85162, 0.8785, 0.85162, 0.83908, 0.88762, 0.83908, 0.88762, 0.83908, 0.88762, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.73293, 0.75241, 0.87289, 0.83016, 0.88506, 0.93125, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.73133, 0.90518, 0.81921, 0.77618, 0.81921, 0.77618, 0.81921, 0.77618, 1, 1, 0.87356, 0.8785, 0.91075, 0.89608, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76229, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.79468, 0.91926, 0.88175, 0.70823, 0.94903, 0.9121, 0.8785, 1, 1, 0.9121, 0.8785, 0.87802, 0.88656, 0.8785, 0.86943, 0.8801, 0.86943, 0.8801, 0.86943, 0.8801, 0.87402, 0.89291, 0.77958, 0.91343, 1, 1, 0.77958, 0.91343, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 0.70864, 0.7173, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.90399, 0.8785, 0.96017, 0.95794, 0.77892, 0.85162, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.88762, 0.77539, 0.8715, 0.87508, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70674, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.06303, 0.83908, 0.80352, 0.57184, 0.6965, 0.56289, 0.82001, 0.56029, 0.81235, 1.02988, 0.83908, 0.7762, 0.68156, 0.80367, 0.73133, 0.78257, 0.87356, 0.86943, 0.95958, 0.75727, 0.89019, 1.04924, 0.9121, 0.7648, 0.86943, 0.87356, 0.79795, 0.78275, 0.81055, 0.77892, 0.9762, 0.82577, 0.99819, 0.84896, 0.95958, 0.77892, 0.96108, 1.01407, 0.89049, 1.02988, 0.94211, 0.96108, 0.8936, 0.84021, 0.87842, 0.96399, 0.79109, 0.89049, 1.00813, 1.02988, 0.86077, 0.87445, 0.92099, 0.84723, 0.86513, 0.8801, 0.75638, 0.85714, 0.78216, 0.79586, 0.87965, 0.94211, 0.97747, 0.78287, 0.97926, 0.84971, 1.02988, 0.94211, 0.8801, 0.94211, 0.84971, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90264, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90518, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90548, 1, 1, 1, 1, 1, 1, 0.96017, 0.95794, 0.96017, 0.95794, 0.96017, 0.95794, 0.77892, 0.85162, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.92794, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71143, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.93835, 0.83406, 0.91133, 0.84107, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90527, 1.81055, 0.90527, 1.81055, 1.31006, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + CalibriBoldMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 + }; + CalibriBoldItalicFactors = [1.3877, 1, 1, 1, 0.97801, 0.92482, 0.89552, 0.91133, 0.81988, 0.97566, 0.98152, 0.93548, 0.93548, 1.2798, 0.85284, 0.92794, 1, 0.96134, 1.56239, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.82845, 0.82845, 0.85284, 0.85284, 0.85284, 0.75859, 0.92138, 0.83908, 0.7762, 0.71805, 0.87289, 0.73133, 0.7514, 0.81921, 0.87356, 0.95958, 0.59526, 0.75727, 0.69225, 1.04924, 0.90872, 0.85938, 0.79795, 0.87068, 0.77958, 0.69766, 0.81055, 0.90399, 0.88653, 0.96068, 0.82577, 0.77892, 0.78257, 0.97507, 1.529, 0.97507, 0.85284, 0.89552, 0.90176, 0.94908, 0.86411, 0.74012, 0.86411, 0.88323, 0.95015, 0.86411, 0.86331, 0.88401, 0.91916, 0.86304, 0.88401, 0.9039, 0.86331, 0.86331, 0.86411, 0.86411, 0.90464, 0.70852, 1.04106, 0.86331, 0.84372, 0.95794, 0.82616, 0.84548, 0.79492, 0.88331, 1.69808, 0.88331, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.7801, 0.89552, 1.24487, 1.13254, 1.19129, 0.96839, 0.85284, 0.68787, 0.70645, 0.85592, 0.90747, 1.01466, 1.0088, 0.90323, 1, 1.07463, 1, 0.91056, 0.75806, 1.19118, 0.96839, 0.78864, 0.82845, 0.84133, 0.75859, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.83908, 0.77539, 0.71805, 0.73133, 0.73133, 0.73133, 0.73133, 0.95958, 0.95958, 0.95958, 0.95958, 0.88506, 0.90872, 0.85938, 0.85938, 0.85938, 0.85938, 0.85938, 0.85284, 0.87068, 0.90399, 0.90399, 0.90399, 0.90399, 0.77892, 0.79795, 0.90807, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.94908, 0.85887, 0.74012, 0.88323, 0.88323, 0.88323, 0.88323, 0.88401, 0.88401, 0.88401, 0.88401, 0.8785, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.86331, 0.90747, 0.89049, 0.86331, 0.86331, 0.86331, 0.86331, 0.84548, 0.86411, 0.84548, 0.83908, 0.94908, 0.83908, 0.94908, 0.83908, 0.94908, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.71805, 0.74012, 0.87289, 0.79538, 0.88506, 0.92726, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.73133, 0.88323, 0.81921, 0.86411, 0.81921, 0.86411, 0.81921, 0.86411, 1, 1, 0.87356, 0.86331, 0.91075, 0.8777, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.95958, 0.88401, 0.76467, 0.90167, 0.59526, 0.91916, 1, 1, 0.86304, 0.69225, 0.88401, 1, 1, 0.70424, 0.77312, 0.91926, 0.88175, 0.70823, 0.94903, 0.90872, 0.86331, 1, 1, 0.90872, 0.86331, 0.86906, 0.88116, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.85938, 0.86331, 0.87402, 0.86549, 0.77958, 0.90464, 1, 1, 0.77958, 0.90464, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 0.69766, 0.70852, 1, 1, 0.81055, 0.75841, 0.81055, 1.06452, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.90399, 0.86331, 0.96068, 0.95794, 0.77892, 0.84548, 0.77892, 0.78257, 0.79492, 0.78257, 0.79492, 0.78257, 0.79492, 0.9297, 0.56892, 0.83908, 0.94908, 0.77539, 0.85887, 0.87068, 0.89049, 1, 1, 0.81055, 1.04106, 1.20528, 1.20528, 1, 1.15543, 0.70088, 0.98387, 0.94721, 1.33431, 1.45894, 0.95161, 1.48387, 0.83908, 0.80352, 0.57118, 0.6965, 0.56347, 0.79179, 0.55853, 0.80346, 1.02988, 0.83908, 0.7762, 0.67174, 0.86036, 0.73133, 0.78257, 0.87356, 0.86441, 0.95958, 0.75727, 0.89019, 1.04924, 0.90872, 0.74889, 0.85938, 0.87891, 0.79795, 0.7957, 0.81055, 0.77892, 0.97447, 0.82577, 0.97466, 0.87179, 0.95958, 0.77892, 0.94252, 0.95612, 0.8753, 1.02988, 0.92733, 0.94252, 0.87411, 0.84021, 0.8728, 0.95612, 0.74081, 0.8753, 1.02189, 1.02988, 0.84814, 0.87445, 0.91822, 0.84723, 0.85668, 0.86331, 0.81344, 0.87581, 0.76422, 0.82046, 0.96057, 0.92733, 0.99375, 0.78022, 0.95452, 0.86015, 1.02988, 0.92733, 0.86331, 0.92733, 0.86015, 0.73133, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90631, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88323, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85174, 1, 1, 1, 1, 1, 1, 0.96068, 0.95794, 0.96068, 0.95794, 0.96068, 0.95794, 0.77892, 0.84548, 1, 1, 0.89552, 0.90527, 1, 0.90363, 0.92794, 0.92794, 0.92794, 0.89807, 0.87012, 0.87012, 0.87012, 0.89552, 0.89552, 1.42259, 0.71094, 1.06152, 1, 1, 1.03372, 1.03372, 0.97171, 1.4956, 2.2807, 0.92972, 0.83406, 0.91133, 0.83326, 0.91133, 1, 1, 1, 0.72021, 1, 1.23108, 0.83489, 0.88525, 0.88525, 0.81499, 0.90616, 1.81055, 0.90527, 1.81055, 1.3107, 1.53711, 0.94434, 1.08696, 1, 0.95018, 0.77192, 0.85284, 0.90747, 1.17534, 0.69825, 0.9716, 1.37077, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.08004, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90727, 0.90727, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + CalibriBoldItalicMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 + }; + CalibriItalicFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39543, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.72346, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89249, 0.84118, 0.77452, 0.85374, 0.75186, 0.67789, 0.79776, 0.88844, 0.85066, 0.94309, 0.77818, 0.7306, 0.76659, 1.10369, 1.38313, 1.10369, 1.06139, 0.89552, 0.8739, 0.9245, 0.9245, 0.83203, 0.9245, 0.85865, 1.09842, 0.9245, 0.9245, 1.03297, 1.07692, 0.90918, 1.03297, 0.94959, 0.9245, 0.92274, 0.9245, 0.9245, 1.02933, 0.77832, 1.20562, 0.9245, 0.8916, 0.98986, 0.86621, 0.89453, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.16359, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.72346, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89249, 0.84118, 0.84118, 0.84118, 0.84118, 0.84118, 0.85284, 0.84557, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.9245, 0.84843, 0.83203, 0.85865, 0.85865, 0.85865, 0.85865, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.9245, 0.92274, 0.92274, 0.92274, 0.92274, 0.92274, 0.90747, 0.86651, 0.9245, 0.9245, 0.9245, 0.9245, 0.89453, 0.9245, 0.89453, 0.8675, 0.9245, 0.8675, 0.9245, 0.8675, 0.9245, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.72346, 0.83203, 0.85193, 0.8875, 0.86477, 0.99034, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.73206, 0.85865, 0.81105, 0.9245, 0.81105, 0.9245, 0.81105, 0.9245, 1, 1, 0.86275, 0.9245, 0.90872, 0.93591, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77896, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.9375, 0.98156, 0.93407, 0.77261, 1.11429, 0.89249, 0.9245, 1, 1, 0.89249, 0.9245, 0.92534, 0.86698, 0.9245, 0.84118, 0.92274, 0.84118, 0.92274, 0.84118, 0.92274, 0.8667, 0.86291, 0.75186, 1.02933, 1, 1, 0.75186, 1.02933, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 0.67789, 0.77832, 1, 1, 0.79776, 0.97655, 0.79776, 1.23023, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.88844, 0.9245, 0.94309, 0.98986, 0.7306, 0.89453, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.9245, 0.76318, 0.84843, 0.84557, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67009, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.8675, 0.90861, 0.6192, 0.7363, 0.64824, 0.82411, 0.56321, 0.85696, 1.23516, 0.8675, 0.81552, 0.7286, 0.84134, 0.73206, 0.76659, 0.86275, 0.84369, 0.90685, 0.77892, 0.85871, 1.02638, 0.89249, 0.75828, 0.84118, 0.85984, 0.77452, 0.76466, 0.79776, 0.7306, 0.90782, 0.77818, 0.903, 0.87291, 0.90685, 0.7306, 0.99058, 1.03667, 0.94635, 1.23516, 0.9849, 0.99058, 0.92393, 0.8916, 0.942, 1.03667, 0.75026, 0.94635, 1.0297, 1.23516, 0.90918, 0.94048, 0.98217, 0.89746, 0.84153, 0.92274, 0.82507, 0.88832, 0.84438, 0.88178, 1.03525, 0.9849, 1.00225, 0.78086, 0.97248, 0.89404, 1.23516, 0.9849, 0.92274, 0.9849, 0.89404, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89693, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.85865, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.90933, 1, 1, 1, 1, 1, 1, 0.94309, 0.98986, 0.94309, 0.98986, 0.94309, 0.98986, 0.7306, 0.89453, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.68994, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.97858, 0.82616, 0.91133, 0.83437, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90572, 1.81055, 0.90749, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85284, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + CalibriItalicMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 + }; + CalibriRegularFactors = [1.3877, 1, 1, 1, 1.17223, 1.1293, 0.89552, 0.91133, 0.80395, 1.02269, 1.15601, 0.91056, 0.91056, 1.2798, 0.85284, 0.89807, 1, 0.90861, 1.39016, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.91133, 0.96309, 0.96309, 0.85284, 0.85284, 0.85284, 0.83319, 0.88071, 0.8675, 0.81552, 0.73834, 0.85193, 0.73206, 0.7522, 0.81105, 0.86275, 0.90685, 0.6377, 0.77892, 0.75593, 1.02638, 0.89385, 0.85122, 0.77452, 0.86503, 0.75186, 0.68887, 0.79776, 0.88844, 0.85066, 0.94258, 0.77818, 0.7306, 0.76659, 1.10369, 1.39016, 1.10369, 1.06139, 0.89552, 0.8739, 0.86128, 0.94469, 0.8457, 0.94469, 0.89464, 1.09842, 0.84636, 0.94469, 1.03297, 1.07692, 0.90918, 1.03297, 0.95897, 0.94469, 0.9482, 0.94469, 0.94469, 1.04692, 0.78223, 1.20562, 0.94469, 0.90332, 0.98986, 0.86621, 0.90527, 0.79004, 0.94152, 1.77256, 0.94152, 0.85284, 0.97801, 0.89552, 0.91133, 0.89552, 0.91133, 1.91729, 0.89552, 1.17889, 1.13254, 1.08707, 0.92098, 0.85284, 0.68787, 0.71353, 0.84737, 0.90747, 1.0088, 1.0044, 0.87683, 1, 1.09091, 1, 0.92229, 0.739, 1.15642, 0.92098, 0.76288, 0.80504, 0.80972, 0.75859, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.8675, 0.76318, 0.73834, 0.73206, 0.73206, 0.73206, 0.73206, 0.90685, 0.90685, 0.90685, 0.90685, 0.86477, 0.89385, 0.85122, 0.85122, 0.85122, 0.85122, 0.85122, 0.85284, 0.85311, 0.88844, 0.88844, 0.88844, 0.88844, 0.7306, 0.77452, 0.86331, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.86128, 0.8693, 0.8457, 0.89464, 0.89464, 0.89464, 0.89464, 0.82601, 0.82601, 0.82601, 0.82601, 0.94469, 0.94469, 0.9482, 0.9482, 0.9482, 0.9482, 0.9482, 0.90747, 0.86651, 0.94469, 0.94469, 0.94469, 0.94469, 0.90527, 0.94469, 0.90527, 0.8675, 0.86128, 0.8675, 0.86128, 0.8675, 0.86128, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.73834, 0.8457, 0.85193, 0.92454, 0.86477, 0.9921, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.73206, 0.89464, 0.81105, 0.84636, 0.81105, 0.84636, 0.81105, 0.84636, 1, 1, 0.86275, 0.94469, 0.90872, 0.95786, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 0.82601, 0.90685, 1.03297, 0.90685, 0.82601, 0.77741, 1.05611, 0.6377, 1.07692, 1, 1, 0.90918, 0.75593, 1.03297, 1, 1, 0.76032, 0.90452, 0.98156, 1.11842, 0.77261, 1.11429, 0.89385, 0.94469, 1, 1, 0.89385, 0.94469, 0.95877, 0.86901, 0.94469, 0.85122, 0.9482, 0.85122, 0.9482, 0.85122, 0.9482, 0.8667, 0.90016, 0.75186, 1.04692, 1, 1, 0.75186, 1.04692, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 0.68887, 0.78223, 1, 1, 0.79776, 0.92188, 0.79776, 1.23023, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.88844, 0.94469, 0.94258, 0.98986, 0.7306, 0.90527, 0.7306, 0.76659, 0.79004, 0.76659, 0.79004, 0.76659, 0.79004, 1.09231, 0.54873, 0.8675, 0.86128, 0.76318, 0.8693, 0.85311, 0.86651, 1, 1, 0.79776, 1.20562, 1.18622, 1.18622, 1, 1.1437, 0.67742, 0.96334, 0.93695, 1.35191, 1.40909, 0.95161, 1.48387, 0.86686, 0.90861, 0.62267, 0.74359, 0.65649, 0.85498, 0.56963, 0.88254, 1.23516, 0.8675, 0.81552, 0.75443, 0.84503, 0.73206, 0.76659, 0.86275, 0.85122, 0.90685, 0.77892, 0.85746, 1.02638, 0.89385, 0.75657, 0.85122, 0.86275, 0.77452, 0.74171, 0.79776, 0.7306, 0.95165, 0.77818, 0.89772, 0.88831, 0.90685, 0.7306, 0.98142, 1.02191, 0.96576, 1.23516, 0.99018, 0.98142, 0.9236, 0.89258, 0.94035, 1.02191, 0.78848, 0.96576, 0.9561, 1.23516, 0.90918, 0.92578, 0.95424, 0.89746, 0.83969, 0.9482, 0.80113, 0.89442, 0.85208, 0.86155, 0.98022, 0.99018, 1.00452, 0.81209, 0.99247, 0.89181, 1.23516, 0.99018, 0.9482, 0.99018, 0.89181, 0.73206, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.88844, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89464, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96766, 1, 1, 1, 1, 1, 1, 0.94258, 0.98986, 0.94258, 0.98986, 0.94258, 0.98986, 0.7306, 0.90527, 1, 1, 0.89552, 0.90527, 1, 0.90186, 1.12308, 1.12308, 1.12308, 1.12308, 1.2566, 1.2566, 1.2566, 0.89552, 0.89552, 1.42259, 0.69043, 1.03809, 1, 1, 1.0176, 1.0176, 1.11523, 1.4956, 2.01462, 0.99331, 0.82616, 0.91133, 0.84286, 0.91133, 1, 1, 1, 0.70508, 1, 1.23108, 0.79801, 0.84426, 0.84426, 0.774, 0.90527, 1.81055, 0.90527, 1.81055, 1.28809, 1.55469, 0.94434, 1.07806, 1, 0.97094, 0.7589, 0.85284, 0.90747, 1.19658, 0.69825, 0.97622, 1.33512, 0.90747, 0.90747, 0.85356, 0.90747, 0.90747, 1.44947, 0.85284, 0.8941, 0.8941, 0.70572, 0.8, 0.70572, 0.70572, 0.70572, 0.70572, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.99862, 0.99862, 1, 1, 1, 1, 1, 1.0336, 0.91027, 1, 1, 1, 0.99862, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05859, 1.05859, 1, 1, 1, 1.07185, 0.99413, 0.96334, 1.08065, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + CalibriRegularMetrics = { + lineHeight: 1.2207, + lineGap: 0.2207 + }; + HelveticaBoldFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.03374, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.00042, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.03828, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00034, 0.99977, 1, 0.99997, 1.00026, 1.00078, 1.00036, 0.99973, 1.00013, 1.0006, 0.99977, 0.99977, 0.99988, 0.85148, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 1.00069, 1.00022, 0.99977, 1.00001, 0.99984, 1.00026, 1.00001, 1.00024, 1.00001, 0.9999, 1, 1.0006, 1.00001, 1.00041, 0.99962, 1.00026, 1.0006, 0.99995, 1.00041, 0.99942, 0.99973, 0.99927, 1.00082, 0.99902, 1.00026, 1.00087, 1.0006, 1.00069, 0.99973, 0.99867, 0.99973, 0.9993, 1.00026, 1.00049, 1.00056, 1, 0.99988, 0.99935, 0.99995, 0.99954, 1.00055, 0.99945, 1.00032, 1.0006, 0.99995, 1.00026, 0.99995, 1.00032, 1.00001, 1.00008, 0.99971, 1.00019, 0.9994, 1.00001, 1.0006, 1.00044, 0.99973, 1.00023, 1.00047, 1, 0.99942, 0.99561, 0.99989, 1.00035, 0.99977, 1.00035, 0.99977, 1.00019, 0.99944, 1.00001, 1.00021, 0.99926, 1.00035, 1.00035, 0.99942, 1.00048, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.99989, 1.00057, 1.00001, 0.99936, 1.00052, 1.00012, 0.99996, 1.00043, 1, 1.00035, 0.9994, 0.99976, 1.00035, 0.99973, 1.00052, 1.00041, 1.00119, 1.00037, 0.99973, 1.00002, 0.99986, 1.00041, 1.00041, 0.99902, 0.9996, 1.00034, 0.99999, 1.00026, 0.99999, 1.00026, 0.99973, 1.00052, 0.99973, 1, 0.99973, 1.00041, 1.00075, 0.9994, 1.0003, 0.99999, 1, 1.00041, 0.99955, 1, 0.99915, 0.99973, 0.99973, 1.00026, 1.00119, 0.99955, 0.99973, 1.0006, 0.99911, 1.0006, 1.00026, 0.99972, 1.00026, 0.99902, 1.00041, 0.99973, 0.99999, 1, 1, 1.00038, 1.0005, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 1.00047, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + HelveticaBoldMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + HelveticaBoldItalicFactors = [0.76116, 1, 1, 1.0006, 0.99998, 0.99974, 0.99973, 0.99973, 0.99982, 0.99977, 1.00087, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.00003, 1.00003, 1.00003, 1.00026, 0.9999, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 0.99973, 0.99977, 1.00026, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 0.99998, 1.0006, 0.99998, 1.00003, 0.99973, 0.99998, 0.99973, 1.00026, 0.99973, 1.00026, 0.99973, 0.99998, 1.00026, 1.00026, 1.0006, 1.0006, 0.99973, 1.0006, 0.99982, 1.00026, 1.00026, 1.00026, 1.00026, 0.99959, 0.99973, 0.99998, 1.00026, 0.99973, 1.00022, 0.99973, 0.99973, 1, 0.99959, 1.00077, 0.99959, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.00077, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.99973, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 0.99977, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 1.06409, 1.00026, 1.00026, 1.00026, 1.00026, 1.00026, 0.99973, 1.00026, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 1.0044, 0.99977, 1.00026, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99971, 0.99973, 0.99973, 1.0006, 0.99977, 0.99973, 0.99973, 1.00026, 1.0006, 1.00026, 1.0006, 1.00026, 1.01011, 1.00026, 0.99999, 1.00026, 1.0006, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.9993, 0.9998, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1.00022, 1.00026, 1, 1.00016, 0.99977, 0.99959, 0.99977, 0.99959, 0.99977, 0.99959, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00026, 0.99998, 1.00026, 0.8121, 1.00026, 0.99998, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 0.99977, 1.00026, 1.00016, 1.00022, 1.00001, 0.99973, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 1.0006, 0.99973, 0.99977, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 0.99973, 1.00026, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99977, 1, 1, 1.00026, 0.99969, 0.99972, 0.99981, 0.9998, 1.0006, 0.99977, 0.99977, 1.00022, 0.91155, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 0.99977, 1.00001, 0.99999, 0.99977, 0.99966, 1.00022, 1.00032, 1.00001, 0.99944, 1.00026, 1.00001, 0.99968, 1.00001, 1.00047, 1, 1.0006, 1.00001, 0.99981, 1.00101, 1.00026, 1.0006, 0.99948, 0.99981, 1.00064, 0.99973, 0.99942, 1.00101, 1.00061, 1.00026, 1.00069, 1.0006, 1.00014, 0.99973, 1.01322, 0.99973, 1.00065, 1.00026, 1.00012, 0.99923, 1, 1.00064, 1.00076, 0.99948, 1.00055, 1.00063, 1.00007, 0.99943, 1.0006, 0.99948, 1.00026, 0.99948, 0.99943, 1.00001, 1.00001, 1.00029, 1.00038, 1.00035, 1.00001, 1.0006, 1.0006, 0.99973, 0.99978, 1.00001, 1.00057, 0.99989, 0.99967, 0.99964, 0.99967, 0.99977, 0.99999, 0.99977, 1.00038, 0.99977, 1.00001, 0.99973, 1.00066, 0.99967, 0.99967, 1.00041, 0.99998, 0.99999, 0.99977, 1.00022, 0.99967, 1.00001, 0.99977, 1.00026, 0.99964, 1.00031, 1.00001, 0.99999, 0.99999, 1, 1.00023, 1, 1, 0.99999, 1.00035, 1.00001, 0.99999, 0.99973, 0.99977, 0.99999, 1.00058, 0.99973, 0.99973, 0.99955, 0.9995, 1.00026, 1.00026, 1.00032, 0.99989, 1.00034, 0.99999, 1.00026, 1.00026, 1.00026, 0.99973, 0.45998, 0.99973, 1.00026, 0.99973, 1.00001, 0.99999, 0.99982, 0.99994, 0.99996, 1, 1.00042, 1.00044, 1.00029, 1.00023, 0.99973, 0.99973, 1.00026, 0.99949, 1.00002, 0.99973, 1.0006, 1.0006, 1.0006, 0.99975, 1.00026, 1.00026, 1.00032, 0.98685, 0.99973, 1.00026, 1, 1, 0.99966, 1.00044, 1.00016, 1.00022, 1.00016, 1.00022, 1.00016, 1.00022, 1.00001, 0.99973, 1, 1, 0.99973, 1, 1, 0.99955, 1.0006, 1.0006, 1.0006, 1.0006, 1, 1, 1, 0.99973, 0.99973, 0.99972, 1, 1, 1.00106, 0.99999, 0.99998, 0.99998, 0.99999, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1, 0.99973, 0.99971, 0.99978, 1, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00098, 1, 1, 1, 1.00049, 1, 1, 0.99972, 1, 1.20985, 1.39713, 1.00003, 1.00031, 1.00015, 1, 0.99561, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.99972, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + HelveticaBoldItalicMetrics = { + lineHeight: 1.35, + lineGap: 0.2 + }; + HelveticaItalicFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.0288, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 0.99946, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.06311, 0.99973, 1.00024, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00041, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.89547, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 1.00001, 1, 1.00054, 0.99977, 1.00084, 1.00007, 0.99973, 1.00013, 0.99924, 1.00001, 1.00001, 0.99945, 0.91221, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00001, 0.99999, 0.99977, 0.99933, 1.00022, 1.00054, 1.00001, 1.00065, 1.00026, 1.00001, 1.0001, 1.00001, 1.00052, 1, 1.0006, 1.00001, 0.99945, 0.99897, 0.99968, 0.99924, 1.00036, 0.99945, 0.99949, 1, 1.0006, 0.99897, 0.99918, 0.99968, 0.99911, 0.99924, 1, 0.99962, 1.01487, 1, 1.0005, 0.99973, 1.00012, 1.00043, 1, 0.99995, 0.99994, 1.00036, 0.99947, 1.00019, 1.00063, 1.00025, 0.99924, 1.00036, 0.99973, 1.00036, 1.00025, 1.00001, 1.00001, 1.00027, 1.0001, 1.00068, 1.00001, 1.0006, 1.0006, 1, 1.00008, 0.99957, 0.99972, 0.9994, 0.99954, 0.99975, 1.00051, 1.00001, 1.00019, 1.00001, 1.0001, 0.99986, 1.00001, 1.00001, 1.00038, 0.99954, 0.99954, 0.9994, 1.00066, 0.99999, 0.99977, 1.00022, 1.00054, 1.00001, 0.99977, 1.00026, 0.99975, 1.0001, 1.00001, 0.99993, 0.9995, 0.99955, 1.00016, 0.99978, 0.99974, 1.00019, 1.00022, 0.99955, 1.00053, 0.99973, 1.00089, 1.00005, 0.99967, 1.00048, 0.99973, 1.00002, 1.00034, 0.99973, 0.99973, 0.99964, 1.00006, 1.00066, 0.99947, 0.99973, 0.98894, 0.99973, 1, 0.44898, 1, 0.99946, 1, 1.00039, 1.00082, 0.99991, 0.99991, 0.99985, 1.00022, 1.00023, 1.00061, 1.00006, 0.99966, 0.99973, 0.99973, 0.99973, 1.00019, 1.0008, 1, 0.99924, 0.99924, 0.99924, 0.99983, 1.00044, 0.99973, 0.99964, 0.98332, 1, 0.99973, 1, 1, 0.99962, 0.99895, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 1.00423, 0.99925, 0.99999, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1.00049, 1, 1.00245, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 1.00003, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 0.99998, 0.99998, 0.99998, 0.99998, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + HelveticaItalicMetrics = { + lineHeight: 1.35, + lineGap: 0.2 + }; + HelveticaRegularFactors = [0.76116, 1, 1, 1.0006, 1.0006, 1.00006, 0.99973, 0.99973, 0.99982, 1.00001, 1.00043, 0.99998, 0.99998, 0.99959, 1.00003, 1.0006, 0.99998, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1, 1.00003, 1.00003, 1.00003, 0.99973, 0.99987, 1.00001, 1.00001, 0.99977, 0.99977, 1.00001, 1.00026, 1.00022, 0.99977, 1.0006, 1, 1.00001, 0.99973, 0.99999, 0.99977, 1.00022, 1.00001, 1.00022, 0.99977, 1.00001, 1.00026, 0.99977, 1.00001, 1.00016, 1.00001, 1.00001, 1.00026, 1.0006, 1.0006, 1.0006, 0.99949, 0.99973, 0.99998, 0.99973, 0.99973, 1, 0.99973, 0.99973, 1.0006, 0.99973, 0.99973, 0.99924, 0.99924, 1, 0.99924, 0.99999, 0.99973, 0.99973, 0.99973, 0.99973, 0.99998, 1, 1.0006, 0.99973, 1, 0.99977, 1, 1, 1, 1.00005, 1.0009, 1.00005, 1.00003, 0.99998, 0.99973, 0.99973, 0.99973, 0.99973, 1.0009, 0.99973, 0.99998, 1.00025, 0.99968, 0.99973, 1.00003, 1.00025, 0.60299, 1.00024, 1.06409, 1, 1, 0.99998, 1, 0.9998, 1.0006, 0.99998, 1, 0.99936, 0.99973, 1.00002, 1.00002, 1.00002, 1.00026, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1.00001, 1, 0.99977, 1.00001, 1.00001, 1.00001, 1.00001, 1.0006, 1.0006, 1.0006, 1.0006, 0.99977, 0.99977, 1.00022, 1.00022, 1.00022, 1.00022, 1.00022, 1.00003, 1.00022, 0.99977, 0.99977, 0.99977, 0.99977, 1.00001, 1.00001, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99982, 1, 0.99973, 0.99973, 0.99973, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 0.99973, 1.06409, 1.00026, 0.99973, 0.99973, 0.99973, 0.99973, 1, 0.99973, 1, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1, 0.99977, 1.04596, 0.99977, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00001, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 1.0006, 0.99924, 1.0006, 1.0006, 1.00019, 1.00034, 1, 0.99924, 1.00001, 1, 1, 0.99973, 0.99924, 0.99973, 0.99924, 0.99973, 1.02572, 0.99973, 1.00005, 0.99973, 0.99924, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99999, 0.9998, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1.00022, 0.99973, 1, 1.00016, 0.99977, 0.99998, 0.99977, 0.99998, 0.99977, 0.99998, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00001, 1, 1.00026, 1.0006, 1.00026, 0.84533, 1.00026, 1.0006, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 0.99977, 0.99973, 1.00016, 0.99977, 1.00001, 1, 1.00001, 1.00026, 1, 1.00026, 1, 1.00026, 1, 0.99924, 0.99973, 1.00001, 0.99973, 1, 0.99982, 1.00022, 1.00026, 1.00001, 1, 1.00026, 1.0006, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99998, 0.99928, 1, 0.99977, 1.00013, 1.00055, 0.99947, 0.99945, 0.99941, 0.99924, 1.00001, 1.00001, 1.0004, 0.91621, 1.00001, 1.00026, 0.99977, 1.00022, 1.0006, 1.00001, 1.00005, 0.99999, 0.99977, 1.00015, 1.00022, 0.99977, 1.00001, 0.99973, 1.00026, 1.00001, 1.00019, 1.00001, 0.99946, 1, 1.0006, 1.00001, 0.99978, 1.00045, 0.99973, 0.99924, 1.00023, 0.99978, 0.99966, 1, 1.00065, 1.00045, 1.00019, 0.99973, 0.99973, 0.99924, 1, 1, 0.96499, 1, 1.00055, 0.99973, 1.00008, 1.00027, 1, 0.9997, 0.99995, 1.00023, 0.99933, 1.00019, 1.00015, 1.00031, 0.99924, 1.00023, 0.99973, 1.00023, 1.00031, 1.00001, 0.99928, 1.00029, 1.00092, 1.00035, 1.00001, 1.0006, 1.0006, 1, 0.99988, 0.99975, 1, 1.00082, 0.99561, 0.9996, 1.00035, 1.00001, 0.99962, 1.00001, 1.00092, 0.99964, 1.00001, 0.99963, 0.99999, 1.00035, 1.00035, 1.00082, 0.99962, 0.99999, 0.99977, 1.00022, 1.00035, 1.00001, 0.99977, 1.00026, 0.9996, 0.99967, 1.00001, 1.00034, 1.00074, 1.00054, 1.00053, 1.00063, 0.99971, 0.99962, 1.00035, 0.99975, 0.99977, 0.99973, 1.00043, 0.99953, 1.0007, 0.99915, 0.99973, 1.00008, 0.99892, 1.00073, 1.00073, 1.00114, 0.99915, 1.00073, 0.99955, 0.99973, 1.00092, 0.99973, 1, 0.99998, 1, 1.0003, 1, 1.00043, 1.00001, 0.99969, 1.0003, 1, 1.00035, 1.00001, 0.9995, 1, 1.00092, 0.99973, 0.99973, 0.99973, 1.0007, 0.9995, 1, 0.99924, 1.0006, 0.99924, 0.99972, 1.00062, 0.99973, 1.00114, 1.00073, 1, 0.99955, 1, 1, 1.00047, 0.99968, 1.00016, 0.99977, 1.00016, 0.99977, 1.00016, 0.99977, 1.00001, 1, 1, 1, 0.99973, 1, 1, 0.99955, 0.99924, 0.99924, 0.99924, 0.99924, 0.99998, 0.99998, 0.99998, 0.99973, 0.99973, 0.99972, 1, 1, 1.00267, 0.99999, 0.99998, 0.99998, 1, 0.99998, 1.66475, 1, 0.99973, 0.99973, 1.00023, 0.99973, 0.99971, 0.99925, 1.00023, 1, 0.99991, 0.99984, 1.00002, 1.00002, 1.00002, 1.00002, 1, 1, 1, 1, 1, 1, 1, 0.96329, 1, 1.20985, 1.39713, 1.00003, 0.8254, 1.00015, 1, 1.00035, 1.00027, 1.00031, 1.00031, 0.99915, 1.00031, 1.00031, 0.99999, 1.00003, 0.99999, 0.99999, 1.41144, 1.6, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.41144, 1.40579, 1.40579, 1.36625, 0.99999, 1, 0.99861, 0.99861, 1, 1.00026, 1.00026, 1.00026, 1.00026, 0.95317, 0.99999, 0.99999, 0.99999, 0.99999, 1.40483, 1, 0.99977, 1.00054, 1, 1, 0.99953, 0.99962, 1.00042, 0.9995, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + HelveticaRegularMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + LiberationSansBoldWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1e3, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 719, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 785, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 385, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1e3, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1e3, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 465, 722, 333, 853, 906, 474, 825, 927, 838, 278, 722, 722, 601, 719, 667, 611, 722, 778, 278, 722, 667, 833, 722, 644, 778, 722, 667, 600, 611, 667, 821, 667, 809, 802, 278, 667, 615, 451, 611, 278, 582, 615, 610, 556, 606, 475, 460, 611, 541, 278, 558, 556, 612, 556, 445, 611, 766, 619, 520, 684, 446, 582, 715, 576, 753, 845, 278, 582, 611, 582, 845, 667, 669, 885, 567, 711, 667, 278, 276, 556, 1094, 1062, 875, 610, 722, 622, 719, 722, 719, 722, 567, 712, 667, 904, 626, 719, 719, 610, 702, 833, 722, 778, 719, 667, 722, 611, 622, 854, 667, 730, 703, 1005, 1019, 870, 979, 719, 711, 1031, 719, 556, 618, 615, 417, 635, 556, 709, 497, 615, 615, 500, 635, 740, 604, 611, 604, 611, 556, 490, 556, 875, 556, 615, 581, 833, 844, 729, 854, 615, 552, 854, 583, 556, 556, 611, 417, 552, 556, 278, 281, 278, 969, 906, 611, 500, 615, 556, 604, 778, 611, 487, 447, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1e3, 1e3, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1e3, 1e3, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1094, 556, 885, 489, 1115, 1e3, 768, 600, 834, 834, 834, 834, 1e3, 500, 1e3, 500, 1e3, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1e3, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; + LiberationSansBoldMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; + LiberationSansBoldItalicWidths = [365, 0, 333, 278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584, 333, 556, 556, 556, 556, 280, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 556, 278, 333, 333, 365, 556, 834, 834, 834, 611, 722, 722, 722, 722, 722, 722, 1e3, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 556, 556, 556, 556, 556, 278, 278, 278, 278, 611, 611, 611, 611, 611, 611, 611, 549, 611, 611, 611, 611, 611, 556, 611, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 740, 722, 611, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 611, 778, 611, 778, 611, 778, 611, 722, 611, 722, 611, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 782, 556, 556, 278, 722, 556, 556, 611, 278, 611, 278, 611, 396, 611, 479, 611, 278, 722, 611, 722, 611, 722, 611, 708, 723, 611, 778, 611, 778, 611, 778, 611, 1e3, 944, 722, 389, 722, 389, 722, 389, 667, 556, 667, 556, 667, 556, 667, 556, 611, 333, 611, 479, 611, 333, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 722, 611, 944, 778, 667, 556, 667, 611, 500, 611, 500, 611, 500, 278, 556, 722, 556, 1e3, 889, 778, 611, 667, 556, 611, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 722, 333, 854, 906, 473, 844, 930, 847, 278, 722, 722, 610, 671, 667, 611, 722, 778, 278, 722, 667, 833, 722, 657, 778, 718, 667, 590, 611, 667, 822, 667, 829, 781, 278, 667, 620, 479, 611, 278, 591, 620, 621, 556, 610, 479, 492, 611, 558, 278, 566, 556, 603, 556, 450, 611, 712, 605, 532, 664, 409, 591, 704, 578, 773, 834, 278, 591, 611, 591, 834, 667, 667, 886, 614, 719, 667, 278, 278, 556, 1094, 1042, 854, 622, 719, 677, 719, 722, 708, 722, 614, 722, 667, 927, 643, 719, 719, 615, 687, 833, 722, 778, 719, 667, 722, 611, 677, 781, 667, 729, 708, 979, 989, 854, 1e3, 708, 719, 1042, 729, 556, 619, 604, 534, 618, 556, 736, 510, 611, 611, 507, 622, 740, 604, 611, 611, 611, 556, 889, 556, 885, 556, 646, 583, 889, 935, 707, 854, 594, 552, 865, 589, 556, 556, 611, 469, 563, 556, 278, 278, 278, 969, 906, 611, 507, 619, 556, 611, 778, 611, 575, 467, 944, 778, 944, 778, 944, 778, 667, 556, 333, 333, 556, 1e3, 1e3, 552, 278, 278, 278, 278, 500, 500, 500, 556, 556, 350, 1e3, 1e3, 240, 479, 333, 333, 604, 333, 167, 396, 556, 556, 1104, 556, 885, 516, 1146, 1e3, 768, 600, 834, 834, 834, 834, 999, 500, 1e3, 500, 1e3, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 722, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1e3, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 611, 611, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 333, 333, 333, 333, 333, 333, 333, 333]; + LiberationSansBoldItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; + LiberationSansItalicWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1e3, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 625, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 733, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 281, 556, 400, 556, 222, 722, 556, 722, 556, 722, 556, 615, 723, 556, 778, 556, 778, 556, 778, 556, 1e3, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 354, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1e3, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 789, 846, 389, 794, 865, 775, 222, 667, 667, 570, 671, 667, 611, 722, 778, 278, 667, 667, 833, 722, 648, 778, 725, 667, 600, 611, 667, 837, 667, 831, 761, 278, 667, 570, 439, 555, 222, 550, 570, 571, 500, 556, 439, 463, 555, 542, 222, 500, 492, 548, 500, 447, 556, 670, 573, 486, 603, 374, 550, 652, 546, 728, 779, 222, 550, 556, 550, 779, 667, 667, 843, 544, 708, 667, 278, 278, 500, 1066, 982, 844, 589, 715, 639, 724, 667, 651, 667, 544, 704, 667, 917, 614, 715, 715, 589, 686, 833, 722, 778, 725, 667, 722, 611, 639, 795, 667, 727, 673, 920, 923, 805, 886, 651, 694, 1022, 682, 556, 562, 522, 493, 553, 556, 688, 465, 556, 556, 472, 564, 686, 550, 556, 556, 556, 500, 833, 500, 835, 500, 572, 518, 830, 851, 621, 736, 526, 492, 752, 534, 556, 556, 556, 378, 496, 500, 222, 222, 222, 910, 828, 556, 472, 565, 500, 556, 778, 556, 492, 339, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1e3, 1e3, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1e3, 1e3, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1083, 1e3, 768, 600, 834, 834, 834, 834, 1e3, 500, 998, 500, 1e3, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 584, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1e3, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; + LiberationSansItalicMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; + LiberationSansRegularWidths = [365, 0, 333, 278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584, 333, 556, 556, 556, 556, 260, 556, 333, 737, 370, 556, 584, 737, 552, 400, 549, 333, 333, 333, 576, 537, 278, 333, 333, 365, 556, 834, 834, 834, 611, 667, 667, 667, 667, 667, 667, 1e3, 722, 667, 667, 667, 667, 278, 278, 278, 278, 722, 722, 778, 778, 778, 778, 778, 584, 778, 722, 722, 722, 722, 667, 667, 611, 556, 556, 556, 556, 556, 556, 889, 500, 556, 556, 556, 556, 278, 278, 278, 278, 556, 556, 556, 556, 556, 556, 556, 549, 611, 556, 556, 556, 556, 500, 556, 500, 667, 556, 667, 556, 667, 556, 722, 500, 722, 500, 722, 500, 722, 500, 722, 615, 722, 556, 667, 556, 667, 556, 667, 556, 667, 556, 667, 556, 778, 556, 778, 556, 778, 556, 778, 556, 722, 556, 722, 556, 278, 278, 278, 278, 278, 278, 278, 222, 278, 278, 735, 444, 500, 222, 667, 500, 500, 556, 222, 556, 222, 556, 292, 556, 334, 556, 222, 722, 556, 722, 556, 722, 556, 604, 723, 556, 778, 556, 778, 556, 778, 556, 1e3, 944, 722, 333, 722, 333, 722, 333, 667, 500, 667, 500, 667, 500, 667, 500, 611, 278, 611, 375, 611, 278, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 722, 556, 944, 722, 667, 500, 667, 611, 500, 611, 500, 611, 500, 222, 556, 667, 556, 1e3, 889, 778, 611, 667, 500, 611, 278, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 333, 667, 278, 784, 838, 384, 774, 855, 752, 222, 667, 667, 551, 668, 667, 611, 722, 778, 278, 667, 668, 833, 722, 650, 778, 722, 667, 618, 611, 667, 798, 667, 835, 748, 278, 667, 578, 446, 556, 222, 547, 578, 575, 500, 557, 446, 441, 556, 556, 222, 500, 500, 576, 500, 448, 556, 690, 569, 482, 617, 395, 547, 648, 525, 713, 781, 222, 547, 556, 547, 781, 667, 667, 865, 542, 719, 667, 278, 278, 500, 1057, 1010, 854, 583, 722, 635, 719, 667, 656, 667, 542, 677, 667, 923, 604, 719, 719, 583, 656, 833, 722, 778, 719, 667, 722, 611, 635, 760, 667, 740, 667, 917, 938, 792, 885, 656, 719, 1010, 722, 556, 573, 531, 365, 583, 556, 669, 458, 559, 559, 438, 583, 688, 552, 556, 542, 556, 500, 458, 500, 823, 500, 573, 521, 802, 823, 625, 719, 521, 510, 750, 542, 556, 556, 556, 365, 510, 500, 222, 278, 222, 906, 812, 556, 438, 559, 500, 552, 778, 556, 489, 411, 944, 722, 944, 722, 944, 722, 667, 500, 333, 333, 556, 1e3, 1e3, 552, 222, 222, 222, 222, 333, 333, 333, 556, 556, 350, 1e3, 1e3, 188, 354, 333, 333, 500, 333, 167, 365, 556, 556, 1094, 556, 885, 323, 1073, 1e3, 768, 600, 834, 834, 834, 834, 1e3, 500, 1e3, 500, 1e3, 500, 500, 494, 612, 823, 713, 584, 549, 713, 979, 719, 274, 549, 549, 583, 549, 549, 604, 584, 604, 604, 708, 625, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 708, 729, 604, 604, 354, 354, 1e3, 990, 990, 990, 990, 494, 604, 604, 604, 604, 354, 1021, 1052, 917, 750, 750, 531, 656, 594, 510, 500, 750, 750, 500, 500, 333, 333, 333, 333, 333, 333, 333, 333, 222, 222, 294, 294, 324, 324, 316, 328, 398, 285]; + LiberationSansRegularMapping = [-1, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 402, 506, 507, 508, 509, 510, 511, 536, 537, 538, 539, 710, 711, 713, 728, 729, 730, 731, 732, 733, 900, 901, 902, 903, 904, 905, 906, 908, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1138, 1139, 1168, 1169, 7808, 7809, 7810, 7811, 7812, 7813, 7922, 7923, 8208, 8209, 8211, 8212, 8213, 8215, 8216, 8217, 8218, 8219, 8220, 8221, 8222, 8224, 8225, 8226, 8230, 8240, 8242, 8243, 8249, 8250, 8252, 8254, 8260, 8319, 8355, 8356, 8359, 8364, 8453, 8467, 8470, 8482, 8486, 8494, 8539, 8540, 8541, 8542, 8592, 8593, 8594, 8595, 8596, 8597, 8616, 8706, 8710, 8719, 8721, 8722, 8730, 8734, 8735, 8745, 8747, 8776, 8800, 8801, 8804, 8805, 8962, 8976, 8992, 8993, 9472, 9474, 9484, 9488, 9492, 9496, 9500, 9508, 9516, 9524, 9532, 9552, 9553, 9554, 9555, 9556, 9557, 9558, 9559, 9560, 9561, 9562, 9563, 9564, 9565, 9566, 9567, 9568, 9569, 9570, 9571, 9572, 9573, 9574, 9575, 9576, 9577, 9578, 9579, 9580, 9600, 9604, 9608, 9612, 9616, 9617, 9618, 9619, 9632, 9633, 9642, 9643, 9644, 9650, 9658, 9660, 9668, 9674, 9675, 9679, 9688, 9689, 9702, 9786, 9787, 9788, 9792, 9794, 9824, 9827, 9829, 9830, 9834, 9835, 9836, 61441, 61442, 61445, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]; + MyriadProBoldFactors = [1.36898, 1, 1, 0.72706, 0.80479, 0.83734, 0.98894, 0.99793, 0.9897, 0.93884, 0.86209, 0.94292, 0.94292, 1.16661, 1.02058, 0.93582, 0.96694, 0.93582, 1.19137, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.99793, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.72851, 0.78966, 0.90838, 0.83637, 0.82391, 0.96376, 0.80061, 0.86275, 0.8768, 0.95407, 1.0258, 0.73901, 0.85022, 0.83655, 1.0156, 0.95546, 0.92179, 0.87107, 0.92179, 0.82114, 0.8096, 0.89713, 0.94438, 0.95353, 0.94083, 0.91905, 0.90406, 0.9446, 0.94292, 1.18777, 0.94292, 1.02058, 0.89903, 0.90088, 0.94938, 0.97898, 0.81093, 0.97571, 0.94938, 1.024, 0.9577, 0.95933, 0.98621, 1.0474, 0.97455, 0.98981, 0.9672, 0.95933, 0.9446, 0.97898, 0.97407, 0.97646, 0.78036, 1.10208, 0.95442, 0.95298, 0.97579, 0.9332, 0.94039, 0.938, 0.80687, 1.01149, 0.80687, 1.02058, 0.80479, 0.99793, 0.99793, 0.99793, 0.99793, 1.01149, 1.00872, 0.90088, 0.91882, 1.0213, 0.8361, 1.02058, 0.62295, 0.54324, 0.89022, 1.08595, 1, 1, 0.90088, 1, 0.97455, 0.93582, 0.90088, 1, 1.05686, 0.8361, 0.99642, 0.99642, 0.99642, 0.72851, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.90838, 0.868, 0.82391, 0.80061, 0.80061, 0.80061, 0.80061, 1.0258, 1.0258, 1.0258, 1.0258, 0.97484, 0.95546, 0.92179, 0.92179, 0.92179, 0.92179, 0.92179, 1.02058, 0.92179, 0.94438, 0.94438, 0.94438, 0.94438, 0.90406, 0.86958, 0.98225, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.94938, 0.9031, 0.81093, 0.94938, 0.94938, 0.94938, 0.94938, 0.98621, 0.98621, 0.98621, 0.98621, 0.93969, 0.95933, 0.9446, 0.9446, 0.9446, 0.9446, 0.9446, 1.08595, 0.9446, 0.95442, 0.95442, 0.95442, 0.95442, 0.94039, 0.97898, 0.94039, 0.90838, 0.94938, 0.90838, 0.94938, 0.90838, 0.94938, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.82391, 0.81093, 0.96376, 0.84313, 0.97484, 0.97571, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.80061, 0.94938, 0.8768, 0.9577, 0.8768, 0.9577, 0.8768, 0.9577, 1, 1, 0.95407, 0.95933, 0.97069, 0.95933, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 1.0258, 0.98621, 0.887, 1.01591, 0.73901, 1.0474, 1, 1, 0.97455, 0.83655, 0.98981, 1, 1, 0.83655, 0.73977, 0.83655, 0.73903, 0.84638, 1.033, 0.95546, 0.95933, 1, 1, 0.95546, 0.95933, 0.8271, 0.95417, 0.95933, 0.92179, 0.9446, 0.92179, 0.9446, 0.92179, 0.9446, 0.936, 0.91964, 0.82114, 0.97646, 1, 1, 0.82114, 0.97646, 0.8096, 0.78036, 0.8096, 0.78036, 1, 1, 0.8096, 0.78036, 1, 1, 0.89713, 0.77452, 0.89713, 1.10208, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94438, 0.95442, 0.94083, 0.97579, 0.90406, 0.94039, 0.90406, 0.9446, 0.938, 0.9446, 0.938, 0.9446, 0.938, 1, 0.99793, 0.90838, 0.94938, 0.868, 0.9031, 0.92179, 0.9446, 1, 1, 0.89713, 1.10208, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90989, 0.9358, 0.91945, 0.83181, 0.75261, 0.87992, 0.82976, 0.96034, 0.83689, 0.97268, 1.0078, 0.90838, 0.83637, 0.8019, 0.90157, 0.80061, 0.9446, 0.95407, 0.92436, 1.0258, 0.85022, 0.97153, 1.0156, 0.95546, 0.89192, 0.92179, 0.92361, 0.87107, 0.96318, 0.89713, 0.93704, 0.95638, 0.91905, 0.91709, 0.92796, 1.0258, 0.93704, 0.94836, 1.0373, 0.95933, 1.0078, 0.95871, 0.94836, 0.96174, 0.92601, 0.9498, 0.98607, 0.95776, 0.95933, 1.05453, 1.0078, 0.98275, 0.9314, 0.95617, 0.91701, 1.05993, 0.9446, 0.78367, 0.9553, 1, 0.86832, 1.0128, 0.95871, 0.99394, 0.87548, 0.96361, 0.86774, 1.0078, 0.95871, 0.9446, 0.95871, 0.86774, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.94083, 0.97579, 0.94083, 0.97579, 0.94083, 0.97579, 0.90406, 0.94039, 0.96694, 1, 0.89903, 1, 1, 1, 0.93582, 0.93582, 0.93582, 1, 0.908, 0.908, 0.918, 0.94219, 0.94219, 0.96544, 1, 1.285, 1, 1, 0.81079, 0.81079, 1, 1, 0.74854, 1, 1, 1, 1, 0.99793, 1, 1, 1, 0.65, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.17173, 1, 0.80535, 0.76169, 1.02058, 1.0732, 1.05486, 1, 1, 1.30692, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.16161, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + MyriadProBoldMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + MyriadProBoldItalicFactors = [1.36898, 1, 1, 0.66227, 0.80779, 0.81625, 0.97276, 0.97276, 0.97733, 0.92222, 0.83266, 0.94292, 0.94292, 1.16148, 1.02058, 0.93582, 0.96694, 0.93582, 1.17337, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.97276, 0.78076, 0.78076, 1.02058, 1.02058, 1.02058, 0.71541, 0.76813, 0.85576, 0.80591, 0.80729, 0.94299, 0.77512, 0.83655, 0.86523, 0.92222, 0.98621, 0.71743, 0.81698, 0.79726, 0.98558, 0.92222, 0.90637, 0.83809, 0.90637, 0.80729, 0.76463, 0.86275, 0.90699, 0.91605, 0.9154, 0.85308, 0.85458, 0.90531, 0.94292, 1.21296, 0.94292, 1.02058, 0.89903, 1.18616, 0.99613, 0.91677, 0.78216, 0.91677, 0.90083, 0.98796, 0.9135, 0.92168, 0.95381, 0.98981, 0.95298, 0.95381, 0.93459, 0.92168, 0.91513, 0.92004, 0.91677, 0.95077, 0.748, 1.04502, 0.91677, 0.92061, 0.94236, 0.89544, 0.89364, 0.9, 0.80687, 0.8578, 0.80687, 1.02058, 0.80779, 0.97276, 0.97276, 0.97276, 0.97276, 0.8578, 0.99973, 1.18616, 0.91339, 1.08074, 0.82891, 1.02058, 0.55509, 0.71526, 0.89022, 1.08595, 1, 1, 1.18616, 1, 0.96736, 0.93582, 1.18616, 1, 1.04864, 0.82711, 0.99043, 0.99043, 0.99043, 0.71541, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.85576, 0.845, 0.80729, 0.77512, 0.77512, 0.77512, 0.77512, 0.98621, 0.98621, 0.98621, 0.98621, 0.95961, 0.92222, 0.90637, 0.90637, 0.90637, 0.90637, 0.90637, 1.02058, 0.90251, 0.90699, 0.90699, 0.90699, 0.90699, 0.85458, 0.83659, 0.94951, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.99613, 0.85811, 0.78216, 0.90083, 0.90083, 0.90083, 0.90083, 0.95381, 0.95381, 0.95381, 0.95381, 0.9135, 0.92168, 0.91513, 0.91513, 0.91513, 0.91513, 0.91513, 1.08595, 0.91677, 0.91677, 0.91677, 0.91677, 0.91677, 0.89364, 0.92332, 0.89364, 0.85576, 0.99613, 0.85576, 0.99613, 0.85576, 0.99613, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.80729, 0.78216, 0.94299, 0.76783, 0.95961, 0.91677, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.77512, 0.90083, 0.86523, 0.9135, 0.86523, 0.9135, 0.86523, 0.9135, 1, 1, 0.92222, 0.92168, 0.92222, 0.92168, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.98621, 0.95381, 0.86036, 0.97096, 0.71743, 0.98981, 1, 1, 0.95298, 0.79726, 0.95381, 1, 1, 0.79726, 0.6894, 0.79726, 0.74321, 0.81691, 1.0006, 0.92222, 0.92168, 1, 1, 0.92222, 0.92168, 0.79464, 0.92098, 0.92168, 0.90637, 0.91513, 0.90637, 0.91513, 0.90637, 0.91513, 0.909, 0.87514, 0.80729, 0.95077, 1, 1, 0.80729, 0.95077, 0.76463, 0.748, 0.76463, 0.748, 1, 1, 0.76463, 0.748, 1, 1, 0.86275, 0.72651, 0.86275, 1.04502, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.90699, 0.91677, 0.9154, 0.94236, 0.85458, 0.89364, 0.85458, 0.90531, 0.9, 0.90531, 0.9, 0.90531, 0.9, 1, 0.97276, 0.85576, 0.99613, 0.845, 0.85811, 0.90251, 0.91677, 1, 1, 0.86275, 1.04502, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.18616, 1.00899, 1.30628, 0.85576, 0.80178, 0.66862, 0.7927, 0.69323, 0.88127, 0.72459, 0.89711, 0.95381, 0.85576, 0.80591, 0.7805, 0.94729, 0.77512, 0.90531, 0.92222, 0.90637, 0.98621, 0.81698, 0.92655, 0.98558, 0.92222, 0.85359, 0.90637, 0.90976, 0.83809, 0.94523, 0.86275, 0.83509, 0.93157, 0.85308, 0.83392, 0.92346, 0.98621, 0.83509, 0.92886, 0.91324, 0.92168, 0.95381, 0.90646, 0.92886, 0.90557, 0.86847, 0.90276, 0.91324, 0.86842, 0.92168, 0.99531, 0.95381, 0.9224, 0.85408, 0.92699, 0.86847, 1.0051, 0.91513, 0.80487, 0.93481, 1, 0.88159, 1.05214, 0.90646, 0.97355, 0.81539, 0.89398, 0.85923, 0.95381, 0.90646, 0.91513, 0.90646, 0.85923, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9154, 0.94236, 0.9154, 0.94236, 0.9154, 0.94236, 0.85458, 0.89364, 0.96694, 1, 0.89903, 1, 1, 1, 0.91782, 0.91782, 0.91782, 1, 0.896, 0.896, 0.896, 0.9332, 0.9332, 0.95973, 1, 1.26, 1, 1, 0.80479, 0.80178, 1, 1, 0.85633, 1, 1, 1, 1, 0.97276, 1, 1, 1, 0.698, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.14542, 1, 0.79199, 0.78694, 1.02058, 1.03493, 1.05486, 1, 1, 1.23026, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.20006, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + MyriadProBoldItalicMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + MyriadProItalicFactors = [1.36898, 1, 1, 0.65507, 0.84943, 0.85639, 0.88465, 0.88465, 0.86936, 0.88307, 0.86948, 0.85283, 0.85283, 1.06383, 1.02058, 0.75945, 0.9219, 0.75945, 1.17337, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.88465, 0.75945, 0.75945, 1.02058, 1.02058, 1.02058, 0.69046, 0.70926, 0.85158, 0.77812, 0.76852, 0.89591, 0.70466, 0.76125, 0.80094, 0.86822, 0.83864, 0.728, 0.77212, 0.79475, 0.93637, 0.87514, 0.8588, 0.76013, 0.8588, 0.72421, 0.69866, 0.77598, 0.85991, 0.80811, 0.87832, 0.78112, 0.77512, 0.8562, 1.0222, 1.18417, 1.0222, 1.27014, 0.89903, 1.15012, 0.93859, 0.94399, 0.846, 0.94399, 0.81453, 1.0186, 0.94219, 0.96017, 1.03075, 1.02175, 0.912, 1.03075, 0.96998, 0.96017, 0.93859, 0.94399, 0.94399, 0.95493, 0.746, 1.12658, 0.94578, 0.91, 0.979, 0.882, 0.882, 0.83, 0.85034, 0.83537, 0.85034, 1.02058, 0.70869, 0.88465, 0.88465, 0.88465, 0.88465, 0.83537, 0.90083, 1.15012, 0.9161, 0.94565, 0.73541, 1.02058, 0.53609, 0.69353, 0.79519, 1.08595, 1, 1, 1.15012, 1, 0.91974, 0.75945, 1.15012, 1, 0.9446, 0.73361, 0.9005, 0.9005, 0.9005, 0.62864, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.85158, 0.773, 0.76852, 0.70466, 0.70466, 0.70466, 0.70466, 0.83864, 0.83864, 0.83864, 0.83864, 0.90561, 0.87514, 0.8588, 0.8588, 0.8588, 0.8588, 0.8588, 1.02058, 0.85751, 0.85991, 0.85991, 0.85991, 0.85991, 0.77512, 0.76013, 0.88075, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 0.8075, 0.846, 0.81453, 0.81453, 0.81453, 0.81453, 0.82424, 0.82424, 0.82424, 0.82424, 0.9278, 0.96017, 0.93859, 0.93859, 0.93859, 0.93859, 0.93859, 1.08595, 0.8562, 0.94578, 0.94578, 0.94578, 0.94578, 0.882, 0.94578, 0.882, 0.85158, 0.93859, 0.85158, 0.93859, 0.85158, 0.93859, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.76852, 0.846, 0.89591, 0.8544, 0.90561, 0.94399, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.70466, 0.81453, 0.80094, 0.94219, 0.80094, 0.94219, 0.80094, 0.94219, 1, 1, 0.86822, 0.96017, 0.86822, 0.96017, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 0.82424, 0.83864, 1.03075, 0.83864, 0.82424, 0.81402, 1.02738, 0.728, 1.02175, 1, 1, 0.912, 0.79475, 1.03075, 1, 1, 0.79475, 0.83911, 0.79475, 0.66266, 0.80553, 1.06676, 0.87514, 0.96017, 1, 1, 0.87514, 0.96017, 0.86865, 0.87396, 0.96017, 0.8588, 0.93859, 0.8588, 0.93859, 0.8588, 0.93859, 0.867, 0.84759, 0.72421, 0.95493, 1, 1, 0.72421, 0.95493, 0.69866, 0.746, 0.69866, 0.746, 1, 1, 0.69866, 0.746, 1, 1, 0.77598, 0.88417, 0.77598, 1.12658, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.85991, 0.94578, 0.87832, 0.979, 0.77512, 0.882, 0.77512, 0.8562, 0.83, 0.8562, 0.83, 0.8562, 0.83, 1, 0.88465, 0.85158, 0.93859, 0.773, 0.8075, 0.85751, 0.8562, 1, 1, 0.77598, 1.12658, 1.15012, 1.15012, 1.15012, 1.15012, 1.15012, 1.15313, 1.15012, 1.15012, 1.15012, 1.08106, 1.03901, 0.85158, 0.77025, 0.62264, 0.7646, 0.65351, 0.86026, 0.69461, 0.89947, 1.03075, 0.85158, 0.77812, 0.76449, 0.88836, 0.70466, 0.8562, 0.86822, 0.8588, 0.83864, 0.77212, 0.85308, 0.93637, 0.87514, 0.82352, 0.8588, 0.85701, 0.76013, 0.89058, 0.77598, 0.8156, 0.82565, 0.78112, 0.77899, 0.89386, 0.83864, 0.8156, 0.9486, 0.92388, 0.96186, 1.03075, 0.91123, 0.9486, 0.93298, 0.878, 0.93942, 0.92388, 0.84596, 0.96186, 0.95119, 1.03075, 0.922, 0.88787, 0.95829, 0.88, 0.93559, 0.93859, 0.78815, 0.93758, 1, 0.89217, 1.03737, 0.91123, 0.93969, 0.77487, 0.85769, 0.86799, 1.03075, 0.91123, 0.93859, 0.91123, 0.86799, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87832, 0.979, 0.87832, 0.979, 0.87832, 0.979, 0.77512, 0.882, 0.9219, 1, 0.89903, 1, 1, 1, 0.87321, 0.87321, 0.87321, 1, 1.027, 1.027, 1.027, 0.86847, 0.86847, 0.79121, 1, 1.124, 1, 1, 0.73572, 0.73572, 1, 1, 0.85034, 1, 1, 1, 1, 0.88465, 1, 1, 1, 0.669, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04828, 1, 0.74948, 0.75187, 1.02058, 0.98391, 1.02119, 1, 1, 1.06233, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05233, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + MyriadProItalicMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + MyriadProRegularFactors = [1.36898, 1, 1, 0.76305, 0.82784, 0.94935, 0.89364, 0.92241, 0.89073, 0.90706, 0.98472, 0.85283, 0.85283, 1.0664, 1.02058, 0.74505, 0.9219, 0.74505, 1.23456, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.92241, 0.74505, 0.74505, 1.02058, 1.02058, 1.02058, 0.73002, 0.72601, 0.91755, 0.8126, 0.80314, 0.92222, 0.73764, 0.79726, 0.83051, 0.90284, 0.86023, 0.74, 0.8126, 0.84869, 0.96518, 0.91115, 0.8858, 0.79761, 0.8858, 0.74498, 0.73914, 0.81363, 0.89591, 0.83659, 0.89633, 0.85608, 0.8111, 0.90531, 1.0222, 1.22736, 1.0222, 1.27014, 0.89903, 0.90088, 0.86667, 1.0231, 0.896, 1.01411, 0.90083, 1.05099, 1.00512, 0.99793, 1.05326, 1.09377, 0.938, 1.06226, 1.00119, 0.99793, 0.98714, 1.0231, 1.01231, 0.98196, 0.792, 1.19137, 0.99074, 0.962, 1.01915, 0.926, 0.942, 0.856, 0.85034, 0.92006, 0.85034, 1.02058, 0.69067, 0.92241, 0.92241, 0.92241, 0.92241, 0.92006, 0.9332, 0.90088, 0.91882, 0.93484, 0.75339, 1.02058, 0.56866, 0.54324, 0.79519, 1.08595, 1, 1, 0.90088, 1, 0.95325, 0.74505, 0.90088, 1, 0.97198, 0.75339, 0.91009, 0.91009, 0.91009, 0.66466, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.91755, 0.788, 0.80314, 0.73764, 0.73764, 0.73764, 0.73764, 0.86023, 0.86023, 0.86023, 0.86023, 0.92915, 0.91115, 0.8858, 0.8858, 0.8858, 0.8858, 0.8858, 1.02058, 0.8858, 0.89591, 0.89591, 0.89591, 0.89591, 0.8111, 0.79611, 0.89713, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86667, 0.86936, 0.896, 0.90083, 0.90083, 0.90083, 0.90083, 0.84224, 0.84224, 0.84224, 0.84224, 0.97276, 0.99793, 0.98714, 0.98714, 0.98714, 0.98714, 0.98714, 1.08595, 0.89876, 0.99074, 0.99074, 0.99074, 0.99074, 0.942, 1.0231, 0.942, 0.91755, 0.86667, 0.91755, 0.86667, 0.91755, 0.86667, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.80314, 0.896, 0.92222, 0.93372, 0.92915, 1.01411, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.73764, 0.90083, 0.83051, 1.00512, 0.83051, 1.00512, 0.83051, 1.00512, 1, 1, 0.90284, 0.99793, 0.90976, 0.99793, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 0.84224, 0.86023, 1.05326, 0.86023, 0.84224, 0.82873, 1.07469, 0.74, 1.09377, 1, 1, 0.938, 0.84869, 1.06226, 1, 1, 0.84869, 0.83704, 0.84869, 0.81441, 0.85588, 1.08927, 0.91115, 0.99793, 1, 1, 0.91115, 0.99793, 0.91887, 0.90991, 0.99793, 0.8858, 0.98714, 0.8858, 0.98714, 0.8858, 0.98714, 0.894, 0.91434, 0.74498, 0.98196, 1, 1, 0.74498, 0.98196, 0.73914, 0.792, 0.73914, 0.792, 1, 1, 0.73914, 0.792, 1, 1, 0.81363, 0.904, 0.81363, 1.19137, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89591, 0.99074, 0.89633, 1.01915, 0.8111, 0.942, 0.8111, 0.90531, 0.856, 0.90531, 0.856, 0.90531, 0.856, 1, 0.92241, 0.91755, 0.86667, 0.788, 0.86936, 0.8858, 0.89876, 1, 1, 0.81363, 1.19137, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90088, 0.90388, 1.03901, 0.92138, 0.78105, 0.7154, 0.86169, 0.80513, 0.94007, 0.82528, 0.98612, 1.06226, 0.91755, 0.8126, 0.81884, 0.92819, 0.73764, 0.90531, 0.90284, 0.8858, 0.86023, 0.8126, 0.91172, 0.96518, 0.91115, 0.83089, 0.8858, 0.87791, 0.79761, 0.89297, 0.81363, 0.88157, 0.89992, 0.85608, 0.81992, 0.94307, 0.86023, 0.88157, 0.95308, 0.98699, 0.99793, 1.06226, 0.95817, 0.95308, 0.97358, 0.928, 0.98088, 0.98699, 0.92761, 0.99793, 0.96017, 1.06226, 0.986, 0.944, 0.95978, 0.938, 0.96705, 0.98714, 0.80442, 0.98972, 1, 0.89762, 1.04552, 0.95817, 0.99007, 0.87064, 0.91879, 0.88888, 1.06226, 0.95817, 0.98714, 0.95817, 0.88888, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.89633, 1.01915, 0.89633, 1.01915, 0.89633, 1.01915, 0.8111, 0.942, 0.9219, 1, 0.89903, 1, 1, 1, 0.93173, 0.93173, 0.93173, 1, 1.06304, 1.06304, 1.06904, 0.89903, 0.89903, 0.80549, 1, 1.156, 1, 1, 0.76575, 0.76575, 1, 1, 0.72458, 1, 1, 1, 1, 0.92241, 1, 1, 1, 0.619, 1, 1.36145, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.07257, 1, 0.74705, 0.71119, 1.02058, 1.024, 1.02119, 1, 1, 1.1536, 1.08595, 1.08595, 1, 1.08595, 1.08595, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.05638, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + MyriadProRegularMetrics = { + lineHeight: 1.2, + lineGap: 0.2 + }; + SegoeuiBoldFactors = [1.76738, 1, 1, 0.99297, 0.9824, 1.04016, 1.06497, 1.03424, 0.97529, 1.17647, 1.23203, 1.1085, 1.1085, 1.16939, 1.2107, 0.9754, 1.21408, 0.9754, 1.59578, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 1.03424, 0.81378, 0.81378, 1.2107, 1.2107, 1.2107, 0.71703, 0.97847, 0.97363, 0.88776, 0.8641, 1.02096, 0.79795, 0.85132, 0.914, 1.06085, 1.1406, 0.8007, 0.89858, 0.83693, 1.14889, 1.09398, 0.97489, 0.92094, 0.97489, 0.90399, 0.84041, 0.95923, 1.00135, 1, 1.06467, 0.98243, 0.90996, 0.99361, 1.1085, 1.56942, 1.1085, 1.2107, 0.74627, 0.94282, 0.96752, 1.01519, 0.86304, 1.01359, 0.97278, 1.15103, 1.01359, 0.98561, 1.02285, 1.02285, 1.00527, 1.02285, 1.0302, 0.99041, 1.0008, 1.01519, 1.01359, 1.02258, 0.79104, 1.16862, 0.99041, 0.97454, 1.02511, 0.99298, 0.96752, 0.95801, 0.94856, 1.16579, 0.94856, 1.2107, 0.9824, 1.03424, 1.03424, 1, 1.03424, 1.16579, 0.8727, 1.3871, 1.18622, 1.10818, 1.04478, 1.2107, 1.18622, 0.75155, 0.94994, 1.28826, 1.21408, 1.21408, 0.91056, 1, 0.91572, 0.9754, 0.64663, 1.18328, 1.24866, 1.04478, 1.14169, 1.15749, 1.17389, 0.71703, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.93506, 0.8641, 0.79795, 0.79795, 0.79795, 0.79795, 1.1406, 1.1406, 1.1406, 1.1406, 1.02096, 1.09398, 0.97426, 0.97426, 0.97426, 0.97426, 0.97426, 1.2107, 0.97489, 1.00135, 1.00135, 1.00135, 1.00135, 0.90996, 0.92094, 1.02798, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.96752, 0.93136, 0.86304, 0.97278, 0.97278, 0.97278, 0.97278, 1.02285, 1.02285, 1.02285, 1.02285, 0.97122, 0.99041, 1, 1, 1, 1, 1, 1.28826, 1.0008, 0.99041, 0.99041, 0.99041, 0.99041, 0.96752, 1.01519, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.97363, 0.96752, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 0.8641, 0.86304, 1.02096, 1.03057, 1.02096, 1.03517, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.79795, 0.97278, 0.914, 1.01359, 0.914, 1.01359, 0.914, 1.01359, 1, 1, 1.06085, 0.98561, 1.06085, 1.00879, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 1.1406, 1.02285, 0.97138, 1.08692, 0.8007, 1.02285, 1, 1, 1.00527, 0.83693, 1.02285, 1, 1, 0.83693, 0.9455, 0.83693, 0.90418, 0.83693, 1.13005, 1.09398, 0.99041, 1, 1, 1.09398, 0.99041, 0.96692, 1.09251, 0.99041, 0.97489, 1.0008, 0.97489, 1.0008, 0.97489, 1.0008, 0.93994, 0.97931, 0.90399, 1.02258, 1, 1, 0.90399, 1.02258, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 0.84041, 0.79104, 1, 1, 0.95923, 1.07034, 0.95923, 1.16862, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.00135, 0.99041, 1.06467, 1.02511, 0.90996, 0.96752, 0.90996, 0.99361, 0.95801, 0.99361, 0.95801, 0.99361, 0.95801, 1.07733, 1.03424, 0.97363, 0.96752, 0.93506, 0.93136, 0.97489, 1.0008, 1, 1, 0.95923, 1.16862, 1.15103, 1.15103, 1.01173, 1.03959, 0.75953, 0.81378, 0.79912, 1.15103, 1.21994, 0.95161, 0.87815, 1.01149, 0.81525, 0.7676, 0.98167, 1.01134, 1.02546, 0.84097, 1.03089, 1.18102, 0.97363, 0.88776, 0.85134, 0.97826, 0.79795, 0.99361, 1.06085, 0.97489, 1.1406, 0.89858, 1.0388, 1.14889, 1.09398, 0.86039, 0.97489, 1.0595, 0.92094, 0.94793, 0.95923, 0.90996, 0.99346, 0.98243, 1.02112, 0.95493, 1.1406, 0.90996, 1.03574, 1.02597, 1.0008, 1.18102, 1.06628, 1.03574, 1.0192, 1.01932, 1.00886, 0.97531, 1.0106, 1.0008, 1.13189, 1.18102, 1.02277, 0.98683, 1.0016, 0.99561, 1.07237, 1.0008, 0.90434, 0.99921, 0.93803, 0.8965, 1.23085, 1.06628, 1.04983, 0.96268, 1.0499, 0.98439, 1.18102, 1.06628, 1.0008, 1.06628, 0.98439, 0.79795, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09466, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.97278, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.02065, 1, 1, 1, 1, 1, 1, 1.06467, 1.02511, 1.06467, 1.02511, 1.06467, 1.02511, 0.90996, 0.96752, 1, 1.21408, 0.89903, 1, 1, 0.75155, 1.04394, 1.04394, 1.04394, 1.04394, 0.98633, 0.98633, 0.98633, 0.73047, 0.73047, 1.20642, 0.91211, 1.25635, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.12454, 0.93503, 1.03424, 1.19687, 1.03424, 1, 1, 1, 0.771, 1, 1, 1.15749, 1.15749, 1.15749, 1.10948, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.16897, 1, 0.96085, 0.90137, 1.2107, 1.18416, 1.13973, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21172, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18874, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.09193, 1.09193, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + SegoeuiBoldMetrics = { + lineHeight: 1.33008, + lineGap: 0 + }; + SegoeuiBoldItalicFactors = [1.76738, 1, 1, 0.98946, 1.03959, 1.04016, 1.02809, 1.036, 0.97639, 1.10953, 1.23203, 1.11144, 1.11144, 1.16939, 1.21237, 0.9754, 1.21261, 0.9754, 1.59754, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 0.81378, 0.81378, 1.21237, 1.21237, 1.21237, 0.73541, 0.97847, 0.97363, 0.89723, 0.87897, 1.0426, 0.79429, 0.85292, 0.91149, 1.05815, 1.1406, 0.79631, 0.90128, 0.83853, 1.04396, 1.10615, 0.97552, 0.94436, 0.97552, 0.88641, 0.80527, 0.96083, 1.00135, 1, 1.06777, 0.9817, 0.91142, 0.99361, 1.11144, 1.57293, 1.11144, 1.21237, 0.74627, 1.31818, 1.06585, 0.97042, 0.83055, 0.97042, 0.93503, 1.1261, 0.97042, 0.97922, 1.14236, 0.94552, 1.01054, 1.14236, 1.02471, 0.97922, 0.94165, 0.97042, 0.97042, 1.0276, 0.78929, 1.1261, 0.97922, 0.95874, 1.02197, 0.98507, 0.96752, 0.97168, 0.95107, 1.16579, 0.95107, 1.21237, 1.03959, 1.036, 1.036, 1, 1.036, 1.16579, 0.87357, 1.31818, 1.18754, 1.26781, 1.05356, 1.21237, 1.18622, 0.79487, 0.94994, 1.29004, 1.24047, 1.24047, 1.31818, 1, 0.91484, 0.9754, 1.31818, 1.1349, 1.24866, 1.05356, 1.13934, 1.15574, 1.17389, 0.73541, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.97363, 0.94385, 0.87897, 0.79429, 0.79429, 0.79429, 0.79429, 1.1406, 1.1406, 1.1406, 1.1406, 1.0426, 1.10615, 0.97552, 0.97552, 0.97552, 0.97552, 0.97552, 1.21237, 0.97552, 1.00135, 1.00135, 1.00135, 1.00135, 0.91142, 0.94436, 0.98721, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 1.06585, 0.96705, 0.83055, 0.93503, 0.93503, 0.93503, 0.93503, 1.14236, 1.14236, 1.14236, 1.14236, 0.93125, 0.97922, 0.94165, 0.94165, 0.94165, 0.94165, 0.94165, 1.29004, 0.94165, 0.97922, 0.97922, 0.97922, 0.97922, 0.96752, 0.97042, 0.96752, 0.97363, 1.06585, 0.97363, 1.06585, 0.97363, 1.06585, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 0.87897, 0.83055, 1.0426, 1.0033, 1.0426, 0.97042, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.79429, 0.93503, 0.91149, 0.97042, 0.91149, 0.97042, 0.91149, 0.97042, 1, 1, 1.05815, 0.97922, 1.05815, 0.97922, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 1.1406, 1.14236, 0.97441, 1.04302, 0.79631, 1.01582, 1, 1, 1.01054, 0.83853, 1.14236, 1, 1, 0.83853, 1.09125, 0.83853, 0.90418, 0.83853, 1.19508, 1.10615, 0.97922, 1, 1, 1.10615, 0.97922, 1.01034, 1.10466, 0.97922, 0.97552, 0.94165, 0.97552, 0.94165, 0.97552, 0.94165, 0.91602, 0.91981, 0.88641, 1.0276, 1, 1, 0.88641, 1.0276, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 0.80527, 0.78929, 1, 1, 0.96083, 1.05403, 0.95923, 1.16862, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.00135, 0.97922, 1.06777, 1.02197, 0.91142, 0.96752, 0.91142, 0.99361, 0.97168, 0.99361, 0.97168, 0.99361, 0.97168, 1.23199, 1.036, 0.97363, 1.06585, 0.94385, 0.96705, 0.97552, 0.94165, 1, 1, 0.96083, 1.1261, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 1.31818, 0.95161, 1.27126, 1.00811, 0.83284, 0.77702, 0.99137, 0.95253, 1.0347, 0.86142, 1.07205, 1.14236, 0.97363, 0.89723, 0.86869, 1.09818, 0.79429, 0.99361, 1.05815, 0.97552, 1.1406, 0.90128, 1.06662, 1.04396, 1.10615, 0.84918, 0.97552, 1.04694, 0.94436, 0.98015, 0.96083, 0.91142, 1.00356, 0.9817, 1.01945, 0.98999, 1.1406, 0.91142, 1.04961, 0.9898, 1.00639, 1.14236, 1.07514, 1.04961, 0.99607, 1.02897, 1.008, 0.9898, 0.95134, 1.00639, 1.11121, 1.14236, 1.00518, 0.97981, 1.02186, 1, 1.08578, 0.94165, 0.99314, 0.98387, 0.93028, 0.93377, 1.35125, 1.07514, 1.10687, 0.93491, 1.04232, 1.00351, 1.14236, 1.07514, 0.94165, 1.07514, 1.00351, 0.79429, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.09097, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.93503, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.96609, 1, 1, 1, 1, 1, 1, 1.06777, 1.02197, 1.06777, 1.02197, 1.06777, 1.02197, 0.91142, 0.96752, 1, 1.21261, 0.89903, 1, 1, 0.75155, 1.04745, 1.04745, 1.04745, 1.04394, 0.98633, 0.98633, 0.98633, 0.72959, 0.72959, 1.20502, 0.91406, 1.26514, 1.222, 1.02956, 1.03372, 1.03372, 0.96039, 1.24633, 1, 1.09125, 0.93327, 1.03336, 1.16541, 1.036, 1, 1, 1, 0.771, 1, 1, 1.15574, 1.15574, 1.15574, 1.15574, 0.86364, 0.94434, 0.86279, 0.94434, 0.86224, 1, 1, 1.16798, 1, 0.96085, 0.90068, 1.21237, 1.18416, 1.13904, 0.69825, 0.9716, 2.10339, 1.29004, 1.29004, 1.21339, 1.29004, 1.29004, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18775, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.13269, 1.13269, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + SegoeuiBoldItalicMetrics = { + lineHeight: 1.33008, + lineGap: 0 + }; + SegoeuiItalicFactors = [1.76738, 1, 1, 0.98946, 1.14763, 1.05365, 1.06234, 0.96927, 0.92586, 1.15373, 1.18414, 0.91349, 0.91349, 1.07403, 1.17308, 0.78383, 1.20088, 0.78383, 1.42531, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78383, 0.78383, 1.17308, 1.17308, 1.17308, 0.77349, 0.94565, 0.94729, 0.85944, 0.88506, 0.9858, 0.74817, 0.80016, 0.88449, 0.98039, 0.95782, 0.69238, 0.89898, 0.83231, 0.98183, 1.03989, 0.96924, 0.86237, 0.96924, 0.80595, 0.74524, 0.86091, 0.95402, 0.94143, 0.98448, 0.8858, 0.83089, 0.93285, 1.0949, 1.39016, 1.0949, 1.45994, 0.74627, 1.04839, 0.97454, 0.97454, 0.87207, 0.97454, 0.87533, 1.06151, 0.97454, 1.00176, 1.16484, 1.08132, 0.98047, 1.16484, 1.02989, 1.01054, 0.96225, 0.97454, 0.97454, 1.06598, 0.79004, 1.16344, 1.00351, 0.94629, 0.9973, 0.91016, 0.96777, 0.9043, 0.91082, 0.92481, 0.91082, 1.17308, 0.95748, 0.96927, 0.96927, 1, 0.96927, 0.92481, 0.80597, 1.04839, 1.23393, 1.1781, 0.9245, 1.17308, 1.20808, 0.63218, 0.94261, 1.24822, 1.09971, 1.09971, 1.04839, 1, 0.85273, 0.78032, 1.04839, 1.09971, 1.22326, 0.9245, 1.09836, 1.13525, 1.15222, 0.70424, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.94729, 0.85498, 0.88506, 0.74817, 0.74817, 0.74817, 0.74817, 0.95782, 0.95782, 0.95782, 0.95782, 0.9858, 1.03989, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.17308, 0.96924, 0.95402, 0.95402, 0.95402, 0.95402, 0.83089, 0.86237, 0.88409, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.97454, 0.92916, 0.87207, 0.87533, 0.87533, 0.87533, 0.87533, 0.93146, 0.93146, 0.93146, 0.93146, 0.93854, 1.01054, 0.96225, 0.96225, 0.96225, 0.96225, 0.96225, 1.24822, 0.8761, 1.00351, 1.00351, 1.00351, 1.00351, 0.96777, 0.97454, 0.96777, 0.94729, 0.97454, 0.94729, 0.97454, 0.94729, 0.97454, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.88506, 0.87207, 0.9858, 0.95391, 0.9858, 0.97454, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.74817, 0.87533, 0.88449, 0.97454, 0.88449, 0.97454, 0.88449, 0.97454, 1, 1, 0.98039, 1.00176, 0.98039, 1.00176, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 0.93146, 0.95782, 1.16484, 0.95782, 0.93146, 0.84421, 1.12761, 0.69238, 1.08132, 1, 1, 0.98047, 0.83231, 1.16484, 1, 1, 0.84723, 1.04861, 0.84723, 0.78755, 0.83231, 1.23736, 1.03989, 1.01054, 1, 1, 1.03989, 1.01054, 0.9857, 1.03849, 1.01054, 0.96924, 0.96225, 0.96924, 0.96225, 0.96924, 0.96225, 0.92383, 0.90171, 0.80595, 1.06598, 1, 1, 0.80595, 1.06598, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 0.74524, 0.79004, 1, 1, 0.86091, 1.02759, 0.85771, 1.16344, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.95402, 1.00351, 0.98448, 0.9973, 0.83089, 0.96777, 0.83089, 0.93285, 0.9043, 0.93285, 0.9043, 0.93285, 0.9043, 1.31868, 0.96927, 0.94729, 0.97454, 0.85498, 0.92916, 0.96924, 0.8761, 1, 1, 0.86091, 1.16344, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 1.04839, 0.81965, 0.81965, 0.94729, 0.78032, 0.71022, 0.90883, 0.84171, 0.99877, 0.77596, 1.05734, 1.2, 0.94729, 0.85944, 0.82791, 0.9607, 0.74817, 0.93285, 0.98039, 0.96924, 0.95782, 0.89898, 0.98316, 0.98183, 1.03989, 0.78614, 0.96924, 0.97642, 0.86237, 0.86075, 0.86091, 0.83089, 0.90082, 0.8858, 0.97296, 1.01284, 0.95782, 0.83089, 1.0976, 1.04, 1.03342, 1.2, 1.0675, 1.0976, 0.98205, 1.03809, 1.05097, 1.04, 0.95364, 1.03342, 1.05401, 1.2, 1.02148, 1.0119, 1.04724, 1.0127, 1.02732, 0.96225, 0.8965, 0.97783, 0.93574, 0.94818, 1.30679, 1.0675, 1.11826, 0.99821, 1.0557, 1.0326, 1.2, 1.0675, 0.96225, 1.0675, 1.0326, 0.74817, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03754, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.87533, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.98705, 1, 1, 1, 1, 1, 1, 0.98448, 0.9973, 0.98448, 0.9973, 0.98448, 0.9973, 0.83089, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 0.94945, 0.94945, 0.94945, 0.94945, 1.12317, 1.12317, 1.12317, 0.67603, 0.67603, 1.15621, 0.73584, 1.21191, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87709, 0.96927, 1.01473, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.09836, 1.09836, 1.09836, 1.01522, 0.86321, 0.94434, 0.8649, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86438, 1.17308, 1.18416, 1.14589, 0.69825, 0.97622, 1.96791, 1.24822, 1.24822, 1.17308, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.17984, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10742, 1.10742, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + SegoeuiItalicMetrics = { + lineHeight: 1.33008, + lineGap: 0 + }; + SegoeuiRegularFactors = [1.76738, 1, 1, 0.98594, 1.02285, 1.10454, 1.06234, 0.96927, 0.92037, 1.19985, 1.2046, 0.90616, 0.90616, 1.07152, 1.1714, 0.78032, 1.20088, 0.78032, 1.40246, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.96927, 0.78032, 0.78032, 1.1714, 1.1714, 1.1714, 0.80597, 0.94084, 0.96706, 0.85944, 0.85734, 0.97093, 0.75842, 0.79936, 0.88198, 0.9831, 0.95782, 0.71387, 0.86969, 0.84636, 1.07796, 1.03584, 0.96924, 0.83968, 0.96924, 0.82826, 0.79649, 0.85771, 0.95132, 0.93119, 0.98965, 0.88433, 0.8287, 0.93365, 1.08612, 1.3638, 1.08612, 1.45786, 0.74627, 0.80499, 0.91484, 1.05707, 0.92383, 1.05882, 0.9403, 1.12654, 1.05882, 1.01756, 1.09011, 1.09011, 0.99414, 1.09011, 1.034, 1.01756, 1.05356, 1.05707, 1.05882, 1.04399, 0.84863, 1.21968, 1.01756, 0.95801, 1.00068, 0.91797, 0.96777, 0.9043, 0.90351, 0.92105, 0.90351, 1.1714, 0.85337, 0.96927, 0.96927, 0.99912, 0.96927, 0.92105, 0.80597, 1.2434, 1.20808, 1.05937, 0.90957, 1.1714, 1.20808, 0.75155, 0.94261, 1.24644, 1.09971, 1.09971, 0.84751, 1, 0.85273, 0.78032, 0.61584, 1.05425, 1.17914, 0.90957, 1.08665, 1.11593, 1.14169, 0.73381, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.96706, 0.86035, 0.85734, 0.75842, 0.75842, 0.75842, 0.75842, 0.95782, 0.95782, 0.95782, 0.95782, 0.97093, 1.03584, 0.96924, 0.96924, 0.96924, 0.96924, 0.96924, 1.1714, 0.96924, 0.95132, 0.95132, 0.95132, 0.95132, 0.8287, 0.83968, 0.89049, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.91484, 0.93575, 0.92383, 0.9403, 0.9403, 0.9403, 0.9403, 0.8717, 0.8717, 0.8717, 0.8717, 1.00527, 1.01756, 1.05356, 1.05356, 1.05356, 1.05356, 1.05356, 1.24644, 0.95923, 1.01756, 1.01756, 1.01756, 1.01756, 0.96777, 1.05707, 0.96777, 0.96706, 0.91484, 0.96706, 0.91484, 0.96706, 0.91484, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.85734, 0.92383, 0.97093, 1.0969, 0.97093, 1.05882, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.75842, 0.9403, 0.88198, 1.05882, 0.88198, 1.05882, 0.88198, 1.05882, 1, 1, 0.9831, 1.01756, 0.9831, 1.01756, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 0.8717, 0.95782, 1.09011, 0.95782, 0.8717, 0.84784, 1.11551, 0.71387, 1.09011, 1, 1, 0.99414, 0.84636, 1.09011, 1, 1, 0.84636, 1.0536, 0.84636, 0.94298, 0.84636, 1.23297, 1.03584, 1.01756, 1, 1, 1.03584, 1.01756, 1.00323, 1.03444, 1.01756, 0.96924, 1.05356, 0.96924, 1.05356, 0.96924, 1.05356, 0.93066, 0.98293, 0.82826, 1.04399, 1, 1, 0.82826, 1.04399, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 0.79649, 0.84863, 1, 1, 0.85771, 1.17318, 0.85771, 1.21968, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.95132, 1.01756, 0.98965, 1.00068, 0.8287, 0.96777, 0.8287, 0.93365, 0.9043, 0.93365, 0.9043, 0.93365, 0.9043, 1.08571, 0.96927, 0.96706, 0.91484, 0.86035, 0.93575, 0.96924, 0.95923, 1, 1, 0.85771, 1.21968, 1.11437, 1.11437, 0.93109, 0.91202, 0.60411, 0.84164, 0.55572, 1.01173, 0.97361, 0.81818, 0.81818, 0.96635, 0.78032, 0.72727, 0.92366, 0.98601, 1.03405, 0.77968, 1.09799, 1.2, 0.96706, 0.85944, 0.85638, 0.96491, 0.75842, 0.93365, 0.9831, 0.96924, 0.95782, 0.86969, 0.94152, 1.07796, 1.03584, 0.78437, 0.96924, 0.98715, 0.83968, 0.83491, 0.85771, 0.8287, 0.94492, 0.88433, 0.9287, 1.0098, 0.95782, 0.8287, 1.0625, 0.98248, 1.03424, 1.2, 1.01071, 1.0625, 0.95246, 1.03809, 1.04912, 0.98248, 1.00221, 1.03424, 1.05443, 1.2, 1.04785, 0.99609, 1.00169, 1.05176, 0.99346, 1.05356, 0.9087, 1.03004, 0.95542, 0.93117, 1.23362, 1.01071, 1.07831, 1.02512, 1.05205, 1.03502, 1.2, 1.01071, 1.05356, 1.01071, 1.03502, 0.75842, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.03719, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.9403, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.04021, 1, 1, 1, 1, 1, 1, 0.98965, 1.00068, 0.98965, 1.00068, 0.98965, 1.00068, 0.8287, 0.96777, 1, 1.20088, 0.89903, 1, 1, 0.75155, 1.03077, 1.03077, 1.03077, 1.03077, 1.13196, 1.13196, 1.13196, 0.67428, 0.67428, 1.16039, 0.73291, 1.20996, 1.22135, 1.06483, 0.94868, 0.94868, 0.95996, 1.24633, 1, 1.07497, 0.87796, 0.96927, 1.01518, 0.96927, 1, 1, 1, 0.77295, 1, 1, 1.10539, 1.10539, 1.11358, 1.06967, 0.86279, 0.94434, 0.86279, 0.94434, 0.86182, 1, 1, 1.083, 1, 0.91578, 0.86507, 1.1714, 1.18416, 1.14589, 0.69825, 0.97622, 1.9697, 1.24822, 1.24822, 1.17238, 1.24822, 1.24822, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.42603, 1, 0.99862, 0.99862, 1, 0.87025, 0.87025, 0.87025, 0.87025, 1.18083, 1.42603, 1, 1.42603, 1.42603, 0.99862, 1, 1, 1, 1, 1, 1.2886, 1.04315, 1.15296, 1.34163, 1, 1, 1, 1.10938, 1.10938, 1, 1, 1, 1.05425, 1.09971, 1.09971, 1.09971, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; + SegoeuiRegularMetrics = { + lineHeight: 1.33008, + lineGap: 0 + }; + getXFAFontMap = getLookupTableFactory(function(t) { + t["MyriadPro-Regular"] = t["PdfJS-Fallback-Regular"] = { + name: "LiberationSans-Regular", + factors: MyriadProRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: MyriadProRegularMetrics + }; + t["MyriadPro-Bold"] = t["PdfJS-Fallback-Bold"] = { + name: "LiberationSans-Bold", + factors: MyriadProBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: MyriadProBoldMetrics + }; + t["MyriadPro-It"] = t["MyriadPro-Italic"] = t["PdfJS-Fallback-Italic"] = { + name: "LiberationSans-Italic", + factors: MyriadProItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: MyriadProItalicMetrics + }; + t["MyriadPro-BoldIt"] = t["MyriadPro-BoldItalic"] = t["PdfJS-Fallback-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: MyriadProBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: MyriadProBoldItalicMetrics + }; + t.ArialMT = t.Arial = t["Arial-Regular"] = { + name: "LiberationSans-Regular", + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping + }; + t["Arial-BoldMT"] = t["Arial-Bold"] = { + name: "LiberationSans-Bold", + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping + }; + t["Arial-ItalicMT"] = t["Arial-Italic"] = { + name: "LiberationSans-Italic", + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping + }; + t["Arial-BoldItalicMT"] = t["Arial-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping + }; + t["Calibri-Regular"] = { + name: "LiberationSans-Regular", + factors: CalibriRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: CalibriRegularMetrics + }; + t["Calibri-Bold"] = { + name: "LiberationSans-Bold", + factors: CalibriBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: CalibriBoldMetrics + }; + t["Calibri-Italic"] = { + name: "LiberationSans-Italic", + factors: CalibriItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: CalibriItalicMetrics + }; + t["Calibri-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: CalibriBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: CalibriBoldItalicMetrics + }; + t["Segoeui-Regular"] = { + name: "LiberationSans-Regular", + factors: SegoeuiRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: SegoeuiRegularMetrics + }; + t["Segoeui-Bold"] = { + name: "LiberationSans-Bold", + factors: SegoeuiBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: SegoeuiBoldMetrics + }; + t["Segoeui-Italic"] = { + name: "LiberationSans-Italic", + factors: SegoeuiItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: SegoeuiItalicMetrics + }; + t["Segoeui-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: SegoeuiBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: SegoeuiBoldItalicMetrics + }; + t["Helvetica-Regular"] = t.Helvetica = { + name: "LiberationSans-Regular", + factors: HelveticaRegularFactors, + baseWidths: LiberationSansRegularWidths, + baseMapping: LiberationSansRegularMapping, + metrics: HelveticaRegularMetrics + }; + t["Helvetica-Bold"] = { + name: "LiberationSans-Bold", + factors: HelveticaBoldFactors, + baseWidths: LiberationSansBoldWidths, + baseMapping: LiberationSansBoldMapping, + metrics: HelveticaBoldMetrics + }; + t["Helvetica-Italic"] = { + name: "LiberationSans-Italic", + factors: HelveticaItalicFactors, + baseWidths: LiberationSansItalicWidths, + baseMapping: LiberationSansItalicMapping, + metrics: HelveticaItalicMetrics + }; + t["Helvetica-BoldItalic"] = { + name: "LiberationSans-BoldItalic", + factors: HelveticaBoldItalicFactors, + baseWidths: LiberationSansBoldItalicWidths, + baseMapping: LiberationSansBoldItalicMapping, + metrics: HelveticaBoldItalicMetrics + }; + }); + PostScriptParser = class { + constructor(lexer) { + this.lexer = lexer; + this.operators = []; + this.token = null; + this.prev = null; + } + nextToken() { + this.prev = this.token; + this.token = this.lexer.getToken(); + } + accept(type) { + if (this.token.type === type) { + this.nextToken(); + return true; + } + return false; + } + expect(type) { + if (this.accept(type)) { + return true; + } + throw new FormatError3(`Unexpected symbol: found ${this.token.type} expected ${type}.`); + } + parse() { + this.nextToken(); + this.expect(PostScriptTokenTypes.LBRACE); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + return this.operators; + } + parseBlock() { + while (true) { + if (this.accept(PostScriptTokenTypes.NUMBER)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.OPERATOR)) { + this.operators.push(this.prev.value); + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + this.parseCondition(); + } else { + return; + } + } + } + parseCondition() { + const conditionLocation = this.operators.length; + this.operators.push(null, null); + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + if (this.accept(PostScriptTokenTypes.IF)) { + this.operators[conditionLocation] = this.operators.length; + this.operators[conditionLocation + 1] = "jz"; + } else if (this.accept(PostScriptTokenTypes.LBRACE)) { + const jumpLocation = this.operators.length; + this.operators.push(null, null); + const endOfTrue = this.operators.length; + this.parseBlock(); + this.expect(PostScriptTokenTypes.RBRACE); + this.expect(PostScriptTokenTypes.IFELSE); + this.operators[jumpLocation] = this.operators.length; + this.operators[jumpLocation + 1] = "j"; + this.operators[conditionLocation] = endOfTrue; + this.operators[conditionLocation + 1] = "jz"; + } else { + throw new FormatError3("PS Function: error parsing conditional."); + } + } + }; + PostScriptTokenTypes = { + LBRACE: 0, + RBRACE: 1, + NUMBER: 2, + OPERATOR: 3, + IF: 4, + IFELSE: 5 + }; + PostScriptToken = class _PostScriptToken { + static get opCache() { + return shadow2(this, "opCache", /* @__PURE__ */ Object.create(null)); + } + constructor(type, value) { + this.type = type; + this.value = value; + } + static getOperator(op) { + return _PostScriptToken.opCache[op] ||= new _PostScriptToken(PostScriptTokenTypes.OPERATOR, op); + } + static get LBRACE() { + return shadow2(this, "LBRACE", new _PostScriptToken(PostScriptTokenTypes.LBRACE, "{")); + } + static get RBRACE() { + return shadow2(this, "RBRACE", new _PostScriptToken(PostScriptTokenTypes.RBRACE, "}")); + } + static get IF() { + return shadow2(this, "IF", new _PostScriptToken(PostScriptTokenTypes.IF, "IF")); + } + static get IFELSE() { + return shadow2(this, "IFELSE", new _PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE")); + } + }; + PostScriptLexer = class { + constructor(stream) { + this.stream = stream; + this.nextChar(); + this.strBuf = []; + } + nextChar() { + return this.currentChar = this.stream.getByte(); + } + getToken() { + let comment = false; + let ch2 = this.currentChar; + while (true) { + if (ch2 < 0) { + return EOF; + } + if (comment) { + if (ch2 === 10 || ch2 === 13) { + comment = false; + } + } else if (ch2 === 37) { + comment = true; + } else if (!isWhiteSpace(ch2)) { + break; + } + ch2 = this.nextChar(); + } + switch (ch2 | 0) { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + case 43: + case 45: + case 46: + return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber()); + case 123: + this.nextChar(); + return PostScriptToken.LBRACE; + case 125: + this.nextChar(); + return PostScriptToken.RBRACE; + } + const strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch2); + while ((ch2 = this.nextChar()) >= 0 && (ch2 >= 65 && ch2 <= 90 || ch2 >= 97 && ch2 <= 122)) { + strBuf.push(String.fromCharCode(ch2)); + } + const str = strBuf.join(""); + switch (str.toLowerCase()) { + case "if": + return PostScriptToken.IF; + case "ifelse": + return PostScriptToken.IFELSE; + default: + return PostScriptToken.getOperator(str); + } + } + getNumber() { + let ch2 = this.currentChar; + const strBuf = this.strBuf; + strBuf.length = 0; + strBuf[0] = String.fromCharCode(ch2); + while ((ch2 = this.nextChar()) >= 0) { + if (ch2 >= 48 && ch2 <= 57 || ch2 === 45 || ch2 === 46) { + strBuf.push(String.fromCharCode(ch2)); + } else { + break; + } + } + const value = parseFloat(strBuf.join("")); + if (isNaN(value)) { + throw new FormatError3(`Invalid floating point number: ${value}`); + } + return value; + } + }; + BaseLocalCache = class { + constructor(options) { + this._onlyRefs = options?.onlyRefs === true; + if (!this._onlyRefs) { + this._nameRefMap = /* @__PURE__ */ new Map(); + this._imageMap = /* @__PURE__ */ new Map(); + } + this._imageCache = new RefSetCache(); + } + getByName(name) { + if (this._onlyRefs) { + unreachable2("Should not call `getByName` method."); + } + const ref = this._nameRefMap.get(name); + if (ref) { + return this.getByRef(ref); + } + return this._imageMap.get(name) || null; + } + getByRef(ref) { + return this._imageCache.get(ref) || null; + } + set(name, ref, data) { + unreachable2("Abstract method `set` called."); + } + }; + LocalImageCache = class extends BaseLocalCache { + set(name, ref = null, data) { + if (typeof name !== "string") { + throw new Error('LocalImageCache.set - expected "name" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + this._nameRefMap.set(name, ref); + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } + }; + LocalColorSpaceCache = class extends BaseLocalCache { + set(name = null, ref = null, data) { + if (typeof name !== "string" && !ref) { + throw new Error('LocalColorSpaceCache.set - expected "name" and/or "ref" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + if (name !== null) { + this._nameRefMap.set(name, ref); + } + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } + }; + LocalFunctionCache = class extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('LocalFunctionCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } + }; + LocalGStateCache = class extends BaseLocalCache { + set(name, ref = null, data) { + if (typeof name !== "string") { + throw new Error('LocalGStateCache.set - expected "name" argument.'); + } + if (ref) { + if (this._imageCache.has(ref)) { + return; + } + this._nameRefMap.set(name, ref); + this._imageCache.put(ref, data); + return; + } + if (this._imageMap.has(name)) { + return; + } + this._imageMap.set(name, data); + } + }; + LocalTilingPatternCache = class extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('LocalTilingPatternCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } + }; + RegionalImageCache = class extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('RegionalImageCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } + }; + GlobalColorSpaceCache = class extends BaseLocalCache { + constructor(options) { + super({ + onlyRefs: true + }); + } + set(name = null, ref, data) { + if (!ref) { + throw new Error('GlobalColorSpaceCache.set - expected "ref" argument.'); + } + if (this._imageCache.has(ref)) { + return; + } + this._imageCache.put(ref, data); + } + clear() { + this._imageCache.clear(); + } + }; + GlobalImageCache = class _GlobalImageCache { + static NUM_PAGES_THRESHOLD = 2; + static MIN_IMAGES_TO_CACHE = 10; + static MAX_BYTE_SIZE = 5e7; + #decodeFailedSet = new RefSet(); + constructor() { + this._refCache = new RefSetCache(); + this._imageCache = new RefSetCache(); + } + get #byteSize() { + let byteSize = 0; + for (const imageData of this._imageCache) { + byteSize += imageData.byteSize; + } + return byteSize; + } + get #cacheLimitReached() { + if (this._imageCache.size < _GlobalImageCache.MIN_IMAGES_TO_CACHE) { + return false; + } + if (this.#byteSize < _GlobalImageCache.MAX_BYTE_SIZE) { + return false; + } + return true; + } + shouldCache(ref, pageIndex) { + let pageIndexSet = this._refCache.get(ref); + if (!pageIndexSet) { + pageIndexSet = /* @__PURE__ */ new Set(); + this._refCache.put(ref, pageIndexSet); + } + pageIndexSet.add(pageIndex); + if (pageIndexSet.size < _GlobalImageCache.NUM_PAGES_THRESHOLD) { + return false; + } + if (!this._imageCache.has(ref) && this.#cacheLimitReached) { + return false; + } + return true; + } + addDecodeFailed(ref) { + this.#decodeFailedSet.put(ref); + } + hasDecodeFailed(ref) { + return this.#decodeFailedSet.has(ref); + } + addByteSize(ref, byteSize) { + const imageData = this._imageCache.get(ref); + if (!imageData) { + return; + } + if (imageData.byteSize) { + return; + } + imageData.byteSize = byteSize; + } + getData(ref, pageIndex) { + const pageIndexSet = this._refCache.get(ref); + if (!pageIndexSet) { + return null; + } + if (pageIndexSet.size < _GlobalImageCache.NUM_PAGES_THRESHOLD) { + return null; + } + const imageData = this._imageCache.get(ref); + if (!imageData) { + return null; + } + pageIndexSet.add(pageIndex); + return imageData; + } + setData(ref, data) { + if (!this._refCache.has(ref)) { + throw new Error('GlobalImageCache.setData - expected "shouldCache" to have been called.'); + } + if (this._imageCache.has(ref)) { + return; + } + if (this.#cacheLimitReached) { + warn2("GlobalImageCache.setData - cache limit reached."); + return; + } + this._imageCache.put(ref, data); + } + clear(onlyData = false) { + if (!onlyData) { + this.#decodeFailedSet.clear(); + this._refCache.clear(); + } + this._imageCache.clear(); + } + }; + PDFFunctionFactory = class { + constructor({ + xref, + isEvalSupported: isEvalSupported3 = true + }) { + this.xref = xref; + this.isEvalSupported = isEvalSupported3 !== false; + } + create(fn, parseArray = false) { + let fnRef, parsedFn; + if (fn instanceof Ref) { + fnRef = fn; + } else if (fn instanceof Dict) { + fnRef = fn.objId; + } else if (fn instanceof BaseStream) { + fnRef = fn.dict?.objId; + } + if (fnRef) { + const cachedFn = this._localFunctionCache.getByRef(fnRef); + if (cachedFn) { + return cachedFn; + } + } + const fnObj = this.xref.fetchIfRef(fn); + if (Array.isArray(fnObj)) { + if (!parseArray) { + throw new Error('PDFFunctionFactory.create - expected "parseArray" argument.'); + } + parsedFn = PDFFunction.parseArray(this, fnObj); + } else { + parsedFn = PDFFunction.parse(this, fnObj); + } + if (fnRef) { + this._localFunctionCache.set(null, fnRef, parsedFn); + } + return parsedFn; + } + get _localFunctionCache() { + return shadow2(this, "_localFunctionCache", new LocalFunctionCache()); + } + }; + PDFFunction = class { + static getSampleArray(size3, outputSize, bps, stream) { + let i, ii; + let length = 1; + for (i = 0, ii = size3.length; i < ii; i++) { + length *= size3[i]; + } + length *= outputSize; + const array2 = new Array(length); + let codeSize = 0; + let codeBuf = 0; + const sampleMul = 1 / (2 ** bps - 1); + const strBytes = stream.getBytes((length * bps + 7) / 8); + let strIdx = 0; + for (i = 0; i < length; i++) { + while (codeSize < bps) { + codeBuf <<= 8; + codeBuf |= strBytes[strIdx++]; + codeSize += 8; + } + codeSize -= bps; + array2[i] = (codeBuf >> codeSize) * sampleMul; + codeBuf &= (1 << codeSize) - 1; + } + return array2; + } + static parse(factory, fn) { + const dict = fn.dict || fn; + const typeNum = dict.get("FunctionType"); + switch (typeNum) { + case 0: + return this.constructSampled(factory, fn, dict); + case 1: + break; + case 2: + return this.constructInterpolated(factory, dict); + case 3: + return this.constructStiched(factory, dict); + case 4: + return this.constructPostScript(factory, fn, dict); + } + throw new FormatError3("Unknown type of function"); + } + static parseArray(factory, fnObj) { + const { + xref + } = factory; + const fnArray = []; + for (const fn of fnObj) { + fnArray.push(this.parse(factory, xref.fetchIfRef(fn))); + } + return function(src, srcOffset, dest, destOffset) { + for (let i = 0, ii = fnArray.length; i < ii; i++) { + fnArray[i](src, srcOffset, dest, destOffset + i); + } + }; + } + static constructSampled(factory, fn, dict) { + function toMultiArray(arr) { + const inputLength = arr.length; + const out = []; + let index2 = 0; + for (let i = 0; i < inputLength; i += 2) { + out[index2++] = [arr[i], arr[i + 1]]; + } + return out; + } + function interpolate(x, xmin, xmax, ymin, ymax) { + return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin)); + } + let domain2 = toNumberArray(dict.getArray("Domain")); + let range2 = toNumberArray(dict.getArray("Range")); + if (!domain2 || !range2) { + throw new FormatError3("No domain or range"); + } + const inputSize = domain2.length / 2; + const outputSize = range2.length / 2; + domain2 = toMultiArray(domain2); + range2 = toMultiArray(range2); + const size3 = toNumberArray(dict.getArray("Size")); + const bps = dict.get("BitsPerSample"); + const order = dict.get("Order") || 1; + if (order !== 1) { + info2("No support for cubic spline interpolation: " + order); + } + let encode4 = toNumberArray(dict.getArray("Encode")); + if (!encode4) { + encode4 = []; + for (let i = 0; i < inputSize; ++i) { + encode4.push([0, size3[i] - 1]); + } + } else { + encode4 = toMultiArray(encode4); + } + let decode4 = toNumberArray(dict.getArray("Decode")); + decode4 = !decode4 ? range2 : toMultiArray(decode4); + const samples = this.getSampleArray(size3, outputSize, bps, fn); + return function constructSampledFn(src, srcOffset, dest, destOffset) { + const cubeVertices = 1 << inputSize; + const cubeN = new Float64Array(cubeVertices).fill(1); + const cubeVertex = new Uint32Array(cubeVertices); + let i, j; + let k = outputSize, pos = 1; + for (i = 0; i < inputSize; ++i) { + const domain_2i = domain2[i][0]; + const domain_2i_1 = domain2[i][1]; + const xi = MathClamp2(src[srcOffset + i], domain_2i, domain_2i_1); + let e = interpolate(xi, domain_2i, domain_2i_1, encode4[i][0], encode4[i][1]); + const size_i = size3[i]; + e = MathClamp2(e, 0, size_i - 1); + const e0 = e < size_i - 1 ? Math.floor(e) : e - 1; + const n0 = e0 + 1 - e; + const n1 = e - e0; + const offset0 = e0 * k; + const offset1 = offset0 + k; + for (j = 0; j < cubeVertices; j++) { + if (j & pos) { + cubeN[j] *= n1; + cubeVertex[j] += offset1; + } else { + cubeN[j] *= n0; + cubeVertex[j] += offset0; + } + } + k *= size_i; + pos <<= 1; + } + for (j = 0; j < outputSize; ++j) { + let rj = 0; + for (i = 0; i < cubeVertices; i++) { + rj += samples[cubeVertex[i] + j] * cubeN[i]; + } + rj = interpolate(rj, 0, 1, decode4[j][0], decode4[j][1]); + dest[destOffset + j] = MathClamp2(rj, range2[j][0], range2[j][1]); + } + }; + } + static constructInterpolated(factory, dict) { + const c0 = toNumberArray(dict.getArray("C0")) || [0]; + const c1 = toNumberArray(dict.getArray("C1")) || [1]; + const n = dict.get("N"); + const diff = []; + for (let i = 0, ii = c0.length; i < ii; ++i) { + diff.push(c1[i] - c0[i]); + } + const length = diff.length; + return function constructInterpolatedFn(src, srcOffset, dest, destOffset) { + const x = n === 1 ? src[srcOffset] : src[srcOffset] ** n; + for (let j = 0; j < length; ++j) { + dest[destOffset + j] = c0[j] + x * diff[j]; + } + }; + } + static constructStiched(factory, dict) { + const domain2 = toNumberArray(dict.getArray("Domain")); + if (!domain2) { + throw new FormatError3("No domain"); + } + const inputSize = domain2.length / 2; + if (inputSize !== 1) { + throw new FormatError3("Bad domain for stiched function"); + } + const { + xref + } = factory; + const fns = []; + for (const fn of dict.get("Functions")) { + fns.push(this.parse(factory, xref.fetchIfRef(fn))); + } + const bounds = toNumberArray(dict.getArray("Bounds")); + const encode4 = toNumberArray(dict.getArray("Encode")); + const tmpBuf = new Float32Array(1); + return function constructStichedFn(src, srcOffset, dest, destOffset) { + const v = MathClamp2(src[srcOffset], domain2[0], domain2[1]); + const length = bounds.length; + let i; + for (i = 0; i < length; ++i) { + if (v < bounds[i]) { + break; + } + } + let dmin = domain2[0]; + if (i > 0) { + dmin = bounds[i - 1]; + } + let dmax = domain2[1]; + if (i < bounds.length) { + dmax = bounds[i]; + } + const rmin = encode4[2 * i]; + const rmax = encode4[2 * i + 1]; + tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); + fns[i](tmpBuf, 0, dest, destOffset); + }; + } + static constructPostScript(factory, fn, dict) { + const domain2 = toNumberArray(dict.getArray("Domain")); + const range2 = toNumberArray(dict.getArray("Range")); + if (!domain2) { + throw new FormatError3("No domain."); + } + if (!range2) { + throw new FormatError3("No range."); + } + const lexer = new PostScriptLexer(fn); + const parser = new PostScriptParser(lexer); + const code = parser.parse(); + if (factory.isEvalSupported && FeatureTest2.isEvalSupported) { + const compiled = new PostScriptCompiler().compile(code, domain2, range2); + if (compiled) { + return new Function("src", "srcOffset", "dest", "destOffset", compiled); + } + } + info2("Unable to compile PS function"); + const numOutputs = range2.length >> 1; + const numInputs = domain2.length >> 1; + const evaluator = new PostScriptEvaluator(code); + const cache2 = /* @__PURE__ */ Object.create(null); + const MAX_CACHE_SIZE = 2048 * 4; + let cache_available = MAX_CACHE_SIZE; + const tmpBuf = new Float32Array(numInputs); + return function constructPostScriptFn(src, srcOffset, dest, destOffset) { + let i, value; + let key = ""; + const input2 = tmpBuf; + for (i = 0; i < numInputs; i++) { + value = src[srcOffset + i]; + input2[i] = value; + key += value + "_"; + } + const cachedValue = cache2[key]; + if (cachedValue !== void 0) { + dest.set(cachedValue, destOffset); + return; + } + const output2 = new Float32Array(numOutputs); + const stack = evaluator.execute(input2); + const stackIndex = stack.length - numOutputs; + for (i = 0; i < numOutputs; i++) { + value = stack[stackIndex + i]; + let bound = range2[i * 2]; + if (value < bound) { + value = bound; + } else { + bound = range2[i * 2 + 1]; + if (value > bound) { + value = bound; + } + } + output2[i] = value; + } + if (cache_available > 0) { + cache_available--; + cache2[key] = output2; + } + dest.set(output2, destOffset); + }; + } + }; + PostScriptStack = class _PostScriptStack { + static MAX_STACK_SIZE = 100; + constructor(initialStack) { + this.stack = initialStack ? Array.from(initialStack) : []; + } + push(value) { + if (this.stack.length >= _PostScriptStack.MAX_STACK_SIZE) { + throw new Error("PostScript function stack overflow."); + } + this.stack.push(value); + } + pop() { + if (this.stack.length <= 0) { + throw new Error("PostScript function stack underflow."); + } + return this.stack.pop(); + } + copy(n) { + if (this.stack.length + n >= _PostScriptStack.MAX_STACK_SIZE) { + throw new Error("PostScript function stack overflow."); + } + const stack = this.stack; + for (let i = stack.length - n, j = n - 1; j >= 0; j--, i++) { + stack.push(stack[i]); + } + } + index(n) { + this.push(this.stack[this.stack.length - n - 1]); + } + roll(n, p) { + const stack = this.stack; + const l2 = stack.length - n; + const r = stack.length - 1; + const c = l2 + (p - Math.floor(p / n) * n); + for (let i = l2, j = r; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (let i = l2, j = c - 1; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + for (let i = c, j = r; i < j; i++, j--) { + const t = stack[i]; + stack[i] = stack[j]; + stack[j] = t; + } + } + }; + PostScriptEvaluator = class { + constructor(operators2) { + this.operators = operators2; + } + execute(initialStack) { + const stack = new PostScriptStack(initialStack); + let counter = 0; + const operators2 = this.operators; + const length = operators2.length; + let operator, a, b2; + while (counter < length) { + operator = operators2[counter++]; + if (typeof operator === "number") { + stack.push(operator); + continue; + } + switch (operator) { + case "jz": + b2 = stack.pop(); + a = stack.pop(); + if (!a) { + counter = b2; + } + break; + case "j": + a = stack.pop(); + counter = a; + break; + case "abs": + a = stack.pop(); + stack.push(Math.abs(a)); + break; + case "add": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a + b2); + break; + case "and": + b2 = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b2 === "boolean") { + stack.push(a && b2); + } else { + stack.push(a & b2); + } + break; + case "atan": + b2 = stack.pop(); + a = stack.pop(); + a = Math.atan2(a, b2) / Math.PI * 180; + if (a < 0) { + a += 360; + } + stack.push(a); + break; + case "bitshift": + b2 = stack.pop(); + a = stack.pop(); + if (a > 0) { + stack.push(a << b2); + } else { + stack.push(a >> b2); + } + break; + case "ceiling": + a = stack.pop(); + stack.push(Math.ceil(a)); + break; + case "copy": + a = stack.pop(); + stack.copy(a); + break; + case "cos": + a = stack.pop(); + stack.push(Math.cos(a % 360 / 180 * Math.PI)); + break; + case "cvi": + a = stack.pop() | 0; + stack.push(a); + break; + case "cvr": + break; + case "div": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a / b2); + break; + case "dup": + stack.copy(1); + break; + case "eq": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a === b2); + break; + case "exch": + stack.roll(2, 1); + break; + case "exp": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a ** b2); + break; + case "false": + stack.push(false); + break; + case "floor": + a = stack.pop(); + stack.push(Math.floor(a)); + break; + case "ge": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a >= b2); + break; + case "gt": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a > b2); + break; + case "idiv": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a / b2 | 0); + break; + case "index": + a = stack.pop(); + stack.index(a); + break; + case "le": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a <= b2); + break; + case "ln": + a = stack.pop(); + stack.push(Math.log(a)); + break; + case "log": + a = stack.pop(); + stack.push(Math.log10(a)); + break; + case "lt": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a < b2); + break; + case "mod": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a % b2); + break; + case "mul": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a * b2); + break; + case "ne": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a !== b2); + break; + case "neg": + a = stack.pop(); + stack.push(-a); + break; + case "not": + a = stack.pop(); + if (typeof a === "boolean") { + stack.push(!a); + } else { + stack.push(~a); + } + break; + case "or": + b2 = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b2 === "boolean") { + stack.push(a || b2); + } else { + stack.push(a | b2); + } + break; + case "pop": + stack.pop(); + break; + case "roll": + b2 = stack.pop(); + a = stack.pop(); + stack.roll(a, b2); + break; + case "round": + a = stack.pop(); + stack.push(Math.round(a)); + break; + case "sin": + a = stack.pop(); + stack.push(Math.sin(a % 360 / 180 * Math.PI)); + break; + case "sqrt": + a = stack.pop(); + stack.push(Math.sqrt(a)); + break; + case "sub": + b2 = stack.pop(); + a = stack.pop(); + stack.push(a - b2); + break; + case "true": + stack.push(true); + break; + case "truncate": + a = stack.pop(); + a = a < 0 ? Math.ceil(a) : Math.floor(a); + stack.push(a); + break; + case "xor": + b2 = stack.pop(); + a = stack.pop(); + if (typeof a === "boolean" && typeof b2 === "boolean") { + stack.push(a !== b2); + } else { + stack.push(a ^ b2); + } + break; + default: + throw new FormatError3(`Unknown operator ${operator}`); + } + } + return stack.stack; + } + }; + AstNode = class { + constructor(type) { + this.type = type; + } + visit(visitor) { + unreachable2("abstract method"); + } + }; + AstArgument = class extends AstNode { + constructor(index2, min2, max2) { + super("args"); + this.index = index2; + this.min = min2; + this.max = max2; + } + visit(visitor) { + visitor.visitArgument(this); + } + }; + AstLiteral = class extends AstNode { + constructor(number4) { + super("literal"); + this.number = number4; + this.min = number4; + this.max = number4; + } + visit(visitor) { + visitor.visitLiteral(this); + } + }; + AstBinaryOperation = class extends AstNode { + constructor(op, arg1, arg2, min2, max2) { + super("binary"); + this.op = op; + this.arg1 = arg1; + this.arg2 = arg2; + this.min = min2; + this.max = max2; + } + visit(visitor) { + visitor.visitBinaryOperation(this); + } + }; + AstMin = class extends AstNode { + constructor(arg, max2) { + super("max"); + this.arg = arg; + this.min = arg.min; + this.max = max2; + } + visit(visitor) { + visitor.visitMin(this); + } + }; + AstVariable = class extends AstNode { + constructor(index2, min2, max2) { + super("var"); + this.index = index2; + this.min = min2; + this.max = max2; + } + visit(visitor) { + visitor.visitVariable(this); + } + }; + AstVariableDefinition = class extends AstNode { + constructor(variable, arg) { + super("definition"); + this.variable = variable; + this.arg = arg; + } + visit(visitor) { + visitor.visitVariableDefinition(this); + } + }; + ExpressionBuilderVisitor = class { + constructor() { + this.parts = []; + } + visitArgument(arg) { + this.parts.push("Math.max(", arg.min, ", Math.min(", arg.max, ", src[srcOffset + ", arg.index, "]))"); + } + visitVariable(variable) { + this.parts.push("v", variable.index); + } + visitLiteral(literal2) { + this.parts.push(literal2.number); + } + visitBinaryOperation(operation) { + this.parts.push("("); + operation.arg1.visit(this); + this.parts.push(" ", operation.op, " "); + operation.arg2.visit(this); + this.parts.push(")"); + } + visitVariableDefinition(definition) { + this.parts.push("var "); + definition.variable.visit(this); + this.parts.push(" = "); + definition.arg.visit(this); + this.parts.push(";"); + } + visitMin(max2) { + this.parts.push("Math.min("); + max2.arg.visit(this); + this.parts.push(", ", max2.max, ")"); + } + toString() { + return this.parts.join(""); + } + }; + PostScriptCompiler = class { + compile(code, domain2, range2) { + const stack = []; + const instructions = []; + const inputSize = domain2.length >> 1, outputSize = range2.length >> 1; + let lastRegister = 0; + let n, j; + let num1, num2, ast1, ast2, tmpVar, item; + for (let i = 0; i < inputSize; i++) { + stack.push(new AstArgument(i, domain2[i * 2], domain2[i * 2 + 1])); + } + for (let i = 0, ii = code.length; i < ii; i++) { + item = code[i]; + if (typeof item === "number") { + stack.push(new AstLiteral(item)); + continue; + } + switch (item) { + case "add": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildAddOperation(num1, num2)); + break; + case "cvr": + if (stack.length < 1) { + return null; + } + break; + case "mul": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildMulOperation(num1, num2)); + break; + case "sub": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + stack.push(buildSubOperation(num1, num2)); + break; + case "exch": + if (stack.length < 2) { + return null; + } + ast1 = stack.pop(); + ast2 = stack.pop(); + stack.push(ast1, ast2); + break; + case "pop": + if (stack.length < 1) { + return null; + } + stack.pop(); + break; + case "index": + if (stack.length < 1) { + return null; + } + num1 = stack.pop(); + if (num1.type !== "literal") { + return null; + } + n = num1.number; + if (n < 0 || !Number.isInteger(n) || stack.length < n) { + return null; + } + ast1 = stack[stack.length - n - 1]; + if (ast1.type === "literal" || ast1.type === "var") { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - n - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case "dup": + if (stack.length < 1) { + return null; + } + if (typeof code[i + 1] === "number" && code[i + 2] === "gt" && code[i + 3] === i + 7 && code[i + 4] === "jz" && code[i + 5] === "pop" && code[i + 6] === code[i + 1]) { + num1 = stack.pop(); + stack.push(buildMinOperation(num1, code[i + 1])); + i += 6; + break; + } + ast1 = stack.at(-1); + if (ast1.type === "literal" || ast1.type === "var") { + stack.push(ast1); + break; + } + tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max); + stack[stack.length - 1] = tmpVar; + stack.push(tmpVar); + instructions.push(new AstVariableDefinition(tmpVar, ast1)); + break; + case "roll": + if (stack.length < 2) { + return null; + } + num2 = stack.pop(); + num1 = stack.pop(); + if (num2.type !== "literal" || num1.type !== "literal") { + return null; + } + j = num2.number; + n = num1.number; + if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) { + return null; + } + j = (j % n + n) % n; + if (j === 0) { + break; + } + stack.push(...stack.splice(stack.length - n, n - j)); + break; + default: + return null; + } + } + if (stack.length !== outputSize) { + return null; + } + const result2 = []; + for (const instruction of instructions) { + const statementBuilder = new ExpressionBuilderVisitor(); + instruction.visit(statementBuilder); + result2.push(statementBuilder.toString()); + } + for (let i = 0, ii = stack.length; i < ii; i++) { + const expr = stack[i], statementBuilder = new ExpressionBuilderVisitor(); + expr.visit(statementBuilder); + const min2 = range2[i * 2], max2 = range2[i * 2 + 1]; + const out = [statementBuilder.toString()]; + if (min2 > expr.min) { + out.unshift("Math.max(", min2, ", "); + out.push(")"); + } + if (max2 < expr.max) { + out.unshift("Math.min(", max2, ", "); + out.push(")"); + } + out.unshift("dest[destOffset + ", i, "] = "); + out.push(";"); + result2.push(out.join("")); + } + return result2.join("\n"); + } + }; + baseTypes = ["BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S", "WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "ON", "ON", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "ON", "ES", "CS", "ES", "CS", "CS", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON", "BN", "BN", "BN", "BN", "BN", "BN", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "ON", "ET", "ET", "ET", "ET", "ON", "ON", "ON", "ON", "L", "ON", "ON", "BN", "ON", "ON", "ET", "ET", "EN", "EN", "ON", "L", "ON", "ON", "ON", "EN", "L", "ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L"]; + arabicTypes = ["AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL", "CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "AN", "ET", "AN", "AN", "AL", "AL", "AL", "NSM", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM", "ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL"]; + chars = []; + types2 = []; + CssFontInfo2 = class _CssFontInfo { + #buffer; + #view; + #decoder; + static strings = ["fontFamily", "fontWeight", "italicAngle"]; + static write(info3) { + const encoder2 = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of _CssFontInfo.strings) { + const encoded = encoder2.encode(info3[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + const buffer2 = new ArrayBuffer(stringsLength); + const data = new Uint8Array(buffer2); + const view = new DataView(buffer2); + let offset = 0; + for (const prop of _CssFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + assert3(offset === buffer2.byteLength, "CssFontInfo.write: Buffer overflow"); + return buffer2; + } + constructor(buffer2) { + this.#buffer = buffer2; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + #readString(index2) { + assert3(index2 < _CssFontInfo.strings.length, "Invalid string index"); + let offset = 0; + for (let i = 0; i < index2; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get fontFamily() { + return this.#readString(0); + } + get fontWeight() { + return this.#readString(1); + } + get italicAngle() { + return this.#readString(2); + } + }; + SystemFontInfo2 = class _SystemFontInfo { + #buffer; + #view; + #decoder; + static strings = ["css", "loadedName", "baseFontName", "src"]; + static write(info3) { + const encoder2 = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of _SystemFontInfo.strings) { + const encoded = encoder2.encode(info3[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + stringsLength += 4; + let encodedStyleStyle, encodedStyleWeight, lengthEstimate = 1 + stringsLength; + if (info3.style) { + encodedStyleStyle = encoder2.encode(info3.style.style); + encodedStyleWeight = encoder2.encode(info3.style.weight); + lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length; + } + const buffer2 = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer2); + const view = new DataView(buffer2); + let offset = 0; + view.setUint8(offset++, info3.guessFallback ? 1 : 0); + view.setUint32(offset, 0); + offset += 4; + stringsLength = 0; + for (const prop of _SystemFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + stringsLength += 4 + length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(offset - stringsLength - 4, stringsLength); + if (info3.style) { + view.setUint32(offset, encodedStyleStyle.length); + data.set(encodedStyleStyle, offset + 4); + offset += 4 + encodedStyleStyle.length; + view.setUint32(offset, encodedStyleWeight.length); + data.set(encodedStyleWeight, offset + 4); + offset += 4 + encodedStyleWeight.length; + } + assert3(offset <= buffer2.byteLength, "SubstitionInfo.write: Buffer overflow"); + return buffer2.transferToFixedLength(offset); + } + constructor(buffer2) { + this.#buffer = buffer2; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + get guessFallback() { + return this.#view.getUint8(0) !== 0; + } + #readString(index2) { + assert3(index2 < _SystemFontInfo.strings.length, "Invalid string index"); + let offset = 5; + for (let i = 0; i < index2; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get css() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get baseFontName() { + return this.#readString(2); + } + get src() { + return this.#readString(3); + } + get style() { + let offset = 1; + offset += 4 + this.#view.getUint32(offset); + const styleLength = this.#view.getUint32(offset); + const style = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, styleLength)); + offset += 4 + styleLength; + const weightLength = this.#view.getUint32(offset); + const weight = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, weightLength)); + return { + style, + weight + }; + } + }; + FontInfo2 = class _FontInfo { + static bools = ["black", "bold", "disableFontFace", "fontExtraProperties", "isInvalidPDFjsFont", "isType3Font", "italic", "missingFile", "remeasure", "vertical"]; + static numbers = ["ascent", "defaultWidth", "descent"]; + static strings = ["fallbackName", "loadedName", "mimetype", "name"]; + static #OFFSET_NUMBERS = Math.ceil(this.bools.length * 2 / 8); + static #OFFSET_BBOX = this.#OFFSET_NUMBERS + this.numbers.length * 8; + static #OFFSET_FONT_MATRIX = this.#OFFSET_BBOX + 1 + 2 * 4; + static #OFFSET_DEFAULT_VMETRICS = this.#OFFSET_FONT_MATRIX + 1 + 8 * 6; + static #OFFSET_STRINGS = this.#OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3; + #buffer; + #decoder; + #view; + constructor({ + data, + extra + }) { + this.#buffer = data; + this.#decoder = new TextDecoder(); + this.#view = new DataView(this.#buffer); + if (extra) { + Object.assign(this, extra); + } + } + #readBoolean(index2) { + assert3(index2 < _FontInfo.bools.length, "Invalid boolean index"); + const byteOffset = Math.floor(index2 / 4); + const bitOffset = index2 * 2 % 8; + const value = this.#view.getUint8(byteOffset) >> bitOffset & 3; + return value === 0 ? void 0 : value === 2; + } + get black() { + return this.#readBoolean(0); + } + get bold() { + return this.#readBoolean(1); + } + get disableFontFace() { + return this.#readBoolean(2); + } + get fontExtraProperties() { + return this.#readBoolean(3); + } + get isInvalidPDFjsFont() { + return this.#readBoolean(4); + } + get isType3Font() { + return this.#readBoolean(5); + } + get italic() { + return this.#readBoolean(6); + } + get missingFile() { + return this.#readBoolean(7); + } + get remeasure() { + return this.#readBoolean(8); + } + get vertical() { + return this.#readBoolean(9); + } + #readNumber(index2) { + assert3(index2 < _FontInfo.numbers.length, "Invalid number index"); + return this.#view.getFloat64(_FontInfo.#OFFSET_NUMBERS + index2 * 8); + } + get ascent() { + return this.#readNumber(0); + } + get defaultWidth() { + return this.#readNumber(1); + } + get descent() { + return this.#readNumber(2); + } + get bbox() { + let offset = _FontInfo.#OFFSET_BBOX; + const numCoords = this.#view.getUint8(offset); + if (numCoords === 0) { + return void 0; + } + offset += 1; + const bbox = []; + for (let i = 0; i < 4; i++) { + bbox.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return bbox; + } + get fontMatrix() { + let offset = _FontInfo.#OFFSET_FONT_MATRIX; + const numPoints = this.#view.getUint8(offset); + if (numPoints === 0) { + return void 0; + } + offset += 1; + const fontMatrix = []; + for (let i = 0; i < 6; i++) { + fontMatrix.push(this.#view.getFloat64(offset, true)); + offset += 8; + } + return fontMatrix; + } + get defaultVMetrics() { + let offset = _FontInfo.#OFFSET_DEFAULT_VMETRICS; + const numMetrics = this.#view.getUint8(offset); + if (numMetrics === 0) { + return void 0; + } + offset += 1; + const defaultVMetrics = []; + for (let i = 0; i < 3; i++) { + defaultVMetrics.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return defaultVMetrics; + } + #readString(index2) { + assert3(index2 < _FontInfo.strings.length, "Invalid string index"); + let offset = _FontInfo.#OFFSET_STRINGS + 4; + for (let i = 0; i < index2; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + const stringData = new Uint8Array(length); + stringData.set(new Uint8Array(this.#buffer, offset + 4, length)); + return this.#decoder.decode(stringData); + } + get fallbackName() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get mimetype() { + return this.#readString(2); + } + get name() { + return this.#readString(3); + } + get data() { + let offset = _FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + if (length === 0) { + return void 0; + } + return new Uint8Array(this.#buffer, offset + 4, length); + } + clearData() { + let offset = _FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + const data = new Uint8Array(this.#buffer, offset + 4, length); + data.fill(0); + this.#view.setUint32(offset, 0); + } + get cssFontInfo() { + let offset = _FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + if (cssFontInfoLength === 0) { + return null; + } + const cssFontInfoData = new Uint8Array(cssFontInfoLength); + cssFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength)); + return new CssFontInfo2(cssFontInfoData.buffer); + } + get systemFontInfo() { + let offset = _FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + if (systemFontInfoLength === 0) { + return null; + } + const systemFontInfoData = new Uint8Array(systemFontInfoLength); + systemFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength)); + return new SystemFontInfo2(systemFontInfoData.buffer); + } + static write(font) { + const systemFontInfoBuffer = font.systemFontInfo ? SystemFontInfo2.write(font.systemFontInfo) : null; + const cssFontInfoBuffer = font.cssFontInfo ? CssFontInfo2.write(font.cssFontInfo) : null; + const encoder2 = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of _FontInfo.strings) { + encodedStrings[prop] = encoder2.encode(font[prop]); + stringsLength += 4 + encodedStrings[prop].length; + } + const lengthEstimate = _FontInfo.#OFFSET_STRINGS + 4 + stringsLength + 4 + (systemFontInfoBuffer ? systemFontInfoBuffer.byteLength : 0) + 4 + (cssFontInfoBuffer ? cssFontInfoBuffer.byteLength : 0) + 4 + (font.data ? font.data.length : 0); + const buffer2 = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer2); + const view = new DataView(buffer2); + let offset = 0; + const numBools = _FontInfo.bools.length; + let boolByte = 0, boolBit = 0; + for (let i = 0; i < numBools; i++) { + const value = font[_FontInfo.bools[i]]; + const bits = value === void 0 ? 0 : value ? 2 : 1; + boolByte |= bits << boolBit; + boolBit += 2; + if (boolBit === 8 || i === numBools - 1) { + view.setUint8(offset++, boolByte); + boolByte = 0; + boolBit = 0; + } + } + assert3(offset === _FontInfo.#OFFSET_NUMBERS, "FontInfo.write: Boolean properties offset mismatch"); + for (const prop of _FontInfo.numbers) { + view.setFloat64(offset, font[prop]); + offset += 8; + } + assert3(offset === _FontInfo.#OFFSET_BBOX, "FontInfo.write: Number properties offset mismatch"); + if (font.bbox) { + view.setUint8(offset++, 4); + for (const coord of font.bbox) { + view.setInt16(offset, coord, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 2 * 4; + } + assert3(offset === _FontInfo.#OFFSET_FONT_MATRIX, "FontInfo.write: BBox properties offset mismatch"); + if (font.fontMatrix) { + view.setUint8(offset++, 6); + for (const point2 of font.fontMatrix) { + view.setFloat64(offset, point2, true); + offset += 8; + } + } else { + view.setUint8(offset++, 0); + offset += 8 * 6; + } + assert3(offset === _FontInfo.#OFFSET_DEFAULT_VMETRICS, "FontInfo.write: FontMatrix properties offset mismatch"); + if (font.defaultVMetrics) { + view.setUint8(offset++, 1); + for (const metric of font.defaultVMetrics) { + view.setInt16(offset, metric, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 3 * 2; + } + assert3(offset === _FontInfo.#OFFSET_STRINGS, "FontInfo.write: DefaultVMetrics properties offset mismatch"); + view.setUint32(_FontInfo.#OFFSET_STRINGS, 0); + offset += 4; + for (const prop of _FontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(_FontInfo.#OFFSET_STRINGS, offset - _FontInfo.#OFFSET_STRINGS - 4); + if (!systemFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = systemFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert3(offset + 4 + length <= buffer2.byteLength, "FontInfo.write: Buffer overflow at systemFontInfo"); + data.set(new Uint8Array(systemFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (!cssFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = cssFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert3(offset + 4 + length <= buffer2.byteLength, "FontInfo.write: Buffer overflow at cssFontInfo"); + data.set(new Uint8Array(cssFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (font.data === void 0) { + view.setUint32(offset, 0); + offset += 4; + } else { + view.setUint32(offset, font.data.length); + data.set(font.data, offset + 4); + offset += 4 + font.data.length; + } + assert3(offset <= buffer2.byteLength, "FontInfo.write: Buffer overflow"); + return buffer2.transferToFixedLength(offset); + } + }; + NORMAL = { + style: "normal", + weight: "normal" + }; + BOLD = { + style: "normal", + weight: "bold" + }; + ITALIC = { + style: "italic", + weight: "normal" + }; + BOLDITALIC = { + style: "italic", + weight: "bold" + }; + substitutionMap = /* @__PURE__ */ new Map([["Times-Roman", { + local: ["Times New Roman", "Times-Roman", "Times", "Liberation Serif", "Nimbus Roman", "Nimbus Roman L", "Tinos", "Thorndale", "TeX Gyre Termes", "FreeSerif", "Linux Libertine O", "Libertinus Serif", "DejaVu Serif", "Bitstream Vera Serif", "Ubuntu"], + style: NORMAL, + ultimate: "serif" + }], ["Times-Bold", { + alias: "Times-Roman", + style: BOLD, + ultimate: "serif" + }], ["Times-Italic", { + alias: "Times-Roman", + style: ITALIC, + ultimate: "serif" + }], ["Times-BoldItalic", { + alias: "Times-Roman", + style: BOLDITALIC, + ultimate: "serif" + }], ["Helvetica", { + local: ["Helvetica", "Helvetica Neue", "Arial", "Arial Nova", "Liberation Sans", "Arimo", "Nimbus Sans", "Nimbus Sans L", "A030", "TeX Gyre Heros", "FreeSans", "DejaVu Sans", "Albany", "Bitstream Vera Sans", "Arial Unicode MS", "Microsoft Sans Serif", "Apple Symbols", "Cantarell"], + path: "LiberationSans-Regular.ttf", + style: NORMAL, + ultimate: "sans-serif" + }], ["Helvetica-Bold", { + alias: "Helvetica", + path: "LiberationSans-Bold.ttf", + style: BOLD, + ultimate: "sans-serif" + }], ["Helvetica-Oblique", { + alias: "Helvetica", + path: "LiberationSans-Italic.ttf", + style: ITALIC, + ultimate: "sans-serif" + }], ["Helvetica-BoldOblique", { + alias: "Helvetica", + path: "LiberationSans-BoldItalic.ttf", + style: BOLDITALIC, + ultimate: "sans-serif" + }], ["Courier", { + local: ["Courier", "Courier New", "Liberation Mono", "Nimbus Mono", "Nimbus Mono L", "Cousine", "Cumberland", "TeX Gyre Cursor", "FreeMono", "Linux Libertine Mono O", "Libertinus Mono"], + style: NORMAL, + ultimate: "monospace" + }], ["Courier-Bold", { + alias: "Courier", + style: BOLD, + ultimate: "monospace" + }], ["Courier-Oblique", { + alias: "Courier", + style: ITALIC, + ultimate: "monospace" + }], ["Courier-BoldOblique", { + alias: "Courier", + style: BOLDITALIC, + ultimate: "monospace" + }], ["ArialBlack", { + local: ["Arial Black"], + style: { + style: "normal", + weight: "900" + }, + fallback: "Helvetica-Bold" + }], ["ArialBlack-Bold", { + alias: "ArialBlack" + }], ["ArialBlack-Italic", { + alias: "ArialBlack", + style: { + style: "italic", + weight: "900" + }, + fallback: "Helvetica-BoldOblique" + }], ["ArialBlack-BoldItalic", { + alias: "ArialBlack-Italic" + }], ["ArialNarrow", { + local: ["Arial Narrow", "Liberation Sans Narrow", "Helvetica Condensed", "Nimbus Sans Narrow", "TeX Gyre Heros Cn"], + style: NORMAL, + fallback: "Helvetica" + }], ["ArialNarrow-Bold", { + alias: "ArialNarrow", + style: BOLD, + fallback: "Helvetica-Bold" + }], ["ArialNarrow-Italic", { + alias: "ArialNarrow", + style: ITALIC, + fallback: "Helvetica-Oblique" + }], ["ArialNarrow-BoldItalic", { + alias: "ArialNarrow", + style: BOLDITALIC, + fallback: "Helvetica-BoldOblique" + }], ["Calibri", { + local: ["Calibri", "Carlito"], + style: NORMAL, + fallback: "Helvetica" + }], ["Calibri-Bold", { + alias: "Calibri", + style: BOLD, + fallback: "Helvetica-Bold" + }], ["Calibri-Italic", { + alias: "Calibri", + style: ITALIC, + fallback: "Helvetica-Oblique" + }], ["Calibri-BoldItalic", { + alias: "Calibri", + style: BOLDITALIC, + fallback: "Helvetica-BoldOblique" + }], ["Wingdings", { + local: ["Wingdings", "URW Dingbats"], + style: NORMAL + }], ["Wingdings-Regular", { + alias: "Wingdings" + }], ["Wingdings-Bold", { + alias: "Wingdings" + }]]); + fontAliases = /* @__PURE__ */ new Map([["Arial-Black", "ArialBlack"]]); + SEED2 = 3285377520; + MASK_HIGH2 = 4294901760; + MASK_LOW2 = 65535; + MurmurHash3_642 = class { + constructor(seed) { + this.h1 = seed ? seed & 4294967295 : SEED2; + this.h2 = seed ? seed & 4294967295 : SEED2; + } + update(input2) { + let data, length; + if (typeof input2 === "string") { + data = new Uint8Array(input2.length * 2); + length = 0; + for (let i = 0, ii = input2.length; i < ii; i++) { + const code = input2.charCodeAt(i); + if (code <= 255) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 255; + } + } + } else if (ArrayBuffer.isView(input2)) { + data = input2.slice(); + length = data.byteLength; + } else { + throw new Error("Invalid data format, must be a string or TypedArray."); + } + const blockCounts = length >> 2; + const tailLength = length - blockCounts * 4; + const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); + let k1 = 0, k2 = 0; + let h1 = this.h1, h2 = this.h2; + const C1 = 3432918353, C2 = 461845907; + const C1_LOW = C1 & MASK_LOW2, C2_LOW = C2 & MASK_LOW2; + for (let i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH2 | k1 * C1_LOW & MASK_LOW2; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH2 | k1 * C2_LOW & MASK_LOW2; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 3864292196; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH2 | k2 * C1_LOW & MASK_LOW2; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH2 | k2 * C2_LOW & MASK_LOW2; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 3864292196; + } + } + k1 = 0; + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH2 | k1 * C1_LOW & MASK_LOW2; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH2 | k1 * C2_LOW & MASK_LOW2; + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + this.h1 = h1; + this.h2 = h2; + } + hexdigest() { + let h1 = this.h1, h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 3981806797 & MASK_HIGH2 | h1 * 36045 & MASK_LOW2; + h2 = h2 * 4283543511 & MASK_HIGH2 | ((h2 << 16 | h1 >>> 16) * 2950163797 & MASK_HIGH2) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 444984403 & MASK_HIGH2 | h1 * 60499 & MASK_LOW2; + h2 = h2 * 3301882366 & MASK_HIGH2 | ((h2 << 16 | h1 >>> 16) * 3120437893 & MASK_HIGH2) >>> 16; + h1 ^= h2 >>> 1; + return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0"); + } + }; + PDFImage = class _PDFImage { + constructor({ + xref, + res, + image, + isInline = false, + smask = null, + mask = null, + isMask = false, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }) { + this.image = image; + const dict = image.dict; + const filter2 = dict.get("F", "Filter"); + let filterName; + if (filter2 instanceof Name2) { + filterName = filter2.name; + } else if (Array.isArray(filter2)) { + const filterZero = xref.fetchIfRef(filter2[0]); + if (filterZero instanceof Name2) { + filterName = filterZero.name; + } + } + switch (filterName) { + case "JPXDecode": + ({ + width: image.width, + height: image.height, + componentsCount: image.numComps, + bitsPerComponent: image.bitsPerComponent + } = JpxImage.parseImageProperties(image.stream)); + image.stream.reset(); + const reducePower = ImageResizer.getReducePowerForJPX(image.width, image.height, image.numComps); + this.jpxDecoderOptions = { + numComponents: 0, + isIndexedColormap: false, + smaskInData: dict.has("SMaskInData"), + reducePower + }; + if (reducePower) { + const factor = 2 ** reducePower; + image.width = Math.ceil(image.width / factor); + image.height = Math.ceil(image.height / factor); + } + break; + case "JBIG2Decode": + image.bitsPerComponent = 1; + image.numComps = 1; + break; + } + let width = dict.get("W", "Width"); + let height = dict.get("H", "Height"); + if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) { + warn2("PDFImage - using the Width/Height of the image data, rather than the image dictionary."); + width = image.width; + height = image.height; + } else { + const validWidth = typeof width === "number" && width > 0, validHeight = typeof height === "number" && height > 0; + if (!validWidth || !validHeight) { + if (!image.fallbackDims) { + throw new FormatError3(`Invalid image width: ${width} or height: ${height}`); + } + warn2("PDFImage - using the Width/Height of the parent image, for SMask/Mask data."); + if (!validWidth) { + width = image.fallbackDims.width; + } + if (!validHeight) { + height = image.fallbackDims.height; + } + } + } + this.width = width; + this.height = height; + this.interpolate = dict.get("I", "Interpolate"); + this.imageMask = dict.get("IM", "ImageMask") || false; + this.matte = dict.get("Matte") || false; + let bitsPerComponent = image.bitsPerComponent; + if (!bitsPerComponent) { + bitsPerComponent = dict.get("BPC", "BitsPerComponent"); + if (!bitsPerComponent) { + if (this.imageMask) { + bitsPerComponent = 1; + } else { + throw new FormatError3(`Bits per component missing in image: ${this.imageMask}`); + } + } + } + this.bpc = bitsPerComponent; + if (!this.imageMask) { + let colorSpace = dict.getRaw("CS") || dict.getRaw("ColorSpace"); + const hasColorSpace = !!colorSpace; + if (!hasColorSpace) { + if (this.jpxDecoderOptions) { + colorSpace = Name2.get("DeviceRGBA"); + } else { + switch (image.numComps) { + case 1: + colorSpace = Name2.get("DeviceGray"); + break; + case 3: + colorSpace = Name2.get("DeviceRGB"); + break; + case 4: + colorSpace = Name2.get("DeviceCMYK"); + break; + default: + throw new Error(`Images with ${image.numComps} color components not supported.`); + } + } + } else if (this.jpxDecoderOptions?.smaskInData) { + colorSpace = Name2.get("DeviceRGBA"); + } + this.colorSpace = ColorSpaceUtils.parse({ + cs: colorSpace, + xref, + resources: isInline ? res : null, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + this.numComps = this.colorSpace.numComps; + if (this.jpxDecoderOptions) { + this.jpxDecoderOptions.numComponents = hasColorSpace ? this.numComps : 0; + this.jpxDecoderOptions.isIndexedColormap = this.colorSpace.name === "Indexed"; + } + } + this.decode = dict.getArray("D", "Decode"); + this.needsDecode = false; + if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !ColorSpace.isDefaultDecode(this.decode, 1))) { + this.needsDecode = true; + const max2 = (1 << bitsPerComponent) - 1; + this.decodeCoefficients = []; + this.decodeAddends = []; + const isIndexed = this.colorSpace?.name === "Indexed"; + for (let i = 0, j = 0; i < this.decode.length; i += 2, ++j) { + const dmin = this.decode[i]; + const dmax = this.decode[i + 1]; + this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max2 : dmax - dmin; + this.decodeAddends[j] = isIndexed ? dmin : max2 * dmin; + } + } + if (smask) { + smask.fallbackDims ??= { + width, + height + }; + this.smask = new _PDFImage({ + xref, + res, + image: smask, + isInline, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } else if (mask) { + if (mask instanceof BaseStream) { + const maskDict = mask.dict, imageMask = maskDict.get("IM", "ImageMask"); + if (!imageMask) { + warn2("Ignoring /Mask in image without /ImageMask."); + } else { + mask.fallbackDims ??= { + width, + height + }; + this.mask = new _PDFImage({ + xref, + res, + image: mask, + isInline, + isMask: true, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } + } else { + this.mask = mask; + } + } + } + static async buildImage({ + xref, + res, + image, + isInline = false, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }) { + const imageData = image; + let smaskData = null; + let maskData = null; + const smask = image.dict.get("SMask"); + const mask = image.dict.get("Mask"); + if (smask) { + if (smask instanceof BaseStream) { + smaskData = smask; + } else { + warn2("Unsupported /SMask format."); + } + } else if (mask) { + if (mask instanceof BaseStream || Array.isArray(mask)) { + maskData = mask; + } else { + warn2("Unsupported /Mask format."); + } + } + return new _PDFImage({ + xref, + res, + image: imageData, + isInline, + smask: smaskData, + mask: maskData, + pdfFunctionFactory, + globalColorSpaceCache, + localColorSpaceCache + }); + } + static async createMask({ + image, + isOffscreenCanvasSupported = false + }) { + const { + dict + } = image; + const width = dict.get("W", "Width"); + const height = dict.get("H", "Height"); + const interpolate = dict.get("I", "Interpolate"); + const decode4 = dict.getArray("D", "Decode"); + const inverseDecode = decode4?.[0] > 0; + const computedLength = (width + 7 >> 3) * height; + const imgArray = image.getBytes(computedLength); + const isSingleOpaquePixel = width === 1 && height === 1 && inverseDecode === (imgArray.length === 0 || !!(imgArray[0] & 128)); + if (isSingleOpaquePixel) { + return { + isSingleOpaquePixel + }; + } + if (isOffscreenCanvasSupported) { + if (ImageResizer.needsToBeResized(width, height)) { + const data2 = new Uint8ClampedArray(width * height * 4); + convertBlackAndWhiteToRGBA2({ + src: imgArray, + dest: data2, + width, + height, + nonBlackColor: 0, + inverseDecode + }); + return ImageResizer.createImage({ + kind: ImageKind2.RGBA_32BPP, + data: data2, + width, + height, + interpolate + }); + } + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + const imgData = ctx.createImageData(width, height); + convertBlackAndWhiteToRGBA2({ + src: imgArray, + dest: imgData.data, + width, + height, + nonBlackColor: 0, + inverseDecode + }); + ctx.putImageData(imgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width, + height, + interpolate, + bitmap + }; + } + const actualLength = imgArray.byteLength; + const haveFullData = computedLength === actualLength; + let data; + if (image instanceof DecodeStream && (!inverseDecode || haveFullData)) { + data = imgArray; + } else if (!inverseDecode) { + data = new Uint8Array(imgArray); + } else { + data = new Uint8Array(computedLength); + data.set(imgArray); + data.fill(255, actualLength); + } + if (inverseDecode) { + for (let i = 0; i < actualLength; i++) { + data[i] ^= 255; + } + } + return { + data, + width, + height, + interpolate + }; + } + get drawWidth() { + return Math.max(this.width, this.smask?.width || 0, this.mask?.width || 0); + } + get drawHeight() { + return Math.max(this.height, this.smask?.height || 0, this.mask?.height || 0); + } + decodeBuffer(buffer2) { + const bpc = this.bpc; + const numComps = this.numComps; + const decodeAddends = this.decodeAddends; + const decodeCoefficients = this.decodeCoefficients; + const max2 = (1 << bpc) - 1; + let i, ii; + if (bpc === 1) { + for (i = 0, ii = buffer2.length; i < ii; i++) { + buffer2[i] = +!buffer2[i]; + } + return; + } + let index2 = 0; + for (i = 0, ii = this.width * this.height; i < ii; i++) { + for (let j = 0; j < numComps; j++) { + buffer2[index2] = MathClamp2(decodeAddends[j] + buffer2[index2] * decodeCoefficients[j], 0, max2); + index2++; + } + } + } + getComponents(buffer2) { + const bpc = this.bpc; + if (bpc === 8) { + return buffer2; + } + const width = this.width; + const height = this.height; + const numComps = this.numComps; + const length = width * height * numComps; + let bufferPos = 0; + let output2; + if (bpc <= 8) { + output2 = new Uint8Array(length); + } else if (bpc <= 16) { + output2 = new Uint16Array(length); + } else { + output2 = new Uint32Array(length); + } + const rowComps = width * numComps; + const max2 = (1 << bpc) - 1; + let i = 0, ii, buf; + if (bpc === 1) { + let mask, loop1End, loop2End; + for (let j = 0; j < height; j++) { + loop1End = i + (rowComps & ~7); + loop2End = i + rowComps; + while (i < loop1End) { + buf = buffer2[bufferPos++]; + output2[i] = buf >> 7 & 1; + output2[i + 1] = buf >> 6 & 1; + output2[i + 2] = buf >> 5 & 1; + output2[i + 3] = buf >> 4 & 1; + output2[i + 4] = buf >> 3 & 1; + output2[i + 5] = buf >> 2 & 1; + output2[i + 6] = buf >> 1 & 1; + output2[i + 7] = buf & 1; + i += 8; + } + if (i < loop2End) { + buf = buffer2[bufferPos++]; + mask = 128; + while (i < loop2End) { + output2[i++] = +!!(buf & mask); + mask >>= 1; + } + } + } + } else { + let bits = 0; + buf = 0; + for (i = 0, ii = length; i < ii; ++i) { + if (i % rowComps === 0) { + buf = 0; + bits = 0; + } + while (bits < bpc) { + buf = buf << 8 | buffer2[bufferPos++]; + bits += 8; + } + const remainingBits = bits - bpc; + let value = buf >> remainingBits; + if (value < 0) { + value = 0; + } else if (value > max2) { + value = max2; + } + output2[i] = value; + buf &= (1 << remainingBits) - 1; + bits = remainingBits; + } + } + return output2; + } + async fillOpacity(rgbaBuf, width, height, actualHeight, image) { + const smask = this.smask; + const mask = this.mask; + let alphaBuf, sw, sh, i, ii, j; + if (smask) { + sw = smask.width; + sh = smask.height; + alphaBuf = new Uint8ClampedArray(sw * sh); + await smask.fillGrayBuffer(alphaBuf); + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height); + } + } else if (mask) { + if (mask instanceof _PDFImage) { + sw = mask.width; + sh = mask.height; + alphaBuf = new Uint8ClampedArray(sw * sh); + mask.numComps = 1; + await mask.fillGrayBuffer(alphaBuf); + for (i = 0, ii = sw * sh; i < ii; ++i) { + alphaBuf[i] = 255 - alphaBuf[i]; + } + if (sw !== width || sh !== height) { + alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height); + } + } else if (Array.isArray(mask)) { + alphaBuf = new Uint8ClampedArray(width * height); + const numComps = this.numComps; + for (i = 0, ii = width * height; i < ii; ++i) { + let opacity = 0; + const imageOffset = i * numComps; + for (j = 0; j < numComps; ++j) { + const color = image[imageOffset + j]; + const maskOffset = j * 2; + if (color < mask[maskOffset] || color > mask[maskOffset + 1]) { + opacity = 255; + break; + } + } + alphaBuf[i] = opacity; + } + } else { + throw new FormatError3("Unknown mask format."); + } + } + if (alphaBuf) { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = alphaBuf[i]; + } + } else { + for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) { + rgbaBuf[j] = 255; + } + } + } + undoPreblend(buffer2, width, height) { + const matte = this.smask?.matte; + if (!matte) { + return; + } + const matteRgb = this.colorSpace.getRgb(matte, 0); + const matteR = matteRgb[0]; + const matteG = matteRgb[1]; + const matteB = matteRgb[2]; + const length = width * height * 4; + for (let i = 0; i < length; i += 4) { + const alpha = buffer2[i + 3]; + if (alpha === 0) { + buffer2[i] = 255; + buffer2[i + 1] = 255; + buffer2[i + 2] = 255; + continue; + } + const k = 255 / alpha; + buffer2[i] = (buffer2[i] - matteR) * k + matteR; + buffer2[i + 1] = (buffer2[i + 1] - matteG) * k + matteG; + buffer2[i + 2] = (buffer2[i + 2] - matteB) * k + matteB; + } + } + async createImageData(forceRGBA = false, isOffscreenCanvasSupported = false) { + const drawWidth = this.drawWidth; + const drawHeight = this.drawHeight; + const imgData = { + width: drawWidth, + height: drawHeight, + interpolate: this.interpolate, + kind: 0, + data: null + }; + const numComps = this.numComps; + const originalWidth = this.width; + const originalHeight = this.height; + const bpc = this.bpc; + const rowBytes = originalWidth * numComps * bpc + 7 >> 3; + const mustBeResized = isOffscreenCanvasSupported && ImageResizer.needsToBeResized(drawWidth, drawHeight); + if (!this.smask && !this.mask && this.colorSpace.name === "DeviceRGBA") { + imgData.kind = ImageKind2.RGBA_32BPP; + const imgArray2 = imgData.data = await this.getImageBytes(originalHeight * originalWidth * 4, {}); + if (isOffscreenCanvasSupported) { + if (!mustBeResized) { + return this.createBitmap(ImageKind2.RGBA_32BPP, drawWidth, drawHeight, imgArray2); + } + return ImageResizer.createImage(imgData, false); + } + return imgData; + } + if (!forceRGBA) { + let kind; + if (this.colorSpace.name === "DeviceGray" && bpc === 1) { + kind = ImageKind2.GRAYSCALE_1BPP; + } else if (this.colorSpace.name === "DeviceRGB" && bpc === 8 && !this.needsDecode) { + kind = ImageKind2.RGB_24BPP; + } + if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) { + const image = await this.#getImage(originalWidth, originalHeight); + if (image) { + return image; + } + const data2 = await this.getImageBytes(originalHeight * rowBytes, {}); + if (isOffscreenCanvasSupported) { + if (mustBeResized) { + return ImageResizer.createImage({ + data: data2, + kind, + width: drawWidth, + height: drawHeight, + interpolate: this.interpolate + }, this.needsDecode); + } + return this.createBitmap(kind, originalWidth, originalHeight, data2); + } + imgData.kind = kind; + imgData.data = data2; + if (this.needsDecode) { + assert3(kind === ImageKind2.GRAYSCALE_1BPP, "PDFImage.createImageData: The image must be grayscale."); + const buffer2 = imgData.data; + for (let i = 0, ii = buffer2.length; i < ii; i++) { + buffer2[i] ^= 255; + } + } + return imgData; + } + if (this.image instanceof JpegStream && !this.smask && !this.mask && !this.needsDecode) { + let imageLength = originalHeight * rowBytes; + if (isOffscreenCanvasSupported && !mustBeResized) { + let isHandled = false; + switch (this.colorSpace.name) { + case "DeviceGray": + imageLength *= 4; + isHandled = true; + break; + case "DeviceRGB": + imageLength = imageLength / 3 * 4; + isHandled = true; + break; + case "DeviceCMYK": + isHandled = true; + break; + } + if (isHandled) { + const image = await this.#getImage(drawWidth, drawHeight); + if (image) { + return image; + } + const rgba = await this.getImageBytes(imageLength, { + drawWidth, + drawHeight, + forceRGBA: true + }); + return this.createBitmap(ImageKind2.RGBA_32BPP, drawWidth, drawHeight, rgba); + } + } else { + switch (this.colorSpace.name) { + case "DeviceGray": + imageLength *= 3; + case "DeviceRGB": + case "DeviceCMYK": + imgData.kind = ImageKind2.RGB_24BPP; + imgData.data = await this.getImageBytes(imageLength, { + drawWidth, + drawHeight, + forceRGB: true + }); + if (mustBeResized) { + return ImageResizer.createImage(imgData); + } + return imgData; + } + } + } + } + const imgArray = await this.getImageBytes(originalHeight * rowBytes, { + internal: true + }); + const actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight; + const comps = this.getComponents(imgArray); + let alpha01, maybeUndoPreblend; + let canvas, ctx, canvasImgData, data; + if (isOffscreenCanvasSupported && !mustBeResized) { + canvas = new OffscreenCanvas(drawWidth, drawHeight); + ctx = canvas.getContext("2d"); + canvasImgData = ctx.createImageData(drawWidth, drawHeight); + data = canvasImgData.data; + } + imgData.kind = ImageKind2.RGBA_32BPP; + if (!forceRGBA && !this.smask && !this.mask) { + if (!isOffscreenCanvasSupported || mustBeResized) { + imgData.kind = ImageKind2.RGB_24BPP; + data = new Uint8ClampedArray(drawWidth * drawHeight * 3); + alpha01 = 0; + } else { + const arr = new Uint32Array(data.buffer); + arr.fill(FeatureTest2.isLittleEndian ? 4278190080 : 255); + alpha01 = 1; + } + maybeUndoPreblend = false; + } else { + if (!isOffscreenCanvasSupported || mustBeResized) { + data = new Uint8ClampedArray(drawWidth * drawHeight * 4); + } + alpha01 = 1; + maybeUndoPreblend = true; + await this.fillOpacity(data, drawWidth, drawHeight, actualHeight, comps); + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + this.colorSpace.fillRgb(data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01); + if (maybeUndoPreblend) { + this.undoPreblend(data, drawWidth, actualHeight); + } + if (isOffscreenCanvasSupported && !mustBeResized) { + ctx.putImageData(canvasImgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width: drawWidth, + height: drawHeight, + bitmap, + interpolate: this.interpolate + }; + } + imgData.data = data; + if (mustBeResized) { + return ImageResizer.createImage(imgData); + } + return imgData; + } + async fillGrayBuffer(buffer2) { + const numComps = this.numComps; + if (numComps !== 1) { + throw new FormatError3(`Reading gray scale from a color image: ${numComps}`); + } + const width = this.width; + const height = this.height; + const bpc = this.bpc; + const rowBytes = width * numComps * bpc + 7 >> 3; + const imgArray = await this.getImageBytes(height * rowBytes, { + internal: true + }); + const comps = this.getComponents(imgArray); + let i, length; + if (bpc === 1) { + length = width * height; + if (this.needsDecode) { + for (i = 0; i < length; ++i) { + buffer2[i] = comps[i] - 1 & 255; + } + } else { + for (i = 0; i < length; ++i) { + buffer2[i] = -comps[i] & 255; + } + } + return; + } + if (this.needsDecode) { + this.decodeBuffer(comps); + } + length = width * height; + const scale = 255 / ((1 << bpc) - 1); + for (i = 0; i < length; ++i) { + buffer2[i] = scale * comps[i]; + } + } + createBitmap(kind, width, height, src) { + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d"); + let imgData; + if (kind === ImageKind2.RGBA_32BPP) { + imgData = new ImageData(src, width, height); + } else { + imgData = ctx.createImageData(width, height); + convertToRGBA({ + kind, + src, + dest: new Uint32Array(imgData.data.buffer), + width, + height, + inverseDecode: this.needsDecode + }); + } + ctx.putImageData(imgData, 0, 0); + const bitmap = canvas.transferToImageBitmap(); + return { + data: null, + width, + height, + bitmap, + interpolate: this.interpolate + }; + } + async #getImage(width, height) { + const bitmap = await this.image.getTransferableImage(); + if (!bitmap) { + return null; + } + return { + data: null, + width, + height, + bitmap, + interpolate: this.interpolate + }; + } + async getImageBytes(length, { + drawWidth, + drawHeight, + forceRGBA = false, + forceRGB = false, + internal = false + }) { + this.image.reset(); + this.image.drawWidth = drawWidth || this.width; + this.image.drawHeight = drawHeight || this.height; + this.image.forceRGBA = !!forceRGBA; + this.image.forceRGB = !!forceRGB; + const imageBytes = await this.image.getImageData(length, this.jpxDecoderOptions); + if (internal || this.image instanceof DecodeStream) { + return imageBytes; + } + assert3(imageBytes instanceof Uint8Array, 'PDFImage.getImageBytes: Unsupported "imageBytes" type.'); + return new Uint8Array(imageBytes); + } + }; + DefaultPartialEvaluatorOptions = Object.freeze({ + maxImageSize: -1, + disableFontFace: false, + ignoreErrors: false, + isEvalSupported: true, + isOffscreenCanvasSupported: false, + isImageDecoderSupported: false, + canvasMaxAreaInBytes: -1, + fontExtraProperties: false, + useSystemFonts: true, + useWasm: true, + useWorkerFetch: true, + cMapUrl: null, + iccUrl: null, + standardFontDataUrl: null, + wasmUrl: null + }); + PatternType = { + TILING: 1, + SHADING: 2 + }; + TEXT_CHUNK_BATCH_SIZE = 10; + deferred = Promise.resolve(); + TimeSlotManager = class _TimeSlotManager { + static TIME_SLOT_DURATION_MS = 20; + static CHECK_TIME_EVERY = 100; + constructor() { + this.reset(); + } + check() { + if (++this.checked < _TimeSlotManager.CHECK_TIME_EVERY) { + return false; + } + this.checked = 0; + return this.endTime <= Date.now(); + } + reset() { + this.endTime = Date.now() + _TimeSlotManager.TIME_SLOT_DURATION_MS; + this.checked = 0; + } + }; + PartialEvaluator = class _PartialEvaluator { + constructor({ + xref, + handler, + pageIndex, + idFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + globalColorSpaceCache, + globalImageCache, + systemFontCache, + options = null + }) { + this.xref = xref; + this.handler = handler; + this.pageIndex = pageIndex; + this.idFactory = idFactory; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.standardFontDataCache = standardFontDataCache; + this.globalColorSpaceCache = globalColorSpaceCache; + this.globalImageCache = globalImageCache; + this.systemFontCache = systemFontCache; + this.options = options || DefaultPartialEvaluatorOptions; + this.type3FontRefs = null; + this._regionalImageCache = new RegionalImageCache(); + this._fetchBuiltInCMapBound = this.fetchBuiltInCMap.bind(this); + } + get _pdfFunctionFactory() { + const pdfFunctionFactory = new PDFFunctionFactory({ + xref: this.xref, + isEvalSupported: this.options.isEvalSupported + }); + return shadow2(this, "_pdfFunctionFactory", pdfFunctionFactory); + } + get parsingType3Font() { + return !!this.type3FontRefs; + } + clone(newOptions = null) { + const newEvaluator = Object.create(this); + newEvaluator.options = Object.assign(/* @__PURE__ */ Object.create(null), this.options, newOptions); + return newEvaluator; + } + hasBlendModes(resources, nonBlendModesSet) { + if (!(resources instanceof Dict)) { + return false; + } + if (resources.objId && nonBlendModesSet.has(resources.objId)) { + return false; + } + const processed = new RefSet(nonBlendModesSet); + if (resources.objId) { + processed.put(resources.objId); + } + const nodes = [resources], xref = this.xref; + while (nodes.length) { + const node2 = nodes.shift(); + const graphicStates = node2.get("ExtGState"); + if (graphicStates instanceof Dict) { + for (let graphicState of graphicStates.getRawValues()) { + if (graphicState instanceof Ref) { + if (processed.has(graphicState)) { + continue; + } + try { + graphicState = xref.fetch(graphicState); + } catch (ex) { + processed.put(graphicState); + info2(`hasBlendModes - ignoring ExtGState: "${ex}".`); + continue; + } + } + if (!(graphicState instanceof Dict)) { + continue; + } + if (graphicState.objId) { + processed.put(graphicState.objId); + } + const bm = graphicState.get("BM"); + if (bm instanceof Name2) { + if (bm.name !== "Normal") { + return true; + } + continue; + } + if (bm !== void 0 && Array.isArray(bm)) { + for (const element of bm) { + if (element instanceof Name2 && element.name !== "Normal") { + return true; + } + } + } + } + } + const xObjects = node2.get("XObject"); + if (!(xObjects instanceof Dict)) { + continue; + } + for (let xObject of xObjects.getRawValues()) { + if (xObject instanceof Ref) { + if (processed.has(xObject)) { + continue; + } + try { + xObject = xref.fetch(xObject); + } catch (ex) { + processed.put(xObject); + info2(`hasBlendModes - ignoring XObject: "${ex}".`); + continue; + } + } + if (!(xObject instanceof BaseStream)) { + continue; + } + if (xObject.dict.objId) { + processed.put(xObject.dict.objId); + } + const xResources = xObject.dict.get("Resources"); + if (!(xResources instanceof Dict)) { + continue; + } + if (xResources.objId && processed.has(xResources.objId)) { + continue; + } + nodes.push(xResources); + if (xResources.objId) { + processed.put(xResources.objId); + } + } + } + for (const ref of processed) { + nonBlendModesSet.put(ref); + } + return false; + } + async fetchBuiltInCMap(name) { + const cachedData = this.builtInCMapCache.get(name); + if (cachedData) { + return cachedData; + } + let data; + if (this.options.useWorkerFetch) { + data = { + cMapData: await fetchBinaryData(`${this.options.cMapUrl}${name}.bcmap`), + isCompressed: true + }; + } else { + data = await this.handler.sendWithPromise("FetchBinaryData", { + type: "cMapReaderFactory", + name + }); + } + this.builtInCMapCache.set(name, data); + return data; + } + async fetchStandardFontData(name) { + const cachedData = this.standardFontDataCache.get(name); + if (cachedData) { + return new Stream3(cachedData); + } + if (this.options.useSystemFonts && name !== "Symbol" && name !== "ZapfDingbats") { + return null; + } + const standardFontNameToFileName = getFontNameToFileMap(), filename = standardFontNameToFileName[name]; + let data; + try { + if (this.options.useWorkerFetch) { + data = await fetchBinaryData(`${this.options.standardFontDataUrl}${filename}`); + } else { + data = await this.handler.sendWithPromise("FetchBinaryData", { + type: "standardFontDataFactory", + filename + }); + } + } catch (ex) { + warn2(ex); + return null; + } + this.standardFontDataCache.set(name, data); + return new Stream3(data); + } + async buildFormXObject(resources, xobj, smask, operatorList, task, initialState, localColorSpaceCache, seenRefs) { + const { + dict + } = xobj; + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + const bbox = lookupNormalRect(dict.getArray("BBox"), null); + let optionalContent, groupOptions; + if (dict.has("OC")) { + optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); + } + if (optionalContent !== void 0) { + operatorList.addOp(OPS2.beginMarkedContentProps, ["OC", optionalContent]); + } + const group2 = dict.get("Group"); + if (group2) { + groupOptions = { + matrix, + bbox, + smask, + isolated: false, + knockout: false + }; + const groupSubtype = group2.get("S"); + let colorSpace = null; + if (isName(groupSubtype, "Transparency")) { + groupOptions.isolated = group2.get("I") || false; + groupOptions.knockout = group2.get("K") || false; + if (group2.has("CS")) { + const cs = this._getColorSpace(group2.getRaw("CS"), resources, localColorSpaceCache); + colorSpace = cs instanceof ColorSpace ? cs : await this._handleColorSpace(cs); + } + } + if (smask?.backdrop) { + colorSpace ||= ColorSpaceUtils.rgb; + smask.backdrop = colorSpace.getRgbHex(smask.backdrop, 0); + } + operatorList.addOp(OPS2.beginGroup, [groupOptions]); + } + const f32matrix = matrix && new Float32Array(matrix); + const f32bbox = !group2 && bbox && new Float32Array(bbox) || null; + const args = [f32matrix, f32bbox]; + operatorList.addOp(OPS2.paintFormXObjectBegin, args); + const localResources = dict.get("Resources"); + await this.getOperatorList({ + stream: xobj, + task, + resources: localResources instanceof Dict ? localResources : resources, + operatorList, + initialState, + prevRefs: seenRefs + }); + operatorList.addOp(OPS2.paintFormXObjectEnd, []); + if (group2) { + operatorList.addOp(OPS2.endGroup, [groupOptions]); + } + if (optionalContent !== void 0) { + operatorList.addOp(OPS2.endMarkedContent, []); + } + } + _sendImgData(objId, imgData, cacheGlobally = false) { + const transfers = imgData ? [imgData.bitmap || imgData.data.buffer] : null; + if (this.parsingType3Font || cacheGlobally) { + return this.handler.send("commonobj", [objId, "Image", imgData], transfers); + } + return this.handler.send("obj", [objId, this.pageIndex, "Image", imgData], transfers); + } + async buildPaintImageXObject({ + resources, + image, + isInline = false, + operatorList, + cacheKey, + localImageCache, + localColorSpaceCache + }) { + const { + maxImageSize, + ignoreErrors, + isOffscreenCanvasSupported + } = this.options; + const { + dict + } = image; + const imageRef = dict.objId; + const w = dict.get("W", "Width"); + const h = dict.get("H", "Height"); + if (!(w && typeof w === "number") || !(h && typeof h === "number")) { + warn2("Image dimensions are missing, or not numbers."); + return; + } + if (maxImageSize !== -1 && w * h > maxImageSize) { + const msg = "Image exceeded maximum allowed size and was removed."; + if (!ignoreErrors) { + throw new Error(msg); + } + warn2(msg); + return; + } + let optionalContent; + if (dict.has("OC")) { + optionalContent = await this.parseMarkedContentProps(dict.get("OC"), resources); + } + const imageMask = dict.get("IM", "ImageMask") || false; + let imgData, fn, args; + if (imageMask) { + imgData = await PDFImage.createMask({ + image, + isOffscreenCanvasSupported: isOffscreenCanvasSupported && !this.parsingType3Font + }); + if (imgData.isSingleOpaquePixel) { + fn = OPS2.paintSolidColorImageMask; + args = []; + operatorList.addImageOps(fn, args, optionalContent); + if (cacheKey) { + const cacheData = { + fn, + args, + optionalContent + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + } + } + return; + } + if (this.parsingType3Font) { + args = compileType3Glyph(imgData); + if (args) { + operatorList.addImageOps(OPS2.constructPath, args, optionalContent); + return; + } + warn2("Cannot compile Type3 glyph."); + operatorList.addImageOps(OPS2.paintImageMaskXObject, [imgData], optionalContent); + return; + } + const objId2 = `mask_${this.idFactory.createObjId()}`; + operatorList.addDependency(objId2); + imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length; + this._sendImgData(objId2, imgData); + fn = OPS2.paintImageMaskXObject; + args = [{ + data: objId2, + width: imgData.width, + height: imgData.height, + interpolate: imgData.interpolate, + count: 1 + }]; + operatorList.addImageOps(fn, args, optionalContent); + if (cacheKey) { + const cacheData = { + objId: objId2, + fn, + args, + optionalContent + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + } + } + return; + } + const SMALL_IMAGE_DIMENSIONS = 200; + const hasMask = dict.has("SMask") || dict.has("Mask"); + if (isInline && w + h < SMALL_IMAGE_DIMENSIONS && !hasMask) { + try { + const imageObj = new PDFImage({ + xref: this.xref, + res: resources, + image, + isInline, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache + }); + imgData = await imageObj.createImageData(true, false); + operatorList.addImageOps(OPS2.paintInlineImageXObject, [imgData], optionalContent); + } catch (reason) { + const msg = `Unable to decode inline image: "${reason}".`; + if (!ignoreErrors) { + throw new Error(msg); + } + warn2(msg); + } + return; + } + let objId = `img_${this.idFactory.createObjId()}`, cacheGlobally = false, globalCacheData = null; + if (this.parsingType3Font) { + objId = `${this.idFactory.getDocId()}_type3_${objId}`; + } else if (cacheKey && imageRef) { + cacheGlobally = this.globalImageCache.shouldCache(imageRef, this.pageIndex); + if (cacheGlobally) { + assert3(!isInline, "Cannot cache an inline image globally."); + objId = `${this.idFactory.getDocId()}_${objId}`; + } + } + operatorList.addDependency(objId); + fn = OPS2.paintImageXObject; + args = [objId, w, h]; + operatorList.addImageOps(fn, args, optionalContent, hasMask); + if (cacheGlobally) { + globalCacheData = { + objId, + fn, + args, + optionalContent, + hasMask, + byteSize: 0 + }; + if (this.globalImageCache.hasDecodeFailed(imageRef)) { + this.globalImageCache.setData(imageRef, globalCacheData); + this._sendImgData(objId, null, cacheGlobally); + return; + } + if (w * h > 25e4 || hasMask) { + const localLength = await this.handler.sendWithPromise("commonobj", [objId, "CopyLocalImage", { + imageRef + }]); + if (localLength) { + this.globalImageCache.setData(imageRef, globalCacheData); + this.globalImageCache.addByteSize(imageRef, localLength); + return; + } + } + } + PDFImage.buildImage({ + xref: this.xref, + res: resources, + image, + isInline, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache + }).then(async (imageObj) => { + imgData = await imageObj.createImageData(false, isOffscreenCanvasSupported); + imgData.dataLen = imgData.bitmap ? imgData.width * imgData.height * 4 : imgData.data.length; + imgData.ref = imageRef; + if (cacheGlobally) { + this.globalImageCache.addByteSize(imageRef, imgData.dataLen); + } + return this._sendImgData(objId, imgData, cacheGlobally); + }).catch((reason) => { + warn2(`Unable to decode image "${objId}": "${reason}".`); + if (imageRef) { + this.globalImageCache.addDecodeFailed(imageRef); + } + return this._sendImgData(objId, null, cacheGlobally); + }); + if (cacheKey) { + const cacheData = { + objId, + fn, + args, + optionalContent, + hasMask + }; + localImageCache.set(cacheKey, imageRef, cacheData); + if (imageRef) { + this._regionalImageCache.set(null, imageRef, cacheData); + if (cacheGlobally) { + assert3(globalCacheData, "The global cache-data must be available."); + this.globalImageCache.setData(imageRef, globalCacheData); + } + } + } + } + handleSMask(smask, resources, operatorList, task, stateManager, localColorSpaceCache, seenRefs) { + const smaskContent = smask.get("G"); + const smaskOptions = { + subtype: smask.get("S").name, + backdrop: smask.get("BC") + }; + const transferObj = smask.get("TR"); + if (isPDFFunction(transferObj)) { + const transferFn = this._pdfFunctionFactory.create(transferObj); + const transferMap = new Uint8Array(256); + const tmp = new Float32Array(1); + for (let i = 0; i < 256; i++) { + tmp[0] = i / 255; + transferFn(tmp, 0, tmp, 0); + transferMap[i] = tmp[0] * 255 | 0; + } + smaskOptions.transferMap = transferMap; + } + return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone({ + newPath: true + }), localColorSpaceCache, seenRefs); + } + handleTransferFunction(tr) { + let transferArray; + if (Array.isArray(tr)) { + transferArray = tr; + } else if (isPDFFunction(tr)) { + transferArray = [tr]; + } else { + return null; + } + const transferMaps = []; + let numFns = 0, numEffectfulFns = 0; + for (const entry of transferArray) { + const transferObj = this.xref.fetchIfRef(entry); + numFns++; + if (isName(transferObj, "Identity")) { + transferMaps.push(null); + continue; + } else if (!isPDFFunction(transferObj)) { + return null; + } + const transferFn = this._pdfFunctionFactory.create(transferObj); + const transferMap = new Uint8Array(256), tmp = new Float32Array(1); + for (let j = 0; j < 256; j++) { + tmp[0] = j / 255; + transferFn(tmp, 0, tmp, 0); + transferMap[j] = tmp[0] * 255 | 0; + } + transferMaps.push(transferMap); + numEffectfulFns++; + } + if (!(numFns === 1 || numFns === 4)) { + return null; + } + if (numEffectfulFns === 0) { + return null; + } + return transferMaps; + } + handleTilingType(fn, color, resources, pattern, patternDict, operatorList, task, localTilingPatternCache) { + const tilingOpList = new OperatorList(); + const patternResources = Dict.merge({ + xref: this.xref, + dictArray: [patternDict.get("Resources"), resources] + }); + return this.getOperatorList({ + stream: pattern, + task, + resources: patternResources, + operatorList: tilingOpList + }).then(function() { + const operatorListIR = tilingOpList.getIR(); + const tilingPatternIR = getTilingPatternIR(operatorListIR, patternDict, color); + operatorList.addDependencies(tilingOpList.dependencies); + operatorList.addOp(fn, tilingPatternIR); + if (patternDict.objId) { + localTilingPatternCache.set(null, patternDict.objId, { + operatorListIR, + dict: patternDict + }); + } + }).catch((reason) => { + if (reason instanceof AbortException3) { + return; + } + if (this.options.ignoreErrors) { + warn2(`handleTilingType - ignoring pattern: "${reason}".`); + return; + } + throw reason; + }); + } + async handleSetFont(resources, fontArgs, fontRef, operatorList, task, state, fallbackFontDict = null, cssFontInfo = null) { + const fontName = fontArgs?.[0] instanceof Name2 ? fontArgs[0].name : null; + const translated = await this.loadFont(fontName, fontRef, resources, task, fallbackFontDict, cssFontInfo); + if (translated.font.isType3Font) { + operatorList.addDependencies(translated.type3Dependencies); + } + state.font = translated.font; + translated.send(this.handler); + return translated.loadedName; + } + handleText(chars2, state) { + const font = state.font; + const glyphs = font.charsToGlyphs(chars2); + if (font.data) { + const isAddToPathSet = !!(state.textRenderingMode & TextRenderingMode2.ADD_TO_PATH_FLAG); + if (isAddToPathSet || state.fillColorSpace.name === "Pattern" || font.disableFontFace) { + _PartialEvaluator.buildFontPaths(font, glyphs, this.handler, this.options); + } + } + return glyphs; + } + ensureStateFont(state) { + if (state.font) { + return; + } + const reason = new FormatError3("Missing setFont (Tf) operator before text rendering operator."); + if (this.options.ignoreErrors) { + warn2(`ensureStateFont: "${reason}".`); + return; + } + throw reason; + } + async setGState({ + resources, + gState, + operatorList, + cacheKey, + task, + stateManager, + localGStateCache, + localColorSpaceCache, + seenRefs + }) { + const gStateRef = gState.objId; + let isSimpleGState = true; + const gStateObj = []; + let promise2 = Promise.resolve(); + for (const [key, value] of gState) { + switch (key) { + case "Type": + break; + case "LW": + if (typeof value !== "number") { + warn2(`Invalid LW (line width): ${value}`); + break; + } + gStateObj.push([key, Math.abs(value)]); + break; + case "LC": + case "LJ": + case "ML": + case "D": + case "RI": + case "FL": + case "CA": + case "ca": + gStateObj.push([key, value]); + break; + case "Font": + isSimpleGState = false; + promise2 = promise2.then(() => this.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function(loadedName) { + operatorList.addDependency(loadedName); + gStateObj.push([key, [loadedName, value[1]]]); + })); + break; + case "BM": + gStateObj.push([key, normalizeBlendMode(value)]); + break; + case "SMask": + if (isName(value, "None")) { + gStateObj.push([key, false]); + break; + } + if (value instanceof Dict) { + isSimpleGState = false; + promise2 = promise2.then(() => this.handleSMask(value, resources, operatorList, task, stateManager, localColorSpaceCache, seenRefs)); + gStateObj.push([key, true]); + } else { + warn2("Unsupported SMask type"); + } + break; + case "TR": + const transferMaps = this.handleTransferFunction(value); + gStateObj.push([key, transferMaps]); + break; + case "OP": + case "op": + case "OPM": + case "BG": + case "BG2": + case "UCR": + case "UCR2": + case "TR2": + case "HT": + case "SM": + case "SA": + case "AIS": + case "TK": + info2("graphic state operator " + key); + break; + default: + info2("Unknown graphic state operator " + key); + break; + } + } + await promise2; + if (gStateObj.length > 0) { + operatorList.addOp(OPS2.setGState, [gStateObj]); + } + if (isSimpleGState) { + localGStateCache.set(cacheKey, gStateRef, gStateObj); + } + } + loadFont(fontName, font, resources, task, fallbackFontDict = null, cssFontInfo = null) { + const errorFont = async () => new TranslatedFont({ + loadedName: "g_font_error", + font: new ErrorFont(`Font "${fontName}" is not available.`), + dict: font + }); + let fontRef; + if (font) { + if (font instanceof Ref) { + fontRef = font; + } + } else { + const fontRes = resources.get("Font"); + if (fontRes) { + fontRef = fontRes.getRaw(fontName); + } + } + if (fontRef) { + if (this.type3FontRefs?.has(fontRef)) { + return errorFont(); + } + if (this.fontCache.has(fontRef)) { + return this.fontCache.get(fontRef); + } + try { + font = this.xref.fetchIfRef(fontRef); + } catch (ex) { + warn2(`loadFont - lookup failed: "${ex}".`); + } + } + if (!(font instanceof Dict)) { + if (!this.options.ignoreErrors && !this.parsingType3Font) { + warn2(`Font "${fontName}" is not available.`); + return errorFont(); + } + warn2(`Font "${fontName}" is not available -- attempting to fallback to a default font.`); + font = fallbackFontDict || _PartialEvaluator.fallbackFontDict; + } + if (font.cacheKey && this.fontCache.has(font.cacheKey)) { + return this.fontCache.get(font.cacheKey); + } + const { + promise: promise2, + resolve: resolve2 + } = Promise.withResolvers(); + let preEvaluatedFont; + try { + preEvaluatedFont = this.preEvaluateFont(font); + preEvaluatedFont.cssFontInfo = cssFontInfo; + } catch (reason) { + warn2(`loadFont - preEvaluateFont failed: "${reason}".`); + return errorFont(); + } + const { + descriptor, + hash: hash2 + } = preEvaluatedFont; + const fontRefIsRef = fontRef instanceof Ref; + let fontID; + if (hash2 && descriptor instanceof Dict) { + const fontAliases2 = descriptor.fontAliases ||= /* @__PURE__ */ Object.create(null); + if (fontAliases2[hash2]) { + const aliasFontRef = fontAliases2[hash2].aliasRef; + if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) { + this.fontCache.putAlias(fontRef, aliasFontRef); + return this.fontCache.get(fontRef); + } + } else { + fontAliases2[hash2] = { + fontID: this.idFactory.createFontId() + }; + } + if (fontRefIsRef) { + fontAliases2[hash2].aliasRef = fontRef; + } + fontID = fontAliases2[hash2].fontID; + } else { + fontID = this.idFactory.createFontId(); + } + assert3(fontID?.startsWith("f"), 'The "fontID" must be (correctly) defined.'); + if (fontRefIsRef) { + this.fontCache.put(fontRef, promise2); + } else { + font.cacheKey = `cacheKey_${fontID}`; + this.fontCache.put(font.cacheKey, promise2); + } + font.loadedName = `${this.idFactory.getDocId()}_${fontID}`; + this.translateFont(preEvaluatedFont).then(async (translatedFont) => { + const translated = new TranslatedFont({ + loadedName: font.loadedName, + font: translatedFont, + dict: font + }); + if (translatedFont.isType3Font) { + try { + await translated.loadType3Data(this, resources, task); + } catch (reason) { + throw new Error(`Type3 font load error: ${reason}`); + } + } + resolve2(translated); + }).catch((reason) => { + warn2(`loadFont - translateFont failed: "${reason}".`); + resolve2(new TranslatedFont({ + loadedName: font.loadedName, + font: new ErrorFont(reason?.message), + dict: font + })); + }); + return promise2; + } + buildPath(fn, args, state) { + const { + pathMinMax: minMax, + pathBuffer + } = state; + switch (fn | 0) { + case OPS2.rectangle: { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + const width = args[2]; + const height = args[3]; + const xw = x + width; + const yh = y + height; + if (width === 0 || height === 0) { + pathBuffer.push(DrawOPS3.moveTo, x, y, DrawOPS3.lineTo, xw, yh, DrawOPS3.closePath); + } else { + pathBuffer.push(DrawOPS3.moveTo, x, y, DrawOPS3.lineTo, xw, y, DrawOPS3.lineTo, xw, yh, DrawOPS3.lineTo, x, yh, DrawOPS3.closePath); + } + Util2.rectBoundingBox(x, y, xw, yh, minMax); + break; + } + case OPS2.moveTo: { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + pathBuffer.push(DrawOPS3.moveTo, x, y); + Util2.pointBoundingBox(x, y, minMax); + break; + } + case OPS2.lineTo: { + const x = state.currentPointX = args[0]; + const y = state.currentPointY = args[1]; + pathBuffer.push(DrawOPS3.lineTo, x, y); + Util2.pointBoundingBox(x, y, minMax); + break; + } + case OPS2.curveTo: { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x2, y2, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS3.curveTo, x1, y1, x2, y2, x, y); + Util2.bezierBoundingBox(startX, startY, x1, y1, x2, y2, x, y, minMax); + break; + } + case OPS2.curveTo2: { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS3.curveTo, startX, startY, x1, y1, x, y); + Util2.bezierBoundingBox(startX, startY, startX, startY, x1, y1, x, y, minMax); + break; + } + case OPS2.curveTo3: { + const startX = state.currentPointX; + const startY = state.currentPointY; + const [x1, y1, x, y] = args; + state.currentPointX = x; + state.currentPointY = y; + pathBuffer.push(DrawOPS3.curveTo, x1, y1, x, y, x, y); + Util2.bezierBoundingBox(startX, startY, x1, y1, x, y, x, y, minMax); + break; + } + case OPS2.closePath: + pathBuffer.push(DrawOPS3.closePath); + break; + } + } + _getColorSpace(cs, resources, localColorSpaceCache) { + return ColorSpaceUtils.parse({ + cs, + xref: this.xref, + resources, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache, + asyncIfNotCached: true + }); + } + async _handleColorSpace(csPromise) { + try { + return await csPromise; + } catch (ex) { + if (ex instanceof AbortException3) { + return null; + } + if (this.options.ignoreErrors) { + warn2(`_handleColorSpace - ignoring ColorSpace: "${ex}".`); + return null; + } + throw ex; + } + } + parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }) { + let id = localShadingPatternCache.get(shading); + if (id) { + return id; + } + let patternIR; + try { + const shadingFill = Pattern.parseShading(shading, this.xref, resources, this._pdfFunctionFactory, this.globalColorSpaceCache, localColorSpaceCache); + patternIR = shadingFill.getIR(); + } catch (reason) { + if (reason instanceof AbortException3) { + return null; + } + if (this.options.ignoreErrors) { + warn2(`parseShading - ignoring shading: "${reason}".`); + localShadingPatternCache.set(shading, null); + return null; + } + throw reason; + } + id = `pattern_${this.idFactory.createObjId()}`; + if (this.parsingType3Font) { + id = `${this.idFactory.getDocId()}_type3_${id}`; + } + localShadingPatternCache.set(shading, id); + if (this.parsingType3Font) { + this.handler.send("commonobj", [id, "Pattern", patternIR]); + } else { + this.handler.send("obj", [id, this.pageIndex, "Pattern", patternIR]); + } + return id; + } + handleColorN(operatorList, fn, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache) { + const patternName = args.pop(); + if (patternName instanceof Name2) { + const rawPattern = patterns.getRaw(patternName.name); + const localTilingPattern = rawPattern instanceof Ref && localTilingPatternCache.getByRef(rawPattern); + if (localTilingPattern) { + try { + const color = cs.base ? cs.base.getRgbHex(args, 0) : null; + const tilingPatternIR = getTilingPatternIR(localTilingPattern.operatorListIR, localTilingPattern.dict, color); + operatorList.addOp(fn, tilingPatternIR); + return void 0; + } catch { + } + } + const pattern = this.xref.fetchIfRef(rawPattern); + if (pattern) { + const dict = pattern instanceof BaseStream ? pattern.dict : pattern; + const typeNum = dict.get("PatternType"); + if (typeNum === PatternType.TILING) { + const color = cs.base ? cs.base.getRgbHex(args, 0) : null; + return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task, localTilingPatternCache); + } else if (typeNum === PatternType.SHADING) { + const shading = dict.get("Shading"); + const objId = this.parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }); + if (objId) { + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + operatorList.addOp(fn, ["Shading", objId, matrix]); + } + return void 0; + } + throw new FormatError3(`Unknown PatternType: ${typeNum}`); + } + } + throw new FormatError3(`Unknown PatternName: ${patternName}`); + } + _parseVisibilityExpression(array2, nestingCounter, currentResult) { + const MAX_NESTING = 10; + if (++nestingCounter > MAX_NESTING) { + warn2("Visibility expression is too deeply nested"); + return; + } + const length = array2.length; + const operator = this.xref.fetchIfRef(array2[0]); + if (length < 2 || !(operator instanceof Name2)) { + warn2("Invalid visibility expression"); + return; + } + switch (operator.name) { + case "And": + case "Or": + case "Not": + currentResult.push(operator.name); + break; + default: + warn2(`Invalid operator ${operator.name} in visibility expression`); + return; + } + for (let i = 1; i < length; i++) { + const raw = array2[i]; + const object3 = this.xref.fetchIfRef(raw); + if (Array.isArray(object3)) { + const nestedResult = []; + currentResult.push(nestedResult); + this._parseVisibilityExpression(object3, nestingCounter, nestedResult); + } else if (raw instanceof Ref) { + currentResult.push(raw.toString()); + } + } + } + async parseMarkedContentProps(contentProperties, resources) { + let optionalContent; + if (contentProperties instanceof Name2) { + const properties = resources.get("Properties"); + optionalContent = properties.get(contentProperties.name); + } else if (contentProperties instanceof Dict) { + optionalContent = contentProperties; + } else { + throw new FormatError3("Optional content properties malformed."); + } + const optionalContentType = optionalContent.get("Type")?.name; + if (optionalContentType === "OCG") { + return { + type: optionalContentType, + id: optionalContent.objId + }; + } else if (optionalContentType === "OCMD") { + const expression = optionalContent.get("VE"); + if (Array.isArray(expression)) { + const result2 = []; + this._parseVisibilityExpression(expression, 0, result2); + if (result2.length > 0) { + return { + type: "OCMD", + expression: result2 + }; + } + } + const optionalContentGroups = optionalContent.get("OCGs"); + if (Array.isArray(optionalContentGroups) || optionalContentGroups instanceof Dict) { + const groupIds = []; + if (Array.isArray(optionalContentGroups)) { + for (const ocg of optionalContentGroups) { + groupIds.push(ocg.toString()); + } + } else { + groupIds.push(optionalContentGroups.objId); + } + return { + type: optionalContentType, + ids: groupIds, + policy: optionalContent.get("P") instanceof Name2 ? optionalContent.get("P").name : null, + expression: null + }; + } else if (optionalContentGroups instanceof Ref) { + return { + type: optionalContentType, + id: optionalContentGroups.toString() + }; + } + } + return null; + } + getOperatorList({ + stream, + task, + resources, + operatorList, + initialState = null, + fallbackFontDict = null, + prevRefs = null + }) { + const objId = stream.dict?.objId; + const seenRefs = new RefSet(prevRefs); + if (objId) { + if (prevRefs?.has(objId)) { + throw new Error(`getOperatorList - ignoring circular reference: ${objId}`); + } + seenRefs.put(objId); + } + resources ||= Dict.empty; + initialState ||= new EvalState(); + if (!operatorList) { + throw new Error('getOperatorList: missing "operatorList" parameter'); + } + const self2 = this; + const xref = this.xref; + const localImageCache = new LocalImageCache(); + const localColorSpaceCache = new LocalColorSpaceCache(); + const localGStateCache = new LocalGStateCache(); + const localTilingPatternCache = new LocalTilingPatternCache(); + const localShadingPatternCache = /* @__PURE__ */ new Map(); + const xobjs = resources.get("XObject") || Dict.empty; + const patterns = resources.get("Pattern") || Dict.empty; + const stateManager = new StateManager(initialState); + const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + const timeSlotManager = new TimeSlotManager(); + function closePendingRestoreOPS(argument) { + for (let i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) { + operatorList.addOp(OPS2.restore, []); + } + } + return new Promise(function promiseBody(resolve2, reject2) { + const next = function(promise2) { + Promise.all([promise2, operatorList.ready]).then(function() { + try { + promiseBody(resolve2, reject2); + } catch (ex) { + reject2(ex); + } + }, reject2); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + const operation = {}; + let stop, i, ii, cs, name, isValidName; + while (!(stop = timeSlotManager.check())) { + operation.args = null; + if (!preprocessor.read(operation)) { + break; + } + let args = operation.args; + let fn = operation.fn; + switch (fn | 0) { + case OPS2.paintXObject: + isValidName = args[0] instanceof Name2; + name = args[0].name; + if (isValidName) { + const localImage = localImageCache.getByName(name); + if (localImage) { + addCachedImageOps(operatorList, localImage); + args = null; + continue; + } + } + next(new Promise(function(resolveXObject, rejectXObject) { + if (!isValidName) { + throw new FormatError3("XObject must be referred to by name."); + } + let xobj = xobjs.getRaw(name); + if (xobj instanceof Ref) { + const cachedImage = localImageCache.getByRef(xobj) || self2._regionalImageCache.getByRef(xobj) || self2.globalImageCache.getData(xobj, self2.pageIndex); + if (cachedImage) { + addCachedImageOps(operatorList, cachedImage); + resolveXObject(); + return; + } + xobj = xref.fetch(xobj); + } + if (!(xobj instanceof BaseStream)) { + throw new FormatError3("XObject should be a stream"); + } + const type = xobj.dict.get("Subtype"); + if (!(type instanceof Name2)) { + throw new FormatError3("XObject should have a Name subtype"); + } + if (type.name === "Form") { + stateManager.save(); + self2.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone({ + newPath: true + }), localColorSpaceCache, seenRefs).then(function() { + stateManager.restore(); + resolveXObject(); + }, rejectXObject); + return; + } else if (type.name === "Image") { + self2.buildPaintImageXObject({ + resources, + image: xobj, + operatorList, + cacheKey: name, + localImageCache, + localColorSpaceCache + }).then(resolveXObject, rejectXObject); + return; + } else if (type.name === "PS") { + info2("Ignored XObject subtype PS"); + } else { + throw new FormatError3(`Unhandled XObject subtype ${type.name}`); + } + resolveXObject(); + }).catch(function(reason) { + if (reason instanceof AbortException3) { + return; + } + if (self2.options.ignoreErrors) { + warn2(`getOperatorList - ignoring XObject: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS2.setFont: + const fontSize = args[1]; + next(self2.handleSetFont(resources, args, null, operatorList, task, stateManager.state, fallbackFontDict).then(function(loadedName) { + operatorList.addDependency(loadedName); + operatorList.addOp(OPS2.setFont, [loadedName, fontSize]); + })); + return; + case OPS2.endInlineImage: + const cacheKey = args[0].cacheKey; + if (cacheKey) { + const localImage = localImageCache.getByName(cacheKey); + if (localImage) { + addCachedImageOps(operatorList, localImage); + args = null; + continue; + } + } + next(self2.buildPaintImageXObject({ + resources, + image: args[0], + isInline: true, + operatorList, + cacheKey, + localImageCache, + localColorSpaceCache + })); + return; + case OPS2.showText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + args[0] = self2.handleText(args[0], stateManager.state); + break; + case OPS2.showSpacedText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + const combinedGlyphs = [], state = stateManager.state; + for (const arrItem of args[0]) { + if (typeof arrItem === "string") { + combinedGlyphs.push(...self2.handleText(arrItem, state)); + } else if (typeof arrItem === "number") { + combinedGlyphs.push(arrItem); + } + } + args[0] = combinedGlyphs; + fn = OPS2.showText; + break; + case OPS2.nextLineShowText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + operatorList.addOp(OPS2.nextLine); + args[0] = self2.handleText(args[0], stateManager.state); + fn = OPS2.showText; + break; + case OPS2.nextLineSetSpacingShowText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + operatorList.addOp(OPS2.nextLine); + operatorList.addOp(OPS2.setWordSpacing, [args.shift()]); + operatorList.addOp(OPS2.setCharSpacing, [args.shift()]); + args[0] = self2.handleText(args[0], stateManager.state); + fn = OPS2.showText; + break; + case OPS2.setTextRenderingMode: + stateManager.state.textRenderingMode = args[0]; + break; + case OPS2.setFillColorSpace: { + const fillCS = self2._getColorSpace(args[0], resources, localColorSpaceCache); + if (fillCS instanceof ColorSpace) { + stateManager.state.fillColorSpace = fillCS; + continue; + } + next(self2._handleColorSpace(fillCS).then((colorSpace) => { + stateManager.state.fillColorSpace = colorSpace || ColorSpaceUtils.gray; + })); + return; + } + case OPS2.setStrokeColorSpace: { + const strokeCS = self2._getColorSpace(args[0], resources, localColorSpaceCache); + if (strokeCS instanceof ColorSpace) { + stateManager.state.strokeColorSpace = strokeCS; + continue; + } + next(self2._handleColorSpace(strokeCS).then((colorSpace) => { + stateManager.state.strokeColorSpace = colorSpace || ColorSpaceUtils.gray; + })); + return; + } + case OPS2.setFillColor: + cs = stateManager.state.fillColorSpace; + args = [cs.getRgbHex(args, 0)]; + fn = OPS2.setFillRGBColor; + break; + case OPS2.setStrokeColor: + cs = stateManager.state.strokeColorSpace; + args = [cs.getRgbHex(args, 0)]; + fn = OPS2.setStrokeRGBColor; + break; + case OPS2.setFillGray: + stateManager.state.fillColorSpace = ColorSpaceUtils.gray; + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS2.setFillRGBColor; + break; + case OPS2.setStrokeGray: + stateManager.state.strokeColorSpace = ColorSpaceUtils.gray; + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS2.setStrokeRGBColor; + break; + case OPS2.setFillCMYKColor: + stateManager.state.fillColorSpace = ColorSpaceUtils.cmyk; + args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)]; + fn = OPS2.setFillRGBColor; + break; + case OPS2.setStrokeCMYKColor: + stateManager.state.strokeColorSpace = ColorSpaceUtils.cmyk; + args = [ColorSpaceUtils.cmyk.getRgbHex(args, 0)]; + fn = OPS2.setStrokeRGBColor; + break; + case OPS2.setFillRGBColor: + stateManager.state.fillColorSpace = ColorSpaceUtils.rgb; + args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)]; + break; + case OPS2.setStrokeRGBColor: + stateManager.state.strokeColorSpace = ColorSpaceUtils.rgb; + args = [ColorSpaceUtils.rgb.getRgbHex(args, 0)]; + break; + case OPS2.setFillColorN: + cs = stateManager.state.patternFillColorSpace; + if (!cs) { + if (isNumberArray(args, null)) { + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS2.setFillRGBColor; + break; + } + args = []; + fn = OPS2.setFillTransparent; + break; + } + if (cs.name === "Pattern") { + next(self2.handleColorN(operatorList, OPS2.setFillColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); + return; + } + args = [cs.getRgbHex(args, 0)]; + fn = OPS2.setFillRGBColor; + break; + case OPS2.setStrokeColorN: + cs = stateManager.state.patternStrokeColorSpace; + if (!cs) { + if (isNumberArray(args, null)) { + args = [ColorSpaceUtils.gray.getRgbHex(args, 0)]; + fn = OPS2.setStrokeRGBColor; + break; + } + args = []; + fn = OPS2.setStrokeTransparent; + break; + } + if (cs.name === "Pattern") { + next(self2.handleColorN(operatorList, OPS2.setStrokeColorN, args, cs, patterns, resources, task, localColorSpaceCache, localTilingPatternCache, localShadingPatternCache)); + return; + } + args = [cs.getRgbHex(args, 0)]; + fn = OPS2.setStrokeRGBColor; + break; + case OPS2.shadingFill: + let shading; + try { + const shadingRes = resources.get("Shading"); + if (!shadingRes) { + throw new FormatError3("No shading resource found"); + } + shading = shadingRes.get(args[0].name); + if (!shading) { + throw new FormatError3("No shading object found"); + } + } catch (reason) { + if (reason instanceof AbortException3) { + continue; + } + if (self2.options.ignoreErrors) { + warn2(`getOperatorList - ignoring Shading: "${reason}".`); + continue; + } + throw reason; + } + const patternId = self2.parseShading({ + shading, + resources, + localColorSpaceCache, + localShadingPatternCache + }); + if (!patternId) { + continue; + } + args = [patternId]; + fn = OPS2.shadingFill; + break; + case OPS2.setGState: + isValidName = args[0] instanceof Name2; + name = args[0].name; + if (isValidName) { + const localGStateObj = localGStateCache.getByName(name); + if (localGStateObj) { + if (localGStateObj.length > 0) { + operatorList.addOp(OPS2.setGState, [localGStateObj]); + } + args = null; + continue; + } + } + next(new Promise(function(resolveGState, rejectGState) { + if (!isValidName) { + throw new FormatError3("GState must be referred to by name."); + } + const extGState = resources.get("ExtGState"); + if (!(extGState instanceof Dict)) { + throw new FormatError3("ExtGState should be a dictionary."); + } + const gState = extGState.get(name); + if (!(gState instanceof Dict)) { + throw new FormatError3("GState should be a dictionary."); + } + self2.setGState({ + resources, + gState, + operatorList, + cacheKey: name, + task, + stateManager, + localGStateCache, + localColorSpaceCache, + seenRefs + }).then(resolveGState, rejectGState); + }).catch(function(reason) { + if (reason instanceof AbortException3) { + return; + } + if (self2.options.ignoreErrors) { + warn2(`getOperatorList - ignoring ExtGState: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS2.setLineWidth: { + const [thickness] = args; + if (typeof thickness !== "number") { + warn2(`Invalid setLineWidth: ${thickness}`); + continue; + } + args[0] = Math.abs(thickness); + break; + } + case OPS2.setDash: { + const dashPhase = args[1]; + if (typeof dashPhase !== "number") { + warn2(`Invalid setDash: ${dashPhase}`); + continue; + } + const dashArray = args[0]; + if (!Array.isArray(dashArray)) { + warn2(`Invalid setDash: ${dashArray}`); + continue; + } + if (dashArray.some((x) => typeof x !== "number")) { + args[0] = dashArray.filter((x) => typeof x === "number"); + } + break; + } + case OPS2.moveTo: + case OPS2.lineTo: + case OPS2.curveTo: + case OPS2.curveTo2: + case OPS2.curveTo3: + case OPS2.closePath: + case OPS2.rectangle: + self2.buildPath(fn, args, stateManager.state); + continue; + case OPS2.stroke: + case OPS2.closeStroke: + case OPS2.fill: + case OPS2.eoFill: + case OPS2.fillStroke: + case OPS2.eoFillStroke: + case OPS2.closeFillStroke: + case OPS2.closeEOFillStroke: + case OPS2.endPath: { + const { + state: { + pathBuffer, + pathMinMax + } + } = stateManager; + if (fn === OPS2.closeStroke || fn === OPS2.closeFillStroke || fn === OPS2.closeEOFillStroke) { + pathBuffer.push(DrawOPS3.closePath); + } + if (pathBuffer.length === 0) { + operatorList.addOp(OPS2.constructPath, [fn, [null], null]); + } else { + operatorList.addOp(OPS2.constructPath, [fn, [new Float32Array(pathBuffer)], pathMinMax.slice()]); + pathBuffer.length = 0; + pathMinMax.set([Infinity, Infinity, -Infinity, -Infinity], 0); + } + continue; + } + case OPS2.setTextMatrix: + operatorList.addOp(fn, [new Float32Array(args)]); + continue; + case OPS2.markPoint: + case OPS2.markPointProps: + case OPS2.beginCompat: + case OPS2.endCompat: + continue; + case OPS2.beginMarkedContentProps: + if (!(args[0] instanceof Name2)) { + warn2(`Expected name for beginMarkedContentProps arg0=${args[0]}`); + operatorList.addOp(OPS2.beginMarkedContentProps, ["OC", null]); + continue; + } + if (args[0].name === "OC") { + next(self2.parseMarkedContentProps(args[1], resources).then((data) => { + operatorList.addOp(OPS2.beginMarkedContentProps, ["OC", data]); + }).catch((reason) => { + if (reason instanceof AbortException3) { + return; + } + if (self2.options.ignoreErrors) { + warn2(`getOperatorList - ignoring beginMarkedContentProps: "${reason}".`); + operatorList.addOp(OPS2.beginMarkedContentProps, ["OC", null]); + return; + } + throw reason; + })); + return; + } + args = [args[0].name, args[1] instanceof Dict ? args[1].get("MCID") : null]; + break; + case OPS2.beginMarkedContent: + case OPS2.endMarkedContent: + default: + if (args !== null) { + for (i = 0, ii = args.length; i < ii; i++) { + if (args[i] instanceof Dict) { + break; + } + } + if (i < ii) { + warn2("getOperatorList - ignoring operator: " + fn); + continue; + } + } + } + operatorList.addOp(fn, args); + } + if (stop) { + next(deferred); + return; + } + closePendingRestoreOPS(); + resolve2(); + }).catch((reason) => { + if (reason instanceof AbortException3) { + return; + } + if (this.options.ignoreErrors) { + warn2(`getOperatorList - ignoring errors during "${task.name}" task: "${reason}".`); + closePendingRestoreOPS(); + return; + } + throw reason; + }); + } + getTextContent({ + stream, + task, + resources, + stateManager = null, + includeMarkedContent = false, + sink, + seenStyles = /* @__PURE__ */ new Set(), + viewBox, + lang = null, + markedContentData = null, + disableNormalization = false, + keepWhiteSpace = false, + prevRefs = null, + intersector = null + }) { + const objId = stream.dict?.objId; + const seenRefs = new RefSet(prevRefs); + if (objId) { + if (prevRefs?.has(objId)) { + throw new Error(`getTextContent - ignoring circular reference: ${objId}`); + } + seenRefs.put(objId); + } + resources ||= Dict.empty; + stateManager ||= new StateManager(new TextState()); + if (includeMarkedContent) { + markedContentData ||= { + level: 0 + }; + } + const textContent = { + items: [], + styles: /* @__PURE__ */ Object.create(null), + lang + }; + const textContentItem = { + initialized: false, + str: [], + totalWidth: 0, + totalHeight: 0, + width: 0, + height: 0, + vertical: false, + prevTransform: null, + textAdvanceScale: 0, + spaceInFlowMin: 0, + spaceInFlowMax: 0, + trackingSpaceMin: Infinity, + negativeSpaceMax: -Infinity, + notASpace: -Infinity, + transform: null, + fontName: null, + hasEOL: false + }; + const twoLastChars = [" ", " "]; + let twoLastCharsPos = 0; + function saveLastChar(char2) { + const nextPos = (twoLastCharsPos + 1) % 2; + const ret2 = twoLastChars[twoLastCharsPos] !== " " && twoLastChars[nextPos] === " "; + twoLastChars[twoLastCharsPos] = char2; + twoLastCharsPos = nextPos; + return !keepWhiteSpace && ret2; + } + function shouldAddWhitepsace() { + return !keepWhiteSpace && twoLastChars[twoLastCharsPos] !== " " && twoLastChars[(twoLastCharsPos + 1) % 2] === " "; + } + function resetLastChars() { + twoLastChars[0] = twoLastChars[1] = " "; + twoLastCharsPos = 0; + } + const TRACKING_SPACE_FACTOR = 0.102; + const NOT_A_SPACE_FACTOR = 0.03; + const NEGATIVE_SPACE_FACTOR = -0.2; + const SPACE_IN_FLOW_MIN_FACTOR = 0.102; + const SPACE_IN_FLOW_MAX_FACTOR = 0.6; + const VERTICAL_SHIFT_RATIO = 0.25; + const self2 = this; + const xref = this.xref; + const showSpacedTextBuffer = []; + let xobjs = null; + const emptyXObjectCache = new LocalImageCache(); + const emptyGStateCache = new LocalGStateCache(); + const preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager); + let textState; + function pushWhitespace({ + width = 0, + height = 0, + transform: transform2 = textContentItem.prevTransform, + fontName = textContentItem.fontName + }) { + intersector?.addExtraChar(" "); + textContent.items.push({ + str: " ", + dir: "ltr", + width, + height, + transform: transform2, + fontName, + hasEOL: false + }); + } + function getCurrentTextTransform() { + const font = textState.font; + const tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise]; + if (font.isType3Font && (textState.fontSize <= 1 || font.isCharBBox) && !isArrayEqual(textState.fontMatrix, FONT_IDENTITY_MATRIX2)) { + const glyphHeight = font.bbox[3] - font.bbox[1]; + if (glyphHeight > 0) { + tsm[3] *= glyphHeight * textState.fontMatrix[3]; + } + } + return Util2.transform(textState.ctm, Util2.transform(textState.textMatrix, tsm)); + } + function ensureTextContentItem() { + if (textContentItem.initialized) { + return textContentItem; + } + const { + font, + loadedName + } = textState; + if (!seenStyles.has(loadedName)) { + seenStyles.add(loadedName); + textContent.styles[loadedName] = { + fontFamily: font.fallbackName, + ascent: font.ascent, + descent: font.descent, + vertical: font.vertical + }; + if (self2.options.fontExtraProperties && font.systemFontInfo) { + const style = textContent.styles[loadedName]; + style.fontSubstitution = font.systemFontInfo.css; + style.fontSubstitutionLoadedName = font.systemFontInfo.loadedName; + } + } + textContentItem.fontName = loadedName; + const trm = textContentItem.transform = getCurrentTextTransform(); + if (!font.vertical) { + textContentItem.width = textContentItem.totalWidth = 0; + textContentItem.height = textContentItem.totalHeight = Math.hypot(trm[2], trm[3]); + textContentItem.vertical = false; + } else { + textContentItem.width = textContentItem.totalWidth = Math.hypot(trm[0], trm[1]); + textContentItem.height = textContentItem.totalHeight = 0; + textContentItem.vertical = true; + } + const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); + const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); + textContentItem.textAdvanceScale = scaleCtmX * scaleLineX; + const { + fontSize + } = textState; + textContentItem.trackingSpaceMin = fontSize * TRACKING_SPACE_FACTOR; + textContentItem.notASpace = fontSize * NOT_A_SPACE_FACTOR; + textContentItem.negativeSpaceMax = fontSize * NEGATIVE_SPACE_FACTOR; + textContentItem.spaceInFlowMin = fontSize * SPACE_IN_FLOW_MIN_FACTOR; + textContentItem.spaceInFlowMax = fontSize * SPACE_IN_FLOW_MAX_FACTOR; + textContentItem.hasEOL = false; + textContentItem.initialized = true; + return textContentItem; + } + function updateAdvanceScale() { + if (!textContentItem.initialized) { + return; + } + const scaleLineX = Math.hypot(textState.textLineMatrix[0], textState.textLineMatrix[1]); + const scaleCtmX = Math.hypot(textState.ctm[0], textState.ctm[1]); + const scaleFactor = scaleCtmX * scaleLineX; + if (scaleFactor === textContentItem.textAdvanceScale) { + return; + } + if (!textContentItem.vertical) { + textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; + textContentItem.width = 0; + } else { + textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; + textContentItem.height = 0; + } + textContentItem.textAdvanceScale = scaleFactor; + } + function runBidiTransform(textChunk) { + let text2 = textChunk.str.join(""); + if (!disableNormalization) { + text2 = normalizeUnicode2(text2); + } + const bidiResult = bidi(text2, -1, textChunk.vertical); + return { + str: bidiResult.str, + dir: bidiResult.dir, + width: Math.abs(textChunk.totalWidth), + height: Math.abs(textChunk.totalHeight), + transform: textChunk.transform, + fontName: textChunk.fontName, + hasEOL: textChunk.hasEOL + }; + } + async function handleSetFont(fontName, fontRef) { + const translated = await self2.loadFont(fontName, fontRef, resources, task); + textState.loadedName = translated.loadedName; + textState.font = translated.font; + textState.fontMatrix = translated.font.fontMatrix || FONT_IDENTITY_MATRIX2; + } + function applyInverseRotation(x, y, matrix) { + const scale = Math.hypot(matrix[0], matrix[1]); + return [(matrix[0] * x + matrix[1] * y) / scale, (matrix[2] * x + matrix[3] * y) / scale]; + } + function compareWithLastPosition(glyphWidth) { + const currentTransform = getCurrentTextTransform(); + let posX = currentTransform[4]; + let posY = currentTransform[5]; + if (textState.font?.vertical) { + if (posX < viewBox[0] || posX > viewBox[2] || posY + glyphWidth < viewBox[1] || posY > viewBox[3]) { + return false; + } + } else if (posX + glyphWidth < viewBox[0] || posX > viewBox[2] || posY < viewBox[1] || posY > viewBox[3]) { + return false; + } + if (!textState.font || !textContentItem.prevTransform) { + return true; + } + let lastPosX = textContentItem.prevTransform[4]; + let lastPosY = textContentItem.prevTransform[5]; + if (lastPosX === posX && lastPosY === posY) { + return true; + } + let rotate = -1; + if (currentTransform[0] && currentTransform[1] === 0 && currentTransform[2] === 0) { + rotate = currentTransform[0] > 0 ? 0 : 180; + } else if (currentTransform[1] && currentTransform[0] === 0 && currentTransform[3] === 0) { + rotate = currentTransform[1] > 0 ? 90 : 270; + } + switch (rotate) { + case 0: + break; + case 90: + [posX, posY] = [posY, posX]; + [lastPosX, lastPosY] = [lastPosY, lastPosX]; + break; + case 180: + [posX, posY, lastPosX, lastPosY] = [-posX, -posY, -lastPosX, -lastPosY]; + break; + case 270: + [posX, posY] = [-posY, -posX]; + [lastPosX, lastPosY] = [-lastPosY, -lastPosX]; + break; + default: + [posX, posY] = applyInverseRotation(posX, posY, currentTransform); + [lastPosX, lastPosY] = applyInverseRotation(lastPosX, lastPosY, textContentItem.prevTransform); + } + if (textState.font.vertical) { + const advanceY2 = (lastPosY - posY) / textContentItem.textAdvanceScale; + const advanceX2 = posX - lastPosX; + const textOrientation2 = Math.sign(textContentItem.height); + if (advanceY2 < textOrientation2 * textContentItem.negativeSpaceMax) { + if (Math.abs(advanceX2) > 0.5 * textContentItem.width) { + appendEOL(); + return true; + } + resetLastChars(); + flushTextContentItem(); + return true; + } + if (Math.abs(advanceX2) > textContentItem.width) { + appendEOL(); + return true; + } + if (advanceY2 <= textOrientation2 * textContentItem.notASpace) { + resetLastChars(); + } + if (advanceY2 <= textOrientation2 * textContentItem.trackingSpaceMin) { + if (shouldAddWhitepsace()) { + resetLastChars(); + flushTextContentItem(); + pushWhitespace({ + height: Math.abs(advanceY2) + }); + } else { + textContentItem.height += advanceY2; + } + } else if (!addFakeSpaces(advanceY2, textContentItem.prevTransform, textOrientation2)) { + if (textContentItem.str.length === 0) { + resetLastChars(); + pushWhitespace({ + height: Math.abs(advanceY2) + }); + } else { + textContentItem.height += advanceY2; + } + } + if (Math.abs(advanceX2) > textContentItem.width * VERTICAL_SHIFT_RATIO) { + flushTextContentItem(); + } + return true; + } + const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale; + const advanceY = posY - lastPosY; + const textOrientation = Math.sign(textContentItem.width); + if (advanceX < textOrientation * textContentItem.negativeSpaceMax) { + if (Math.abs(advanceY) > 0.5 * textContentItem.height) { + appendEOL(); + return true; + } + resetLastChars(); + flushTextContentItem(); + return true; + } + if (Math.abs(advanceY) > textContentItem.height) { + appendEOL(); + return true; + } + if (advanceX <= textOrientation * textContentItem.notASpace) { + resetLastChars(); + } + if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) { + if (shouldAddWhitepsace()) { + resetLastChars(); + flushTextContentItem(); + pushWhitespace({ + width: Math.abs(advanceX) + }); + } else { + textContentItem.width += advanceX; + } + } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)) { + if (textContentItem.str.length === 0) { + resetLastChars(); + pushWhitespace({ + width: Math.abs(advanceX) + }); + } else { + textContentItem.width += advanceX; + } + } + if (Math.abs(advanceY) > textContentItem.height * VERTICAL_SHIFT_RATIO) { + flushTextContentItem(); + } + return true; + } + function buildTextContentItem({ + chars: chars2, + extraSpacing + }) { + const font = textState.font; + if (!chars2) { + const charSpacing = textState.charSpacing + extraSpacing; + if (charSpacing) { + if (!font.vertical) { + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, -charSpacing); + } + } + if (keepWhiteSpace) { + compareWithLastPosition(0); + } + return; + } + const glyphs = font.charsToGlyphs(chars2); + const scale = textState.fontMatrix[0] * textState.fontSize; + for (let i = 0, ii = glyphs.length; i < ii; i++) { + const glyph = glyphs[i]; + const { + category, + originalCharCode + } = glyph; + if (category.isInvisibleFormatMark) { + continue; + } + let charSpacing = textState.charSpacing + (i + 1 === ii ? extraSpacing : 0); + let glyphWidth = glyph.width; + if (font.vertical) { + glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth; + } + let scaledDim = glyphWidth * scale; + if (originalCharCode === 32) { + charSpacing += textState.wordSpacing; + } + if (!keepWhiteSpace && category.isWhitespace) { + if (!font.vertical) { + charSpacing += scaledDim; + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + charSpacing += -scaledDim; + textState.translateTextMatrix(0, -charSpacing); + } + saveLastChar(" "); + continue; + } + if (!category.isZeroWidthDiacritic && !compareWithLastPosition(scaledDim)) { + if (!font.vertical) { + textState.translateTextMatrix(scaledDim * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, scaledDim); + } + continue; + } + const textChunk = ensureTextContentItem(); + if (category.isZeroWidthDiacritic) { + scaledDim = 0; + } + if (!font.vertical) { + scaledDim *= textState.textHScale; + intersector?.addGlyph(getCurrentTextTransform(), scaledDim, 0, glyph.unicode); + textState.translateTextMatrix(scaledDim, 0); + textChunk.width += scaledDim; + } else { + intersector?.addGlyph(getCurrentTextTransform(), 0, scaledDim, glyph.unicode); + textState.translateTextMatrix(0, scaledDim); + scaledDim = Math.abs(scaledDim); + textChunk.height += scaledDim; + } + if (scaledDim) { + textChunk.prevTransform = getCurrentTextTransform(); + } + const glyphUnicode = glyph.unicode; + if (saveLastChar(glyphUnicode)) { + textChunk.str.push(" "); + intersector?.addExtraChar(" "); + } + if (!intersector) { + textChunk.str.push(glyphUnicode); + } + if (charSpacing) { + if (!font.vertical) { + textState.translateTextMatrix(charSpacing * textState.textHScale, 0); + } else { + textState.translateTextMatrix(0, -charSpacing); + } + } + } + } + function appendEOL() { + intersector?.addExtraChar("\n"); + resetLastChars(); + if (textContentItem.initialized) { + textContentItem.hasEOL = true; + flushTextContentItem(); + } else { + textContent.items.push({ + str: "", + dir: "ltr", + width: 0, + height: 0, + transform: getCurrentTextTransform(), + fontName: textState.loadedName, + hasEOL: true + }); + } + } + function addFakeSpaces(width, transf, textOrientation) { + if (textOrientation * textContentItem.spaceInFlowMin <= width && width <= textOrientation * textContentItem.spaceInFlowMax) { + if (textContentItem.initialized) { + resetLastChars(); + textContentItem.str.push(" "); + intersector?.addExtraChar(" "); + } + return false; + } + const fontName = textContentItem.fontName; + let height = 0; + if (textContentItem.vertical) { + height = width; + width = 0; + } + flushTextContentItem(); + resetLastChars(); + pushWhitespace({ + width: Math.abs(width), + height: Math.abs(height), + transform: transf || getCurrentTextTransform(), + fontName + }); + return true; + } + function flushTextContentItem() { + if (!textContentItem.initialized || !textContentItem.str) { + return; + } + if (!textContentItem.vertical) { + textContentItem.totalWidth += textContentItem.width * textContentItem.textAdvanceScale; + } else { + textContentItem.totalHeight += textContentItem.height * textContentItem.textAdvanceScale; + } + textContent.items.push(runBidiTransform(textContentItem)); + textContentItem.initialized = false; + textContentItem.str.length = 0; + } + function enqueueChunk(batch = false) { + const length = textContent.items.length; + if (length === 0) { + return; + } + if (batch && length < TEXT_CHUNK_BATCH_SIZE) { + return; + } + sink?.enqueue(textContent, length); + textContent.items = []; + textContent.styles = /* @__PURE__ */ Object.create(null); + } + const timeSlotManager = new TimeSlotManager(); + return new Promise(function promiseBody(resolve2, reject2) { + const next = function(promise2) { + enqueueChunk(true); + Promise.all([promise2, sink?.ready]).then(function() { + try { + promiseBody(resolve2, reject2); + } catch (ex) { + reject2(ex); + } + }, reject2); + }; + task.ensureNotTerminated(); + timeSlotManager.reset(); + const operation = {}; + let stop, name, isValidName, args = []; + while (!(stop = timeSlotManager.check())) { + args.length = 0; + operation.args = args; + if (!preprocessor.read(operation)) { + break; + } + const previousState = textState; + textState = stateManager.state; + const fn = operation.fn; + args = operation.args; + switch (fn | 0) { + case OPS2.setFont: + const fontNameArg = args[0].name, fontSizeArg = args[1]; + if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) { + break; + } + flushTextContentItem(); + textState.fontName = fontNameArg; + textState.fontSize = fontSizeArg; + next(handleSetFont(fontNameArg, null)); + return; + case OPS2.setTextRise: + textState.textRise = args[0]; + break; + case OPS2.setHScale: + textState.textHScale = args[0] / 100; + break; + case OPS2.setLeading: + textState.leading = args[0]; + break; + case OPS2.moveText: + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS2.setLeadingMoveText: + textState.leading = -args[1]; + textState.translateTextLineMatrix(args[0], args[1]); + textState.textMatrix = textState.textLineMatrix.slice(); + break; + case OPS2.nextLine: + textState.carriageReturn(); + break; + case OPS2.setTextMatrix: + textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); + updateAdvanceScale(); + break; + case OPS2.setCharSpacing: + textState.charSpacing = args[0]; + break; + case OPS2.setWordSpacing: + textState.wordSpacing = args[0]; + break; + case OPS2.beginText: + textState.textMatrix = IDENTITY_MATRIX.slice(); + textState.textLineMatrix = IDENTITY_MATRIX.slice(); + break; + case OPS2.showSpacedText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + const spaceFactor = (textState.font.vertical ? 1 : -1) * textState.fontSize / 1e3; + const elements = args[0]; + for (let i = 0, ii = elements.length; i < ii; i++) { + const item = elements[i]; + if (typeof item === "string") { + showSpacedTextBuffer.push(item); + } else if (typeof item === "number" && item !== 0) { + const str = showSpacedTextBuffer.join(""); + showSpacedTextBuffer.length = 0; + buildTextContentItem({ + chars: str, + extraSpacing: item * spaceFactor + }); + } + } + if (showSpacedTextBuffer.length > 0) { + const str = showSpacedTextBuffer.join(""); + showSpacedTextBuffer.length = 0; + buildTextContentItem({ + chars: str, + extraSpacing: 0 + }); + } + break; + case OPS2.showText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + buildTextContentItem({ + chars: args[0], + extraSpacing: 0 + }); + break; + case OPS2.nextLineShowText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + textState.carriageReturn(); + buildTextContentItem({ + chars: args[0], + extraSpacing: 0 + }); + break; + case OPS2.nextLineSetSpacingShowText: + if (!stateManager.state.font) { + self2.ensureStateFont(stateManager.state); + continue; + } + textState.wordSpacing = args[0]; + textState.charSpacing = args[1]; + textState.carriageReturn(); + buildTextContentItem({ + chars: args[2], + extraSpacing: 0 + }); + break; + case OPS2.paintXObject: + flushTextContentItem(); + xobjs ??= resources.get("XObject") || Dict.empty; + isValidName = args[0] instanceof Name2; + name = args[0].name; + if (isValidName && emptyXObjectCache.getByName(name)) { + break; + } + next(new Promise(function(resolveXObject, rejectXObject) { + if (!isValidName) { + throw new FormatError3("XObject must be referred to by name."); + } + let xobj = xobjs.getRaw(name); + if (xobj instanceof Ref) { + if (emptyXObjectCache.getByRef(xobj)) { + resolveXObject(); + return; + } + const globalImage = self2.globalImageCache.getData(xobj, self2.pageIndex); + if (globalImage) { + resolveXObject(); + return; + } + xobj = xref.fetch(xobj); + } + if (!(xobj instanceof BaseStream)) { + throw new FormatError3("XObject should be a stream"); + } + const { + dict + } = xobj; + const type = dict.get("Subtype"); + if (!(type instanceof Name2)) { + throw new FormatError3("XObject should have a Name subtype"); + } + if (type.name !== "Form") { + emptyXObjectCache.set(name, dict.objId, true); + resolveXObject(); + return; + } + const currentState = stateManager.state.clone(); + const xObjStateManager = new StateManager(currentState); + const matrix = lookupMatrix(dict.getArray("Matrix"), null); + if (matrix) { + xObjStateManager.transform(matrix); + } + const localResources = dict.get("Resources"); + enqueueChunk(); + const sinkWrapper = { + enqueueInvoked: false, + enqueue(chunk2, size3) { + this.enqueueInvoked = true; + sink.enqueue(chunk2, size3); + }, + get desiredSize() { + return sink.desiredSize ?? 0; + }, + get ready() { + return sink.ready; + } + }; + self2.getTextContent({ + stream: xobj, + task, + resources: localResources instanceof Dict ? localResources : resources, + stateManager: xObjStateManager, + includeMarkedContent, + sink: sink && sinkWrapper, + seenStyles, + viewBox, + lang, + markedContentData, + disableNormalization, + keepWhiteSpace, + prevRefs: seenRefs + }).then(function() { + if (!sinkWrapper.enqueueInvoked) { + emptyXObjectCache.set(name, dict.objId, true); + } + resolveXObject(); + }, rejectXObject); + }).catch(function(reason) { + if (reason instanceof AbortException3) { + return; + } + if (self2.options.ignoreErrors) { + warn2(`getTextContent - ignoring XObject: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS2.setGState: + isValidName = args[0] instanceof Name2; + name = args[0].name; + if (isValidName && emptyGStateCache.getByName(name)) { + break; + } + next(new Promise(function(resolveGState, rejectGState) { + if (!isValidName) { + throw new FormatError3("GState must be referred to by name."); + } + const extGState = resources.get("ExtGState"); + if (!(extGState instanceof Dict)) { + throw new FormatError3("ExtGState should be a dictionary."); + } + const gState = extGState.get(name); + if (!(gState instanceof Dict)) { + throw new FormatError3("GState should be a dictionary."); + } + const gStateFont = gState.get("Font"); + if (!gStateFont) { + emptyGStateCache.set(name, gState.objId, true); + resolveGState(); + return; + } + flushTextContentItem(); + textState.fontName = null; + textState.fontSize = gStateFont[1]; + handleSetFont(null, gStateFont[0]).then(resolveGState, rejectGState); + }).catch(function(reason) { + if (reason instanceof AbortException3) { + return; + } + if (self2.options.ignoreErrors) { + warn2(`getTextContent - ignoring ExtGState: "${reason}".`); + return; + } + throw reason; + })); + return; + case OPS2.beginMarkedContent: + flushTextContentItem(); + if (includeMarkedContent) { + markedContentData.level++; + textContent.items.push({ + type: "beginMarkedContent", + tag: args[0] instanceof Name2 ? args[0].name : null + }); + } + break; + case OPS2.beginMarkedContentProps: + flushTextContentItem(); + if (includeMarkedContent) { + markedContentData.level++; + let mcid = null; + if (args[1] instanceof Dict) { + mcid = args[1].get("MCID"); + } + textContent.items.push({ + type: "beginMarkedContentProps", + id: Number.isInteger(mcid) ? `${self2.idFactory.getPageObjId()}_mc${mcid}` : null, + tag: args[0] instanceof Name2 ? args[0].name : null + }); + } + break; + case OPS2.endMarkedContent: + flushTextContentItem(); + if (includeMarkedContent) { + if (markedContentData.level === 0) { + break; + } + markedContentData.level--; + textContent.items.push({ + type: "endMarkedContent" + }); + } + break; + case OPS2.restore: + if (previousState && (previousState.font !== textState.font || previousState.fontSize !== textState.fontSize || previousState.fontName !== textState.fontName)) { + flushTextContentItem(); + } + break; + } + if (textContent.items.length >= (sink?.desiredSize ?? 1)) { + stop = true; + break; + } + } + if (stop) { + next(deferred); + return; + } + flushTextContentItem(); + enqueueChunk(); + resolve2(); + }).catch((reason) => { + if (reason instanceof AbortException3) { + return; + } + if (this.options.ignoreErrors) { + warn2(`getTextContent - ignoring errors during "${task.name}" task: "${reason}".`); + flushTextContentItem(); + enqueueChunk(); + return; + } + throw reason; + }); + } + async extractDataStructures(dict, properties) { + const xref = this.xref; + let cidToGidBytes; + const toUnicodePromise = this.readToUnicode(properties.toUnicode); + if (properties.composite) { + const cidSystemInfo = dict.get("CIDSystemInfo"); + if (cidSystemInfo instanceof Dict) { + properties.cidSystemInfo = { + registry: stringToPDFString(cidSystemInfo.get("Registry")), + ordering: stringToPDFString(cidSystemInfo.get("Ordering")), + supplement: cidSystemInfo.get("Supplement") + }; + } + try { + const cidToGidMap = dict.get("CIDToGIDMap"); + if (cidToGidMap instanceof BaseStream) { + cidToGidBytes = cidToGidMap.getBytes(); + } + } catch (ex) { + if (!this.options.ignoreErrors) { + throw ex; + } + warn2(`extractDataStructures - ignoring CIDToGIDMap data: "${ex}".`); + } + } + const differences = []; + let baseEncodingName = null; + let encoding; + if (dict.has("Encoding")) { + encoding = dict.get("Encoding"); + if (encoding instanceof Dict) { + baseEncodingName = encoding.get("BaseEncoding"); + baseEncodingName = baseEncodingName instanceof Name2 ? baseEncodingName.name : null; + if (encoding.has("Differences")) { + const diffEncoding = encoding.get("Differences"); + let index2 = 0; + for (const entry of diffEncoding) { + const data = xref.fetchIfRef(entry); + if (typeof data === "number") { + index2 = data; + } else if (data instanceof Name2) { + differences[index2++] = data.name; + } else { + throw new FormatError3(`Invalid entry in 'Differences' array: ${data}`); + } + } + } + } else if (encoding instanceof Name2) { + baseEncodingName = encoding.name; + } else { + const msg = "Encoding is not a Name nor a Dict"; + if (!this.options.ignoreErrors) { + throw new FormatError3(msg); + } + warn2(msg); + } + if (baseEncodingName !== "MacRomanEncoding" && baseEncodingName !== "MacExpertEncoding" && baseEncodingName !== "WinAnsiEncoding") { + baseEncodingName = null; + } + } + const nonEmbeddedFont = !properties.file || properties.isInternalFont, isSymbolsFontName = getSymbolsFonts()[properties.name]; + if (baseEncodingName && nonEmbeddedFont && isSymbolsFontName) { + baseEncodingName = null; + } + if (baseEncodingName) { + properties.defaultEncoding = getEncoding(baseEncodingName); + } else { + let isSymbolicFont = !!(properties.flags & FontFlags.Symbolic); + const isNonsymbolicFont = !!(properties.flags & FontFlags.Nonsymbolic); + if (properties.type === "TrueType" && isSymbolicFont && isNonsymbolicFont && differences.length !== 0) { + properties.flags &= ~FontFlags.Symbolic; + isSymbolicFont = false; + } + encoding = StandardEncoding; + if (properties.type === "TrueType" && !isNonsymbolicFont) { + encoding = WinAnsiEncoding; + } + if (isSymbolicFont || isSymbolsFontName) { + encoding = MacRomanEncoding; + if (nonEmbeddedFont) { + if (/Symbol/i.test(properties.name)) { + encoding = SymbolSetEncoding; + } else if (/Dingbats/i.test(properties.name)) { + encoding = ZapfDingbatsEncoding; + } else if (/Wingdings/i.test(properties.name)) { + encoding = WinAnsiEncoding; + } + } + } + properties.defaultEncoding = encoding; + } + properties.differences = differences; + properties.baseEncodingName = baseEncodingName; + properties.hasEncoding = !!baseEncodingName || differences.length > 0; + properties.dict = dict; + properties.toUnicode = await toUnicodePromise; + const builtToUnicode = await this.buildToUnicode(properties); + properties.toUnicode = builtToUnicode; + if (cidToGidBytes) { + properties.cidToGidMap = this.readCidToGidMap(cidToGidBytes, builtToUnicode); + } + return properties; + } + _simpleFontToUnicode(properties, forceGlyphs = false) { + assert3(!properties.composite, "Must be a simple font."); + const toUnicode = []; + const encoding = properties.defaultEncoding.slice(); + const baseEncodingName = properties.baseEncodingName; + const differences = properties.differences; + for (const charcode in differences) { + const glyphName = differences[charcode]; + if (glyphName === ".notdef") { + continue; + } + encoding[charcode] = glyphName; + } + const glyphsUnicodeMap = getGlyphsUnicode(); + for (const charcode in encoding) { + let glyphName = encoding[charcode]; + if (glyphName === "") { + continue; + } + let unicode = glyphsUnicodeMap[glyphName]; + if (unicode !== void 0) { + toUnicode[charcode] = String.fromCharCode(unicode); + continue; + } + let code = 0; + switch (glyphName[0]) { + case "G": + if (glyphName.length === 3) { + code = parseInt(glyphName.substring(1), 16); + } + break; + case "g": + if (glyphName.length === 5) { + code = parseInt(glyphName.substring(1), 16); + } + break; + case "C": + case "c": + if (glyphName.length >= 3 && glyphName.length <= 4) { + const codeStr = glyphName.substring(1); + if (forceGlyphs) { + code = parseInt(codeStr, 16); + break; + } + code = +codeStr; + if (Number.isNaN(code) && Number.isInteger(parseInt(codeStr, 16))) { + return this._simpleFontToUnicode(properties, true); + } + } + break; + case "u": + unicode = getUnicodeForGlyph(glyphName, glyphsUnicodeMap); + if (unicode !== -1) { + code = unicode; + } + break; + default: + switch (glyphName) { + case "f_h": + case "f_t": + case "T_h": + toUnicode[charcode] = glyphName.replaceAll("_", ""); + continue; + } + break; + } + if (code > 0 && code <= 1114111 && Number.isInteger(code)) { + if (baseEncodingName && code === +charcode) { + const baseEncoding = getEncoding(baseEncodingName); + if (baseEncoding && (glyphName = baseEncoding[charcode])) { + toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]); + continue; + } + } + toUnicode[charcode] = String.fromCodePoint(code); + } + } + return toUnicode; + } + async buildToUnicode(properties) { + properties.hasIncludedToUnicodeMap = properties.toUnicode?.length > 0; + if (properties.hasIncludedToUnicodeMap) { + if (!properties.composite && properties.hasEncoding) { + properties.fallbackToUnicode = this._simpleFontToUnicode(properties); + } + return properties.toUnicode; + } + if (!properties.composite) { + return new ToUnicodeMap(this._simpleFontToUnicode(properties)); + } + if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof IdentityCMap) || properties.cidSystemInfo?.registry === "Adobe" && (properties.cidSystemInfo.ordering === "GB1" || properties.cidSystemInfo.ordering === "CNS1" || properties.cidSystemInfo.ordering === "Japan1" || properties.cidSystemInfo.ordering === "Korea1"))) { + const { + registry: registry2, + ordering + } = properties.cidSystemInfo; + const ucs2CMapName = Name2.get(`${registry2}-${ordering}-UCS2`); + const ucs2CMap = await CMapFactory.create({ + encoding: ucs2CMapName, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + const toUnicode = [], buf = []; + properties.cMap.forEach(function(charcode, cid) { + if (cid > 65535) { + throw new FormatError3("Max size of CID is 65,535"); + } + const ucs2 = ucs2CMap.lookup(cid); + if (ucs2) { + buf.length = 0; + for (let i = 0, ii = ucs2.length; i < ii; i += 2) { + buf.push((ucs2.charCodeAt(i) << 8) + ucs2.charCodeAt(i + 1)); + } + toUnicode[charcode] = String.fromCharCode(...buf); + } + }); + return new ToUnicodeMap(toUnicode); + } + return new IdentityToUnicodeMap(properties.firstChar, properties.lastChar); + } + async readToUnicode(cmapObj) { + if (!cmapObj) { + return null; + } + if (cmapObj instanceof Name2) { + const cmap = await CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 65535); + } + return new ToUnicodeMap(cmap.getMap()); + } + if (cmapObj instanceof BaseStream) { + try { + const cmap = await CMapFactory.create({ + encoding: cmapObj, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + if (cmap instanceof IdentityCMap) { + return new IdentityToUnicodeMap(0, 65535); + } + const map3 = new Array(cmap.length); + cmap.forEach(function(charCode, token) { + if (typeof token === "number") { + map3[charCode] = String.fromCodePoint(token); + return; + } + if (token.length % 2 !== 0) { + token = "\0" + token; + } + const str = []; + for (let k = 0; k < token.length; k += 2) { + const w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + if ((w1 & 63488) !== 55296) { + str.push(w1); + continue; + } + k += 2; + const w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1); + str.push(((w1 & 1023) << 10) + (w2 & 1023) + 65536); + } + map3[charCode] = String.fromCodePoint(...str); + }); + return new ToUnicodeMap(map3); + } catch (reason) { + if (reason instanceof AbortException3) { + return null; + } + if (this.options.ignoreErrors) { + warn2(`readToUnicode - ignoring ToUnicode data: "${reason}".`); + return null; + } + throw reason; + } + } + return null; + } + readCidToGidMap(glyphsData, toUnicode) { + const result2 = []; + for (let j = 0, jj = glyphsData.length; j < jj; j++) { + const glyphID = glyphsData[j++] << 8 | glyphsData[j]; + const code = j >> 1; + if (glyphID === 0 && !toUnicode.has(code)) { + continue; + } + result2[code] = glyphID; + } + return result2; + } + extractWidths(dict, descriptor, properties) { + const xref = this.xref; + let glyphsWidths = []; + let defaultWidth = 0; + const glyphsVMetrics = []; + let defaultVMetrics; + if (properties.composite) { + const dw = dict.get("DW"); + defaultWidth = typeof dw === "number" ? Math.ceil(dw) : 1e3; + const widths = dict.get("W"); + if (Array.isArray(widths)) { + for (let i = 0, ii = widths.length; i < ii; i++) { + let start = xref.fetchIfRef(widths[i++]); + if (!Number.isInteger(start)) { + break; + } + const code = xref.fetchIfRef(widths[i]); + if (Array.isArray(code)) { + for (const c of code) { + const width = xref.fetchIfRef(c); + if (typeof width === "number") { + glyphsWidths[start] = width; + } + start++; + } + } else if (Number.isInteger(code)) { + const width = xref.fetchIfRef(widths[++i]); + if (typeof width !== "number") { + continue; + } + for (let j = start; j <= code; j++) { + glyphsWidths[j] = width; + } + } else { + break; + } + } + } + if (properties.vertical) { + const dw2 = dict.getArray("DW2"); + let vmetrics = isNumberArray(dw2, 2) ? dw2 : [880, -1e3]; + defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]]; + vmetrics = dict.get("W2"); + if (Array.isArray(vmetrics)) { + for (let i = 0, ii = vmetrics.length; i < ii; i++) { + let start = xref.fetchIfRef(vmetrics[i++]); + if (!Number.isInteger(start)) { + break; + } + const code = xref.fetchIfRef(vmetrics[i]); + if (Array.isArray(code)) { + for (let j = 0, jj = code.length; j < jj; j++) { + const vmetric = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])]; + if (isNumberArray(vmetric, null)) { + glyphsVMetrics[start] = vmetric; + } + start++; + } + } else if (Number.isInteger(code)) { + const vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])]; + if (!isNumberArray(vmetric, null)) { + continue; + } + for (let j = start; j <= code; j++) { + glyphsVMetrics[j] = vmetric; + } + } else { + break; + } + } + } + } + } else { + const widths = dict.get("Widths"); + if (Array.isArray(widths)) { + let j = properties.firstChar; + for (const w of widths) { + const width = xref.fetchIfRef(w); + if (typeof width === "number") { + glyphsWidths[j] = width; + } + j++; + } + const missingWidth = descriptor.get("MissingWidth"); + defaultWidth = typeof missingWidth === "number" ? missingWidth : 0; + } else { + const baseFontName = dict.get("BaseFont"); + if (baseFontName instanceof Name2) { + const metrics2 = this.getBaseFontMetrics(baseFontName.name); + glyphsWidths = this.buildCharCodeToWidth(metrics2.widths, properties); + defaultWidth = metrics2.defaultWidth; + } + } + } + let isMonospace = true; + let firstWidth = defaultWidth; + for (const glyph in glyphsWidths) { + const glyphWidth = glyphsWidths[glyph]; + if (!glyphWidth) { + continue; + } + if (!firstWidth) { + firstWidth = glyphWidth; + continue; + } + if (firstWidth !== glyphWidth) { + isMonospace = false; + break; + } + } + if (isMonospace) { + properties.flags |= FontFlags.FixedPitch; + } else { + properties.flags &= ~FontFlags.FixedPitch; + } + properties.defaultWidth = defaultWidth; + properties.widths = glyphsWidths; + properties.defaultVMetrics = defaultVMetrics; + properties.vmetrics = glyphsVMetrics; + } + isSerifFont(baseFontName) { + const fontNameWoStyle = baseFontName.split("-", 1)[0]; + return fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle); + } + getBaseFontMetrics(name) { + let defaultWidth = 0; + let widths = /* @__PURE__ */ Object.create(null); + let monospace = false; + const stdFontMap = getStdFontMap(); + let lookupName = stdFontMap[name] || name; + const Metrics = getMetrics(); + if (!(lookupName in Metrics)) { + lookupName = this.isSerifFont(name) ? "Times-Roman" : "Helvetica"; + } + const glyphWidths = Metrics[lookupName]; + if (typeof glyphWidths === "number") { + defaultWidth = glyphWidths; + monospace = true; + } else { + widths = glyphWidths(); + } + return { + defaultWidth, + monospace, + widths + }; + } + buildCharCodeToWidth(widthsByGlyphName, properties) { + const widths = /* @__PURE__ */ Object.create(null); + const differences = properties.differences; + const encoding = properties.defaultEncoding; + for (let charCode = 0; charCode < 256; charCode++) { + if (charCode in differences && widthsByGlyphName[differences[charCode]]) { + widths[charCode] = widthsByGlyphName[differences[charCode]]; + continue; + } + if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) { + widths[charCode] = widthsByGlyphName[encoding[charCode]]; + continue; + } + } + return widths; + } + preEvaluateFont(dict) { + const baseDict = dict; + let type = dict.get("Subtype"); + if (!(type instanceof Name2)) { + throw new FormatError3("invalid font Subtype"); + } + let composite = false; + let hash2; + if (type.name === "Type0") { + const df = dict.get("DescendantFonts"); + if (!df) { + throw new FormatError3("Descendant fonts are not specified"); + } + dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df; + if (!(dict instanceof Dict)) { + throw new FormatError3("Descendant font is not a dictionary."); + } + type = dict.get("Subtype"); + if (!(type instanceof Name2)) { + throw new FormatError3("invalid font Subtype"); + } + composite = true; + } + let firstChar = dict.get("FirstChar"); + if (!Number.isInteger(firstChar)) { + firstChar = 0; + } + let lastChar = dict.get("LastChar"); + if (!Number.isInteger(lastChar)) { + lastChar = composite ? 65535 : 255; + } + const descriptor = dict.get("FontDescriptor"); + const toUnicode = dict.get("ToUnicode") || baseDict.get("ToUnicode"); + if (descriptor) { + hash2 = new MurmurHash3_642(); + const encoding = baseDict.getRaw("Encoding"); + if (encoding instanceof Name2) { + hash2.update(encoding.name); + } else if (encoding instanceof Ref) { + hash2.update(encoding.toString()); + } else if (encoding instanceof Dict) { + for (const entry of encoding.getRawValues()) { + if (entry instanceof Name2) { + hash2.update(entry.name); + } else if (entry instanceof Ref) { + hash2.update(entry.toString()); + } else if (Array.isArray(entry)) { + const diffLength = entry.length, diffBuf = new Array(diffLength); + for (let j = 0; j < diffLength; j++) { + const diffEntry = entry[j]; + if (diffEntry instanceof Name2) { + diffBuf[j] = diffEntry.name; + } else if (typeof diffEntry === "number" || diffEntry instanceof Ref) { + diffBuf[j] = diffEntry.toString(); + } + } + hash2.update(diffBuf.join()); + } + } + } + hash2.update(`${firstChar}-${lastChar}`); + if (toUnicode instanceof BaseStream) { + const stream = toUnicode.str || toUnicode; + const uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start); + hash2.update(uint8array); + } else if (toUnicode instanceof Name2) { + hash2.update(toUnicode.name); + } + const widths = dict.get("Widths") || baseDict.get("Widths"); + if (Array.isArray(widths)) { + const widthsBuf = []; + for (const entry of widths) { + if (typeof entry === "number" || entry instanceof Ref) { + widthsBuf.push(entry.toString()); + } + } + hash2.update(widthsBuf.join()); + } + if (composite) { + hash2.update("compositeFont"); + const compositeWidths = dict.get("W") || baseDict.get("W"); + if (Array.isArray(compositeWidths)) { + const widthsBuf = []; + for (const entry of compositeWidths) { + if (typeof entry === "number" || entry instanceof Ref) { + widthsBuf.push(entry.toString()); + } else if (Array.isArray(entry)) { + const subWidthsBuf = []; + for (const element of entry) { + if (typeof element === "number" || element instanceof Ref) { + subWidthsBuf.push(element.toString()); + } + } + widthsBuf.push(`[${subWidthsBuf.join()}]`); + } + } + hash2.update(widthsBuf.join()); + } + const cidToGidMap = dict.getRaw("CIDToGIDMap") || baseDict.getRaw("CIDToGIDMap"); + if (cidToGidMap instanceof Name2) { + hash2.update(cidToGidMap.name); + } else if (cidToGidMap instanceof Ref) { + hash2.update(cidToGidMap.toString()); + } else if (cidToGidMap instanceof BaseStream) { + hash2.update(cidToGidMap.peekBytes()); + } + } + } + return { + descriptor, + dict, + baseDict, + composite, + type: type.name, + firstChar, + lastChar, + toUnicode, + hash: hash2 ? hash2.hexdigest() : "" + }; + } + async translateFont({ + descriptor, + dict, + baseDict, + composite, + type, + firstChar, + lastChar, + toUnicode, + cssFontInfo + }) { + const isType3Font = type === "Type3"; + if (!descriptor) { + if (isType3Font) { + descriptor = Dict.empty; + } else { + let baseFontName = dict.get("BaseFont"); + if (!(baseFontName instanceof Name2)) { + throw new FormatError3("Base font is not specified"); + } + baseFontName = baseFontName.name.replaceAll(/[,_]/g, "-"); + const metrics2 = this.getBaseFontMetrics(baseFontName); + const fontNameWoStyle = baseFontName.split("-", 1)[0]; + const flags2 = (this.isSerifFont(fontNameWoStyle) ? FontFlags.Serif : 0) | (metrics2.monospace ? FontFlags.FixedPitch : 0) | (getSymbolsFonts()[fontNameWoStyle] ? FontFlags.Symbolic : FontFlags.Nonsymbolic); + const properties2 = { + type, + name: baseFontName, + loadedName: baseDict.loadedName, + systemFontInfo: null, + widths: metrics2.widths, + defaultWidth: metrics2.defaultWidth, + isSimulatedFlags: true, + flags: flags2, + firstChar, + lastChar, + toUnicode, + xHeight: 0, + capHeight: 0, + italicAngle: 0, + isType3Font + }; + const widths = dict.get("Widths"); + const standardFontName = getStandardFontName(baseFontName); + let file2 = null; + if (standardFontName) { + file2 = await this.fetchStandardFontData(standardFontName); + properties2.isInternalFont = !!file2; + } + if (!properties2.isInternalFont && this.options.useSystemFonts) { + properties2.systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, baseFontName, standardFontName, type); + } + const newProperties2 = await this.extractDataStructures(dict, properties2); + if (Array.isArray(widths)) { + const glyphWidths = []; + let j = firstChar; + for (const w of widths) { + const width = this.xref.fetchIfRef(w); + if (typeof width === "number") { + glyphWidths[j] = width; + } + j++; + } + newProperties2.widths = glyphWidths; + } else { + newProperties2.widths = this.buildCharCodeToWidth(metrics2.widths, newProperties2); + } + return new Font(baseFontName, file2, newProperties2, this.options); + } + } + let fontName = descriptor.get("FontName"); + let baseFont = dict.get("BaseFont"); + if (typeof fontName === "string") { + fontName = Name2.get(fontName); + } + if (typeof baseFont === "string") { + baseFont = Name2.get(baseFont); + } + const fontNameStr = fontName?.name; + const baseFontStr = baseFont?.name; + if (isType3Font) { + if (!fontNameStr) { + fontName = Name2.get(type); + } + } else if (fontNameStr !== baseFontStr) { + info2(`The FontDescriptor's FontName is "${fontNameStr}" but should be the same as the Font's BaseFont "${baseFontStr}".`); + if (fontNameStr && baseFontStr && (baseFontStr.startsWith(fontNameStr) || !isKnownFontName(fontNameStr) && isKnownFontName(baseFontStr))) { + fontName = null; + } + fontName ||= baseFont; + } + if (!(fontName instanceof Name2)) { + throw new FormatError3("invalid font name"); + } + let fontFile, subtype, length1, length2, length3; + try { + fontFile = descriptor.get("FontFile", "FontFile2", "FontFile3"); + if (fontFile) { + if (!(fontFile instanceof BaseStream)) { + throw new FormatError3("FontFile should be a stream"); + } else if (fontFile.isEmpty) { + throw new FormatError3("FontFile is empty"); + } + } + } catch (ex) { + if (!this.options.ignoreErrors) { + throw ex; + } + warn2(`translateFont - fetching "${fontName.name}" font file: "${ex}".`); + fontFile = null; + } + let isInternalFont = false; + let glyphScaleFactors = null; + let systemFontInfo = null; + if (fontFile) { + if (fontFile.dict) { + const subtypeEntry = fontFile.dict.get("Subtype"); + if (subtypeEntry instanceof Name2) { + subtype = subtypeEntry.name; + } + length1 = fontFile.dict.get("Length1"); + length2 = fontFile.dict.get("Length2"); + length3 = fontFile.dict.get("Length3"); + } + } else if (cssFontInfo) { + const standardFontName = getXfaFontName(fontName.name); + if (standardFontName) { + cssFontInfo.fontFamily = `${cssFontInfo.fontFamily}-PdfJS-XFA`; + cssFontInfo.metrics = standardFontName.metrics || null; + glyphScaleFactors = standardFontName.factors || null; + fontFile = await this.fetchStandardFontData(standardFontName.name); + isInternalFont = !!fontFile; + baseDict = dict = getXfaFontDict(fontName.name); + composite = true; + } + } else if (!isType3Font) { + const standardFontName = getStandardFontName(fontName.name); + if (standardFontName) { + fontFile = await this.fetchStandardFontData(standardFontName); + isInternalFont = !!fontFile; + } + if (!isInternalFont && this.options.useSystemFonts) { + systemFontInfo = getFontSubstitution(this.systemFontCache, this.idFactory, this.options.standardFontDataUrl, fontName.name, standardFontName, type); + } + } + const fontMatrix = lookupMatrix(dict.getArray("FontMatrix"), FONT_IDENTITY_MATRIX2); + const bbox = lookupNormalRect(descriptor.getArray("FontBBox") || dict.getArray("FontBBox"), isType3Font ? [0, 0, 0, 0] : void 0); + let ascent = descriptor.get("Ascent"); + if (typeof ascent !== "number") { + ascent = void 0; + } + let descent = descriptor.get("Descent"); + if (typeof descent !== "number") { + descent = void 0; + } + let xHeight = descriptor.get("XHeight"); + if (typeof xHeight !== "number") { + xHeight = 0; + } + let capHeight = descriptor.get("CapHeight"); + if (typeof capHeight !== "number") { + capHeight = 0; + } + let flags = descriptor.get("Flags"); + if (!Number.isInteger(flags)) { + flags = 0; + } + let italicAngle = descriptor.get("ItalicAngle"); + if (typeof italicAngle !== "number") { + italicAngle = 0; + } + const properties = { + type, + name: fontName.name, + subtype, + file: fontFile, + length1, + length2, + length3, + isInternalFont, + loadedName: baseDict.loadedName, + composite, + fixedPitch: false, + fontMatrix, + firstChar, + lastChar, + toUnicode, + bbox, + ascent, + descent, + xHeight, + capHeight, + flags, + italicAngle, + isType3Font, + cssFontInfo, + scaleFactors: glyphScaleFactors, + systemFontInfo + }; + if (composite) { + const cidEncoding = baseDict.get("Encoding"); + if (cidEncoding instanceof Name2) { + properties.cidEncoding = cidEncoding.name; + } + const cMap = await CMapFactory.create({ + encoding: cidEncoding, + fetchBuiltInCMap: this._fetchBuiltInCMapBound, + useCMap: null + }); + properties.cMap = cMap; + properties.vertical = properties.cMap.vertical; + } + const newProperties = await this.extractDataStructures(dict, properties); + this.extractWidths(dict, descriptor, newProperties); + return new Font(fontName.name, fontFile, newProperties, this.options); + } + static buildFontPaths(font, glyphs, handler, evaluatorOptions) { + function buildPath(fontChar) { + const glyphName = `${font.loadedName}_path_${fontChar}`; + try { + if (font.renderer.hasBuiltPath(fontChar)) { + return; + } + handler.send("commonobj", [glyphName, "FontPath", font.renderer.getPathJs(fontChar)]); + } catch (reason) { + if (evaluatorOptions.ignoreErrors) { + warn2(`buildFontPaths - ignoring ${glyphName} glyph: "${reason}".`); + return; + } + throw reason; + } + } + for (const glyph of glyphs) { + buildPath(glyph.fontChar); + const accent = glyph.accent; + if (accent?.fontChar) { + buildPath(accent.fontChar); + } + } + } + static get fallbackFontDict() { + const dict = new Dict(); + dict.set("BaseFont", Name2.get("Helvetica")); + dict.set("Type", Name2.get("FallbackType")); + dict.set("Subtype", Name2.get("FallbackType")); + dict.set("Encoding", Name2.get("WinAnsiEncoding")); + return shadow2(this, "fallbackFontDict", dict); + } + }; + TranslatedFont = class { + #sent = false; + #type3Loaded = null; + constructor({ + loadedName, + font, + dict + }) { + this.loadedName = loadedName; + this.font = font; + this.dict = dict; + this.type3Dependencies = font.isType3Font ? /* @__PURE__ */ new Set() : null; + } + send(handler) { + if (this.#sent) { + return; + } + this.#sent = true; + const fontData = this.font.exportData(); + const transfer = []; + if (fontData.data) { + if (fontData.data.charProcOperatorList) { + fontData.charProcOperatorList = fontData.data.charProcOperatorList; + } + fontData.data = FontInfo2.write(fontData.data); + transfer.push(fontData.data); + } + handler.send("commonobj", [this.loadedName, "Font", fontData], transfer); + } + fallback(handler, evaluatorOptions) { + if (!this.font.data) { + return; + } + this.font.disableFontFace = true; + PartialEvaluator.buildFontPaths(this.font, this.font.glyphCacheValues, handler, evaluatorOptions); + } + loadType3Data(evaluator, resources, task) { + if (this.#type3Loaded) { + return this.#type3Loaded; + } + const { + font, + type3Dependencies + } = this; + assert3(font.isType3Font, "Must be a Type3 font."); + const type3Evaluator = evaluator.clone({ + ignoreErrors: false + }); + const type3FontRefs = new RefSet(evaluator.type3FontRefs); + if (this.dict.objId && !type3FontRefs.has(this.dict.objId)) { + type3FontRefs.put(this.dict.objId); + } + type3Evaluator.type3FontRefs = type3FontRefs; + let loadCharProcsPromise = Promise.resolve(); + const charProcs = this.dict.get("CharProcs"); + const fontResources = this.dict.get("Resources") || resources; + const charProcOperatorList = /* @__PURE__ */ Object.create(null); + const [x0, y0, x1, y1] = font.bbox, width = x1 - x0, height = y1 - y0; + const fontBBoxSize = Math.hypot(width, height); + for (const key of charProcs.getKeys()) { + loadCharProcsPromise = loadCharProcsPromise.then(() => { + const glyphStream = charProcs.get(key); + const operatorList = new OperatorList(); + return type3Evaluator.getOperatorList({ + stream: glyphStream, + task, + resources: fontResources, + operatorList + }).then(() => { + switch (operatorList.fnArray[0]) { + case OPS2.setCharWidthAndBounds: + this.#removeType3ColorOperators(operatorList, fontBBoxSize); + break; + case OPS2.setCharWidth: + if (!fontBBoxSize) { + this.#guessType3FontBBox(operatorList); + } + break; + } + charProcOperatorList[key] = operatorList.getIR(); + for (const dependency of operatorList.dependencies) { + type3Dependencies.add(dependency); + } + }).catch(function(reason) { + warn2(`Type3 font resource "${key}" is not available.`); + const dummyOperatorList = new OperatorList(); + charProcOperatorList[key] = dummyOperatorList.getIR(); + }); + }); + } + this.#type3Loaded = loadCharProcsPromise.then(() => { + font.charProcOperatorList = charProcOperatorList; + if (this._bbox) { + font.isCharBBox = true; + font.bbox = this._bbox; + } + }); + return this.#type3Loaded; + } + #removeType3ColorOperators(operatorList, fontBBoxSize = NaN) { + const charBBox = Util2.normalizeRect(operatorList.argsArray[0].slice(2)), width = charBBox[2] - charBBox[0], height = charBBox[3] - charBBox[1]; + const charBBoxSize = Math.hypot(width, height); + if (width === 0 || height === 0) { + operatorList.fnArray.splice(0, 1); + operatorList.argsArray.splice(0, 1); + } else if (fontBBoxSize === 0 || Math.round(charBBoxSize / fontBBoxSize) >= 10) { + this._bbox ??= [Infinity, Infinity, -Infinity, -Infinity]; + Util2.rectBoundingBox(...charBBox, this._bbox); + } + let i = 0, ii = operatorList.length; + while (i < ii) { + switch (operatorList.fnArray[i]) { + case OPS2.setCharWidthAndBounds: + break; + case OPS2.setStrokeColorSpace: + case OPS2.setFillColorSpace: + case OPS2.setStrokeColor: + case OPS2.setStrokeColorN: + case OPS2.setFillColor: + case OPS2.setFillColorN: + case OPS2.setStrokeGray: + case OPS2.setFillGray: + case OPS2.setStrokeRGBColor: + case OPS2.setFillRGBColor: + case OPS2.setStrokeCMYKColor: + case OPS2.setFillCMYKColor: + case OPS2.shadingFill: + case OPS2.setRenderingIntent: + operatorList.fnArray.splice(i, 1); + operatorList.argsArray.splice(i, 1); + ii--; + continue; + case OPS2.setGState: + const [gStateObj] = operatorList.argsArray[i]; + let j = 0, jj = gStateObj.length; + while (j < jj) { + const [gStateKey] = gStateObj[j]; + switch (gStateKey) { + case "TR": + case "TR2": + case "HT": + case "BG": + case "BG2": + case "UCR": + case "UCR2": + gStateObj.splice(j, 1); + jj--; + continue; + } + j++; + } + break; + } + i++; + } + } + #guessType3FontBBox(operatorList) { + let i = 1; + const ii = operatorList.length; + while (i < ii) { + switch (operatorList.fnArray[i]) { + case OPS2.constructPath: + const minMax = operatorList.argsArray[i][2]; + this._bbox ??= [Infinity, Infinity, -Infinity, -Infinity]; + Util2.rectBoundingBox(...minMax, this._bbox); + break; + } + i++; + } + } + }; + StateManager = class { + constructor(initialState = new EvalState()) { + this.state = initialState; + this.stateStack = []; + } + save() { + const old = this.state; + this.stateStack.push(this.state); + this.state = old.clone(); + } + restore() { + const prev = this.stateStack.pop(); + if (prev) { + this.state = prev; + } + } + transform(args) { + this.state.ctm = Util2.transform(this.state.ctm, args); + } + }; + TextState = class { + constructor() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.fontName = null; + this.fontSize = 0; + this.loadedName = null; + this.font = null; + this.fontMatrix = FONT_IDENTITY_MATRIX2; + this.textMatrix = IDENTITY_MATRIX.slice(); + this.textLineMatrix = IDENTITY_MATRIX.slice(); + this.charSpacing = 0; + this.wordSpacing = 0; + this.leading = 0; + this.textHScale = 1; + this.textRise = 0; + } + setTextMatrix(a, b2, c, d, e, f) { + const m = this.textMatrix; + m[0] = a; + m[1] = b2; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + } + setTextLineMatrix(a, b2, c, d, e, f) { + const m = this.textLineMatrix; + m[0] = a; + m[1] = b2; + m[2] = c; + m[3] = d; + m[4] = e; + m[5] = f; + } + translateTextMatrix(x, y) { + const m = this.textMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + } + translateTextLineMatrix(x, y) { + const m = this.textLineMatrix; + m[4] = m[0] * x + m[2] * y + m[4]; + m[5] = m[1] * x + m[3] * y + m[5]; + } + carriageReturn() { + this.translateTextLineMatrix(0, -this.leading); + this.textMatrix = this.textLineMatrix.slice(); + } + clone() { + const clone3 = Object.create(this); + clone3.textMatrix = this.textMatrix.slice(); + clone3.textLineMatrix = this.textLineMatrix.slice(); + clone3.fontMatrix = this.fontMatrix.slice(); + return clone3; + } + }; + EvalState = class { + constructor() { + this.ctm = new Float32Array(IDENTITY_MATRIX); + this.font = null; + this.textRenderingMode = TextRenderingMode2.FILL; + this._fillColorSpace = this._strokeColorSpace = ColorSpaceUtils.gray; + this.patternFillColorSpace = null; + this.patternStrokeColorSpace = null; + this.currentPointX = this.currentPointY = 0; + this.pathMinMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + this.pathBuffer = []; + } + get fillColorSpace() { + return this._fillColorSpace; + } + set fillColorSpace(colorSpace) { + this._fillColorSpace = this.patternFillColorSpace = colorSpace; + } + get strokeColorSpace() { + return this._strokeColorSpace; + } + set strokeColorSpace(colorSpace) { + this._strokeColorSpace = this.patternStrokeColorSpace = colorSpace; + } + clone({ + newPath = false + } = {}) { + const clone3 = Object.create(this); + if (newPath) { + clone3.pathBuffer = []; + clone3.pathMinMax = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + } + return clone3; + } + }; + EvaluatorPreprocessor = class _EvaluatorPreprocessor { + static get opMap() { + return shadow2(this, "opMap", Object.assign(/* @__PURE__ */ Object.create(null), { + w: { + id: OPS2.setLineWidth, + numArgs: 1, + variableArgs: false + }, + J: { + id: OPS2.setLineCap, + numArgs: 1, + variableArgs: false + }, + j: { + id: OPS2.setLineJoin, + numArgs: 1, + variableArgs: false + }, + M: { + id: OPS2.setMiterLimit, + numArgs: 1, + variableArgs: false + }, + d: { + id: OPS2.setDash, + numArgs: 2, + variableArgs: false + }, + ri: { + id: OPS2.setRenderingIntent, + numArgs: 1, + variableArgs: false + }, + i: { + id: OPS2.setFlatness, + numArgs: 1, + variableArgs: false + }, + gs: { + id: OPS2.setGState, + numArgs: 1, + variableArgs: false + }, + q: { + id: OPS2.save, + numArgs: 0, + variableArgs: false + }, + Q: { + id: OPS2.restore, + numArgs: 0, + variableArgs: false + }, + cm: { + id: OPS2.transform, + numArgs: 6, + variableArgs: false + }, + m: { + id: OPS2.moveTo, + numArgs: 2, + variableArgs: false + }, + l: { + id: OPS2.lineTo, + numArgs: 2, + variableArgs: false + }, + c: { + id: OPS2.curveTo, + numArgs: 6, + variableArgs: false + }, + v: { + id: OPS2.curveTo2, + numArgs: 4, + variableArgs: false + }, + y: { + id: OPS2.curveTo3, + numArgs: 4, + variableArgs: false + }, + h: { + id: OPS2.closePath, + numArgs: 0, + variableArgs: false + }, + re: { + id: OPS2.rectangle, + numArgs: 4, + variableArgs: false + }, + S: { + id: OPS2.stroke, + numArgs: 0, + variableArgs: false + }, + s: { + id: OPS2.closeStroke, + numArgs: 0, + variableArgs: false + }, + f: { + id: OPS2.fill, + numArgs: 0, + variableArgs: false + }, + F: { + id: OPS2.fill, + numArgs: 0, + variableArgs: false + }, + "f*": { + id: OPS2.eoFill, + numArgs: 0, + variableArgs: false + }, + B: { + id: OPS2.fillStroke, + numArgs: 0, + variableArgs: false + }, + "B*": { + id: OPS2.eoFillStroke, + numArgs: 0, + variableArgs: false + }, + b: { + id: OPS2.closeFillStroke, + numArgs: 0, + variableArgs: false + }, + "b*": { + id: OPS2.closeEOFillStroke, + numArgs: 0, + variableArgs: false + }, + n: { + id: OPS2.endPath, + numArgs: 0, + variableArgs: false + }, + W: { + id: OPS2.clip, + numArgs: 0, + variableArgs: false + }, + "W*": { + id: OPS2.eoClip, + numArgs: 0, + variableArgs: false + }, + BT: { + id: OPS2.beginText, + numArgs: 0, + variableArgs: false + }, + ET: { + id: OPS2.endText, + numArgs: 0, + variableArgs: false + }, + Tc: { + id: OPS2.setCharSpacing, + numArgs: 1, + variableArgs: false + }, + Tw: { + id: OPS2.setWordSpacing, + numArgs: 1, + variableArgs: false + }, + Tz: { + id: OPS2.setHScale, + numArgs: 1, + variableArgs: false + }, + TL: { + id: OPS2.setLeading, + numArgs: 1, + variableArgs: false + }, + Tf: { + id: OPS2.setFont, + numArgs: 2, + variableArgs: false + }, + Tr: { + id: OPS2.setTextRenderingMode, + numArgs: 1, + variableArgs: false + }, + Ts: { + id: OPS2.setTextRise, + numArgs: 1, + variableArgs: false + }, + Td: { + id: OPS2.moveText, + numArgs: 2, + variableArgs: false + }, + TD: { + id: OPS2.setLeadingMoveText, + numArgs: 2, + variableArgs: false + }, + Tm: { + id: OPS2.setTextMatrix, + numArgs: 6, + variableArgs: false + }, + "T*": { + id: OPS2.nextLine, + numArgs: 0, + variableArgs: false + }, + Tj: { + id: OPS2.showText, + numArgs: 1, + variableArgs: false + }, + TJ: { + id: OPS2.showSpacedText, + numArgs: 1, + variableArgs: false + }, + "'": { + id: OPS2.nextLineShowText, + numArgs: 1, + variableArgs: false + }, + '"': { + id: OPS2.nextLineSetSpacingShowText, + numArgs: 3, + variableArgs: false + }, + d0: { + id: OPS2.setCharWidth, + numArgs: 2, + variableArgs: false + }, + d1: { + id: OPS2.setCharWidthAndBounds, + numArgs: 6, + variableArgs: false + }, + CS: { + id: OPS2.setStrokeColorSpace, + numArgs: 1, + variableArgs: false + }, + cs: { + id: OPS2.setFillColorSpace, + numArgs: 1, + variableArgs: false + }, + SC: { + id: OPS2.setStrokeColor, + numArgs: 4, + variableArgs: true + }, + SCN: { + id: OPS2.setStrokeColorN, + numArgs: 33, + variableArgs: true + }, + sc: { + id: OPS2.setFillColor, + numArgs: 4, + variableArgs: true + }, + scn: { + id: OPS2.setFillColorN, + numArgs: 33, + variableArgs: true + }, + G: { + id: OPS2.setStrokeGray, + numArgs: 1, + variableArgs: false + }, + g: { + id: OPS2.setFillGray, + numArgs: 1, + variableArgs: false + }, + RG: { + id: OPS2.setStrokeRGBColor, + numArgs: 3, + variableArgs: false + }, + rg: { + id: OPS2.setFillRGBColor, + numArgs: 3, + variableArgs: false + }, + K: { + id: OPS2.setStrokeCMYKColor, + numArgs: 4, + variableArgs: false + }, + k: { + id: OPS2.setFillCMYKColor, + numArgs: 4, + variableArgs: false + }, + sh: { + id: OPS2.shadingFill, + numArgs: 1, + variableArgs: false + }, + BI: { + id: OPS2.beginInlineImage, + numArgs: 0, + variableArgs: false + }, + ID: { + id: OPS2.beginImageData, + numArgs: 0, + variableArgs: false + }, + EI: { + id: OPS2.endInlineImage, + numArgs: 1, + variableArgs: false + }, + Do: { + id: OPS2.paintXObject, + numArgs: 1, + variableArgs: false + }, + MP: { + id: OPS2.markPoint, + numArgs: 1, + variableArgs: false + }, + DP: { + id: OPS2.markPointProps, + numArgs: 2, + variableArgs: false + }, + BMC: { + id: OPS2.beginMarkedContent, + numArgs: 1, + variableArgs: false + }, + BDC: { + id: OPS2.beginMarkedContentProps, + numArgs: 2, + variableArgs: false + }, + EMC: { + id: OPS2.endMarkedContent, + numArgs: 0, + variableArgs: false + }, + BX: { + id: OPS2.beginCompat, + numArgs: 0, + variableArgs: false + }, + EX: { + id: OPS2.endCompat, + numArgs: 0, + variableArgs: false + }, + BM: null, + BD: null, + true: null, + fa: null, + fal: null, + fals: null, + false: null, + nu: null, + nul: null, + null: null + })); + } + static MAX_INVALID_PATH_OPS = 10; + constructor(stream, xref, stateManager = new StateManager()) { + this.parser = new Parser({ + lexer: new Lexer(stream, _EvaluatorPreprocessor.opMap), + xref + }); + this.stateManager = stateManager; + this.nonProcessedArgs = []; + this._isPathOp = false; + this._numInvalidPathOPS = 0; + } + get savedStatesDepth() { + return this.stateManager.stateStack.length; + } + read(operation) { + let args = operation.args; + while (true) { + const obj2 = this.parser.getObj(); + if (obj2 instanceof Cmd) { + const cmd = obj2.cmd; + const opSpec = _EvaluatorPreprocessor.opMap[cmd]; + if (!opSpec) { + warn2(`Unknown command "${cmd}".`); + continue; + } + const fn = opSpec.id; + const numArgs = opSpec.numArgs; + let argsLength = args !== null ? args.length : 0; + if (!this._isPathOp) { + this._numInvalidPathOPS = 0; + } + this._isPathOp = fn >= OPS2.moveTo && fn <= OPS2.endPath; + if (!opSpec.variableArgs) { + if (argsLength !== numArgs) { + const nonProcessedArgs = this.nonProcessedArgs; + while (argsLength > numArgs) { + nonProcessedArgs.push(args.shift()); + argsLength--; + } + while (argsLength < numArgs && nonProcessedArgs.length !== 0) { + if (args === null) { + args = []; + } + args.unshift(nonProcessedArgs.pop()); + argsLength++; + } + } + if (argsLength < numArgs) { + const partialMsg = `command ${cmd}: expected ${numArgs} args, but received ${argsLength} args.`; + if (this._isPathOp && ++this._numInvalidPathOPS > _EvaluatorPreprocessor.MAX_INVALID_PATH_OPS) { + throw new FormatError3(`Invalid ${partialMsg}`); + } + warn2(`Skipping ${partialMsg}`); + if (args !== null) { + args.length = 0; + } + continue; + } + } else if (argsLength > numArgs) { + info2(`Command ${cmd}: expected [0, ${numArgs}] args, but received ${argsLength} args.`); + } + this.preprocessCommand(fn, args); + operation.fn = fn; + operation.args = args; + return true; + } + if (obj2 === EOF) { + return false; + } + if (obj2 !== null) { + if (args === null) { + args = []; + } + args.push(obj2); + if (args.length > 33) { + throw new FormatError3("Too many arguments"); + } + } + } + } + preprocessCommand(fn, args) { + switch (fn | 0) { + case OPS2.save: + this.stateManager.save(); + break; + case OPS2.restore: + this.stateManager.restore(); + break; + case OPS2.transform: + this.stateManager.transform(args); + break; + } + } + }; + DefaultAppearanceEvaluator = class extends EvaluatorPreprocessor { + constructor(str) { + super(new StringStream(str)); + } + parse() { + const operation = { + fn: 0, + args: [] + }; + const result2 = { + fontSize: 0, + fontName: "", + fontColor: new Uint8ClampedArray(3) + }; + try { + while (true) { + operation.args.length = 0; + if (!this.read(operation)) { + break; + } + if (this.savedStatesDepth !== 0) { + continue; + } + const { + fn, + args + } = operation; + switch (fn | 0) { + case OPS2.setFont: + const [fontName, fontSize] = args; + if (fontName instanceof Name2) { + result2.fontName = fontName.name; + } + if (typeof fontSize === "number" && fontSize > 0) { + result2.fontSize = fontSize; + } + break; + case OPS2.setFillRGBColor: + ColorSpaceUtils.rgb.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.setFillGray: + ColorSpaceUtils.gray.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.setFillCMYKColor: + ColorSpaceUtils.cmyk.getRgbItem(args, 0, result2.fontColor, 0); + break; + } + } + } catch (reason) { + warn2(`parseDefaultAppearance - ignoring errors: "${reason}".`); + } + return result2; + } + }; + AppearanceStreamEvaluator = class extends EvaluatorPreprocessor { + constructor(stream, evaluatorOptions, xref, globalColorSpaceCache) { + super(stream); + this.stream = stream; + this.evaluatorOptions = evaluatorOptions; + this.xref = xref; + this.globalColorSpaceCache = globalColorSpaceCache; + this.resources = stream.dict?.get("Resources"); + } + parse() { + const operation = { + fn: 0, + args: [] + }; + let result2 = { + scaleFactor: 1, + fontSize: 0, + fontName: "", + fontColor: new Uint8ClampedArray(3), + fillColorSpace: ColorSpaceUtils.gray + }; + let breakLoop = false; + const stack = []; + try { + while (true) { + operation.args.length = 0; + if (breakLoop || !this.read(operation)) { + break; + } + const { + fn, + args + } = operation; + switch (fn | 0) { + case OPS2.save: + stack.push({ + scaleFactor: result2.scaleFactor, + fontSize: result2.fontSize, + fontName: result2.fontName, + fontColor: result2.fontColor.slice(), + fillColorSpace: result2.fillColorSpace + }); + break; + case OPS2.restore: + result2 = stack.pop() || result2; + break; + case OPS2.setTextMatrix: + result2.scaleFactor *= Math.hypot(args[0], args[1]); + break; + case OPS2.setFont: + const [fontName, fontSize] = args; + if (fontName instanceof Name2) { + result2.fontName = fontName.name; + } + if (typeof fontSize === "number" && fontSize > 0) { + result2.fontSize = fontSize * result2.scaleFactor; + } + break; + case OPS2.setFillColorSpace: + result2.fillColorSpace = ColorSpaceUtils.parse({ + cs: args[0], + xref: this.xref, + resources: this.resources, + pdfFunctionFactory: this._pdfFunctionFactory, + globalColorSpaceCache: this.globalColorSpaceCache, + localColorSpaceCache: this._localColorSpaceCache + }); + break; + case OPS2.setFillColor: + const cs = result2.fillColorSpace; + cs.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.setFillRGBColor: + ColorSpaceUtils.rgb.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.setFillGray: + ColorSpaceUtils.gray.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.setFillCMYKColor: + ColorSpaceUtils.cmyk.getRgbItem(args, 0, result2.fontColor, 0); + break; + case OPS2.showText: + case OPS2.showSpacedText: + case OPS2.nextLineShowText: + case OPS2.nextLineSetSpacingShowText: + breakLoop = true; + break; + } + } + } catch (reason) { + warn2(`parseAppearanceStream - ignoring errors: "${reason}".`); + } + this.stream.reset(); + delete result2.scaleFactor; + delete result2.fillColorSpace; + return result2; + } + get _localColorSpaceCache() { + return shadow2(this, "_localColorSpaceCache", new LocalColorSpaceCache()); + } + get _pdfFunctionFactory() { + const pdfFunctionFactory = new PDFFunctionFactory({ + xref: this.xref, + isEvalSupported: this.evaluatorOptions.isEvalSupported + }); + return shadow2(this, "_pdfFunctionFactory", pdfFunctionFactory); + } + }; + FakeUnicodeFont = class _FakeUnicodeFont { + constructor(xref, fontFamily) { + this.xref = xref; + this.widths = null; + this.firstChar = Infinity; + this.lastChar = -Infinity; + this.fontFamily = fontFamily; + const canvas = new OffscreenCanvas(1, 1); + this.ctxMeasure = canvas.getContext("2d", { + willReadFrequently: true + }); + if (!_FakeUnicodeFont._fontNameId) { + _FakeUnicodeFont._fontNameId = 1; + } + this.fontName = Name2.get(`InvalidPDFjsFont_${fontFamily}_${_FakeUnicodeFont._fontNameId++}`); + } + get fontDescriptorRef() { + if (!_FakeUnicodeFont._fontDescriptorRef) { + const fontDescriptor = new Dict(this.xref); + fontDescriptor.setIfName("Type", "FontDescriptor"); + fontDescriptor.set("FontName", this.fontName); + fontDescriptor.set("FontFamily", "MyriadPro Regular"); + fontDescriptor.set("FontBBox", [0, 0, 0, 0]); + fontDescriptor.setIfName("FontStretch", "Normal"); + fontDescriptor.set("FontWeight", 400); + fontDescriptor.set("ItalicAngle", 0); + _FakeUnicodeFont._fontDescriptorRef = this.xref.getNewPersistentRef(fontDescriptor); + } + return _FakeUnicodeFont._fontDescriptorRef; + } + get descendantFontRef() { + const descendantFont = new Dict(this.xref); + descendantFont.set("BaseFont", this.fontName); + descendantFont.setIfName("Type", "Font"); + descendantFont.setIfName("Subtype", "CIDFontType0"); + descendantFont.setIfName("CIDToGIDMap", "Identity"); + descendantFont.set("FirstChar", this.firstChar); + descendantFont.set("LastChar", this.lastChar); + descendantFont.set("FontDescriptor", this.fontDescriptorRef); + descendantFont.set("DW", 1e3); + const widths = []; + const chars2 = [...this.widths.entries()].sort(); + let currentChar = null; + let currentWidths = null; + for (const [char2, width] of chars2) { + if (!currentChar) { + currentChar = char2; + currentWidths = [width]; + continue; + } + if (char2 === currentChar + currentWidths.length) { + currentWidths.push(width); + } else { + widths.push(currentChar, currentWidths); + currentChar = char2; + currentWidths = [width]; + } + } + if (currentChar) { + widths.push(currentChar, currentWidths); + } + descendantFont.set("W", widths); + const cidSystemInfo = new Dict(this.xref); + cidSystemInfo.set("Ordering", "Identity"); + cidSystemInfo.set("Registry", "Adobe"); + cidSystemInfo.set("Supplement", 0); + descendantFont.set("CIDSystemInfo", cidSystemInfo); + return this.xref.getNewPersistentRef(descendantFont); + } + get baseFontRef() { + const baseFont = new Dict(this.xref); + baseFont.set("BaseFont", this.fontName); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type0"); + baseFont.setIfName("Encoding", "Identity-H"); + baseFont.set("DescendantFonts", [this.descendantFontRef]); + baseFont.setIfName("ToUnicode", "Identity-H"); + return this.xref.getNewPersistentRef(baseFont); + } + get resources() { + const resources = new Dict(this.xref); + const font = new Dict(this.xref); + font.set(this.fontName.name, this.baseFontRef); + resources.set("Font", font); + return resources; + } + _createContext() { + this.widths = /* @__PURE__ */ new Map(); + this.ctxMeasure.font = `1000px ${this.fontFamily}`; + return this.ctxMeasure; + } + createFontResources(text2) { + const ctx = this._createContext(); + for (const line2 of text2.split(/\r\n?|\n/)) { + for (const char2 of line2.split("")) { + const code = char2.charCodeAt(0); + if (this.widths.has(code)) { + continue; + } + const metrics2 = ctx.measureText(char2); + const width = Math.ceil(metrics2.width); + this.widths.set(code, width); + this.firstChar = Math.min(code, this.firstChar); + this.lastChar = Math.max(code, this.lastChar); + } + } + return this.resources; + } + static getFirstPositionInfo(rect, rotation, fontSize) { + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + const lineHeight = LINE_FACTOR2 * fontSize; + const lineDescent = LINE_DESCENT_FACTOR2 * fontSize; + return { + coords: [0, h + lineDescent - lineHeight], + bbox: [0, 0, w, h], + matrix: rotation !== 0 ? getRotationMatrix(rotation, h, lineHeight) : void 0 + }; + } + createAppearance(text2, rect, rotation, fontSize, bgColor, strokeAlpha) { + const ctx = this._createContext(); + const lines = []; + let maxWidth = -Infinity; + for (const line2 of text2.split(/\r\n?|\n/)) { + lines.push(line2); + const lineWidth = ctx.measureText(line2).width; + maxWidth = Math.max(maxWidth, lineWidth); + for (const code of codePointIter(line2)) { + const char2 = String.fromCodePoint(code); + let width = this.widths.get(code); + if (width === void 0) { + const metrics2 = ctx.measureText(char2); + width = Math.ceil(metrics2.width); + this.widths.set(code, width); + this.firstChar = Math.min(code, this.firstChar); + this.lastChar = Math.max(code, this.lastChar); + } + } + } + maxWidth *= fontSize / 1e3; + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + let hscale = 1; + if (maxWidth > w) { + hscale = w / maxWidth; + } + let vscale = 1; + const lineHeight = LINE_FACTOR2 * fontSize; + const lineDescent = LINE_DESCENT_FACTOR2 * fontSize; + const maxHeight = lineHeight * lines.length; + if (maxHeight > h) { + vscale = h / maxHeight; + } + const fscale = Math.min(hscale, vscale); + const newFontSize = fontSize * fscale; + const buffer2 = ["q", `0 0 ${numberToString(w)} ${numberToString(h)} re W n`, `BT`, `1 0 0 1 0 ${numberToString(h + lineDescent)} Tm 0 Tc ${getPdfColor(bgColor, true)}`, `/${this.fontName.name} ${numberToString(newFontSize)} Tf`]; + const { + resources + } = this; + strokeAlpha = typeof strokeAlpha === "number" && strokeAlpha >= 0 && strokeAlpha <= 1 ? strokeAlpha : 1; + if (strokeAlpha !== 1) { + buffer2.push("/R0 gs"); + const extGState = new Dict(this.xref); + const r0 = new Dict(this.xref); + r0.set("ca", strokeAlpha); + r0.set("CA", strokeAlpha); + r0.setIfName("Type", "ExtGState"); + extGState.set("R0", r0); + resources.set("ExtGState", extGState); + } + const vShift = numberToString(lineHeight); + for (const line2 of lines) { + buffer2.push(`0 -${vShift} Td <${stringToUTF16HexString(line2)}> Tj`); + } + buffer2.push("ET", "Q"); + const appearance = buffer2.join("\n"); + const appearanceStreamDict = new Dict(this.xref); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", [0, 0, w, h]); + appearanceStreamDict.set("Length", appearance.length); + appearanceStreamDict.set("Resources", resources); + if (rotation) { + const matrix = getRotationMatrix(rotation, w, h); + appearanceStreamDict.set("Matrix", matrix); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + }; + DateFormats = ["m/d", "m/d/yy", "mm/dd/yy", "mm/yy", "d-mmm", "d-mmm-yy", "dd-mmm-yy", "yy-mm-dd", "mmm-yy", "mmmm-yy", "mmm d, yyyy", "mmmm d, yyyy", "m/d/yy h:MM tt", "m/d/yy HH:MM"]; + TimeFormats = ["HH:MM", "h:MM tt", "HH:MM:ss", "h:MM:ss tt"]; + NameOrNumberTree = class { + constructor(root2, xref, type) { + this.root = root2; + this.xref = xref; + this._type = type; + } + getAll() { + const map3 = /* @__PURE__ */ new Map(); + if (!this.root) { + return map3; + } + const xref = this.xref; + const processed = new RefSet(); + processed.put(this.root); + const queue = [this.root]; + while (queue.length > 0) { + const obj2 = xref.fetchIfRef(queue.shift()); + if (!(obj2 instanceof Dict)) { + continue; + } + if (obj2.has("Kids")) { + const kids = obj2.get("Kids"); + if (!Array.isArray(kids)) { + continue; + } + for (const kid of kids) { + if (processed.has(kid)) { + throw new FormatError3(`Duplicate entry in "${this._type}" tree.`); + } + queue.push(kid); + processed.put(kid); + } + continue; + } + const entries = obj2.get(this._type); + if (!Array.isArray(entries)) { + continue; + } + for (let i = 0, ii = entries.length; i < ii; i += 2) { + map3.set(xref.fetchIfRef(entries[i]), xref.fetchIfRef(entries[i + 1])); + } + } + return map3; + } + getRaw(key) { + if (!this.root) { + return null; + } + const xref = this.xref; + let kidsOrEntries = xref.fetchIfRef(this.root); + let loopCount = 0; + const MAX_LEVELS = 10; + while (kidsOrEntries.has("Kids")) { + if (++loopCount > MAX_LEVELS) { + warn2(`Search depth limit reached for "${this._type}" tree.`); + return null; + } + const kids = kidsOrEntries.get("Kids"); + if (!Array.isArray(kids)) { + return null; + } + let l2 = 0, r = kids.length - 1; + while (l2 <= r) { + const m = l2 + r >> 1; + const kid = xref.fetchIfRef(kids[m]); + const limits = kid.get("Limits"); + if (key < xref.fetchIfRef(limits[0])) { + r = m - 1; + } else if (key > xref.fetchIfRef(limits[1])) { + l2 = m + 1; + } else { + kidsOrEntries = kid; + break; + } + } + if (l2 > r) { + return null; + } + } + const entries = kidsOrEntries.get(this._type); + if (Array.isArray(entries)) { + let l2 = 0, r = entries.length - 2; + while (l2 <= r) { + const tmp = l2 + r >> 1, m = tmp + (tmp & 1); + const currentKey = xref.fetchIfRef(entries[m]); + if (key < currentKey) { + r = m - 2; + } else if (key > currentKey) { + l2 = m + 2; + } else { + return entries[m + 1]; + } + } + } + return null; + } + get(key) { + return this.xref.fetchIfRef(this.getRaw(key)); + } + }; + NameTree = class extends NameOrNumberTree { + constructor(root2, xref) { + super(root2, xref, "Names"); + } + }; + NumberTree = class extends NameOrNumberTree { + constructor(root2, xref) { + super(root2, xref, "Nums"); + } + }; + FileSpec = class { + #contentAvailable = false; + constructor(root2, xref, skipContent = false) { + if (!(root2 instanceof Dict)) { + return; + } + this.xref = xref; + this.root = root2; + if (root2.has("FS")) { + this.fs = root2.get("FS"); + } + if (root2.has("RF")) { + warn2("Related file specifications are not supported"); + } + if (!skipContent) { + if (root2.has("EF")) { + this.#contentAvailable = true; + } else { + warn2("Non-embedded file specifications are not supported"); + } + } + } + get filename() { + let filename = ""; + const item = pickPlatformItem(this.root); + if (item && typeof item === "string") { + filename = stringToPDFString(item, true).replaceAll("\\\\", "\\").replaceAll("\\/", "/").replaceAll("\\", "/"); + } + return shadow2(this, "filename", filename || "unnamed"); + } + get content() { + if (!this.#contentAvailable) { + return null; + } + this._contentRef ||= pickPlatformItem(this.root?.get("EF")); + let content = null; + if (this._contentRef) { + const fileObj = this.xref.fetchIfRef(this._contentRef); + if (fileObj instanceof BaseStream) { + content = fileObj.getBytes(); + } else { + warn2("Embedded file specification points to non-existing/invalid content"); + } + } else { + warn2("Embedded file specification does not have any content"); + } + return content; + } + get description() { + let description = ""; + const desc2 = this.root?.get("Desc"); + if (desc2 && typeof desc2 === "string") { + description = stringToPDFString(desc2); + } + return shadow2(this, "description", description); + } + get serializable() { + return { + rawFilename: this.filename, + filename: stripPath(this.filename), + content: this.content, + description: this.description + }; + } + }; + XMLParserErrorCode = { + NoError: 0, + EndOfDocument: -1, + UnterminatedCdat: -2, + UnterminatedXmlDeclaration: -3, + UnterminatedDoctypeDeclaration: -4, + UnterminatedComment: -5, + MalformedElement: -6, + OutOfMemory: -7, + UnterminatedAttributeValue: -8, + UnterminatedElement: -9, + ElementNeverBegun: -10 + }; + XMLParserBase = class { + _resolveEntities(s) { + return s.replaceAll(/&([^;]+);/g, (all, entity) => { + if (entity.substring(0, 2) === "#x") { + return String.fromCodePoint(parseInt(entity.substring(2), 16)); + } else if (entity.substring(0, 1) === "#") { + return String.fromCodePoint(parseInt(entity.substring(1), 10)); + } + switch (entity) { + case "lt": + return "<"; + case "gt": + return ">"; + case "amp": + return "&"; + case "quot": + return '"'; + case "apos": + return "'"; + } + return this.onResolveEntity(entity); + }); + } + _parseContent(s, start) { + const attributes = []; + let pos = start; + function skipWs() { + while (pos < s.length && isWhitespace(s, pos)) { + ++pos; + } + } + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "/") { + ++pos; + } + const name = s.substring(start, pos); + skipWs(); + while (pos < s.length && s[pos] !== ">" && s[pos] !== "/" && s[pos] !== "?") { + skipWs(); + let attrName = "", attrValue = ""; + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== "=") { + attrName += s[pos]; + ++pos; + } + skipWs(); + if (s[pos] !== "=") { + return null; + } + ++pos; + skipWs(); + const attrEndChar = s[pos]; + if (attrEndChar !== '"' && attrEndChar !== "'") { + return null; + } + const attrEndIndex = s.indexOf(attrEndChar, ++pos); + if (attrEndIndex < 0) { + return null; + } + attrValue = s.substring(pos, attrEndIndex); + attributes.push({ + name: attrName, + value: this._resolveEntities(attrValue) + }); + pos = attrEndIndex + 1; + skipWs(); + } + return { + name, + attributes, + parsed: pos - start + }; + } + _parseProcessingInstruction(s, start) { + let pos = start; + function skipWs() { + while (pos < s.length && isWhitespace(s, pos)) { + ++pos; + } + } + while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== ">" && s[pos] !== "?" && s[pos] !== "/") { + ++pos; + } + const name = s.substring(start, pos); + skipWs(); + const attrStart = pos; + while (pos < s.length && (s[pos] !== "?" || s[pos + 1] !== ">")) { + ++pos; + } + const value = s.substring(attrStart, pos); + return { + name, + value, + parsed: pos - start + }; + } + parseXml(s) { + let i = 0; + while (i < s.length) { + const ch2 = s[i]; + let j = i; + if (ch2 === "<") { + ++j; + const ch22 = s[j]; + let q; + switch (ch22) { + case "/": + ++j; + q = s.indexOf(">", j); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedElement); + return; + } + this.onEndElement(s.substring(j, q)); + j = q + 1; + break; + case "?": + ++j; + const pi = this._parseProcessingInstruction(s, j); + if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== "?>") { + this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration); + return; + } + this.onPi(pi.name, pi.value); + j += pi.parsed + 2; + break; + case "!": + if (s.substring(j + 1, j + 3) === "--") { + q = s.indexOf("-->", j + 3); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedComment); + return; + } + this.onComment(s.substring(j + 3, q)); + j = q + 3; + } else if (s.substring(j + 1, j + 8) === "[CDATA[") { + q = s.indexOf("]]>", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedCdat); + return; + } + this.onCdata(s.substring(j + 8, q)); + j = q + 3; + } else if (s.substring(j + 1, j + 8) === "DOCTYPE") { + const q2 = s.indexOf("[", j + 8); + let complexDoctype = false; + q = s.indexOf(">", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); + return; + } + if (q2 > 0 && q > q2) { + q = s.indexOf("]>", j + 8); + if (q < 0) { + this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration); + return; + } + complexDoctype = true; + } + const doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0)); + this.onDoctype(doctypeContent); + j = q + (complexDoctype ? 2 : 1); + } else { + this.onError(XMLParserErrorCode.MalformedElement); + return; + } + break; + default: + const content = this._parseContent(s, j); + if (content === null) { + this.onError(XMLParserErrorCode.MalformedElement); + return; + } + let isClosed = false; + if (s.substring(j + content.parsed, j + content.parsed + 2) === "/>") { + isClosed = true; + } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== ">") { + this.onError(XMLParserErrorCode.UnterminatedElement); + return; + } + this.onBeginElement(content.name, content.attributes, isClosed); + j += content.parsed + (isClosed ? 2 : 1); + break; + } + } else { + while (j < s.length && s[j] !== "<") { + j++; + } + const text2 = s.substring(i, j); + this.onText(this._resolveEntities(text2)); + } + i = j; + } + } + onResolveEntity(name) { + return `&${name};`; + } + onPi(name, value) { + } + onComment(text2) { + } + onCdata(text2) { + } + onDoctype(doctypeContent) { + } + onText(text2) { + } + onBeginElement(name, attributes, isEmpty2) { + } + onEndElement(name) { + } + onError(code) { + } + }; + SimpleDOMNode = class { + constructor(nodeName, nodeValue) { + this.nodeName = nodeName; + this.nodeValue = nodeValue; + Object.defineProperty(this, "parentNode", { + value: null, + writable: true + }); + } + get firstChild() { + return this.childNodes?.[0]; + } + get nextSibling() { + const childNodes = this.parentNode.childNodes; + if (!childNodes) { + return void 0; + } + const index2 = childNodes.indexOf(this); + if (index2 === -1) { + return void 0; + } + return childNodes[index2 + 1]; + } + get textContent() { + if (!this.childNodes) { + return this.nodeValue || ""; + } + return this.childNodes.map((child) => child.textContent).join(""); + } + get children() { + return this.childNodes || []; + } + hasChildNodes() { + return this.childNodes?.length > 0; + } + searchNode(paths, pos) { + if (pos >= paths.length) { + return this; + } + const component = paths[pos]; + if (component.name.startsWith("#") && pos < paths.length - 1) { + return this.searchNode(paths, pos + 1); + } + const stack = []; + let node2 = this; + while (true) { + if (component.name === node2.nodeName) { + if (component.pos === 0) { + const res = node2.searchNode(paths, pos + 1); + if (res !== null) { + return res; + } + } else if (stack.length === 0) { + return null; + } else { + const [parent] = stack.pop(); + let siblingPos = 0; + for (const child of parent.childNodes) { + if (component.name === child.nodeName) { + if (siblingPos === component.pos) { + return child.searchNode(paths, pos + 1); + } + siblingPos++; + } + } + return node2.searchNode(paths, pos + 1); + } + } + if (node2.childNodes?.length > 0) { + stack.push([node2, 0]); + node2 = node2.childNodes[0]; + } else if (stack.length === 0) { + return null; + } else { + while (stack.length !== 0) { + const [parent, currentPos] = stack.pop(); + const newPos = currentPos + 1; + if (newPos < parent.childNodes.length) { + stack.push([parent, newPos]); + node2 = parent.childNodes[newPos]; + break; + } + } + if (stack.length === 0) { + return null; + } + } + } + } + dump(buffer2) { + if (this.nodeName === "#text") { + buffer2.push(encodeToXmlString(this.nodeValue)); + return; + } + buffer2.push(`<${this.nodeName}`); + if (this.attributes) { + for (const attribute of this.attributes) { + buffer2.push(` ${attribute.name}="${encodeToXmlString(attribute.value)}"`); + } + } + if (this.hasChildNodes()) { + buffer2.push(">"); + for (const child of this.childNodes) { + child.dump(buffer2); + } + buffer2.push(``); + } else if (this.nodeValue) { + buffer2.push(`>${encodeToXmlString(this.nodeValue)}`); + } else { + buffer2.push("/>"); + } + } + }; + SimpleXMLParser = class extends XMLParserBase { + constructor({ + hasAttributes = false, + lowerCaseName = false + }) { + super(); + this._currentFragment = null; + this._stack = null; + this._errorCode = XMLParserErrorCode.NoError; + this._hasAttributes = hasAttributes; + this._lowerCaseName = lowerCaseName; + } + parseFromString(data) { + this._currentFragment = []; + this._stack = []; + this._errorCode = XMLParserErrorCode.NoError; + this.parseXml(data); + if (this._errorCode !== XMLParserErrorCode.NoError) { + return void 0; + } + const [documentElement] = this._currentFragment; + if (!documentElement) { + return void 0; + } + return { + documentElement + }; + } + onText(text2) { + if (isWhitespaceString(text2)) { + return; + } + const node2 = new SimpleDOMNode("#text", text2); + this._currentFragment.push(node2); + } + onCdata(text2) { + const node2 = new SimpleDOMNode("#text", text2); + this._currentFragment.push(node2); + } + onBeginElement(name, attributes, isEmpty2) { + if (this._lowerCaseName) { + name = name.toLowerCase(); + } + const node2 = new SimpleDOMNode(name); + node2.childNodes = []; + if (this._hasAttributes) { + node2.attributes = attributes; + } + this._currentFragment.push(node2); + if (isEmpty2) { + return; + } + this._stack.push(this._currentFragment); + this._currentFragment = node2.childNodes; + } + onEndElement(name) { + this._currentFragment = this._stack.pop() || []; + const lastElement = this._currentFragment.at(-1); + if (!lastElement) { + return null; + } + for (const childNode of lastElement.childNodes) { + childNode.parentNode = lastElement; + } + return lastElement; + } + onError(code) { + this._errorCode = code; + } + }; + MetadataParser = class { + constructor(data) { + data = this._repair(data); + const parser = new SimpleXMLParser({ + lowerCaseName: true + }); + const xmlDocument = parser.parseFromString(data); + this._metadataMap = /* @__PURE__ */ new Map(); + this._data = data; + if (xmlDocument) { + this._parse(xmlDocument); + } + } + _repair(data) { + return data.replace(/^[^<]+/, "").replaceAll(/>\\376\\377([^<]+)/g, function(all, codes) { + const bytes = codes.replaceAll(/\\([0-3])([0-7])([0-7])/g, function(code, d1, d2, d3) { + return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1); + }).replaceAll(/&(amp|apos|gt|lt|quot);/g, function(str, name) { + switch (name) { + case "amp": + return "&"; + case "apos": + return "'"; + case "gt": + return ">"; + case "lt": + return "<"; + case "quot": + return '"'; + } + throw new Error(`_repair: ${name} isn't defined.`); + }); + const charBuf = [">"]; + for (let i = 0, ii = bytes.length; i < ii; i += 2) { + const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); + if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) { + charBuf.push(String.fromCharCode(code)); + } else { + charBuf.push("&#x" + (65536 + code).toString(16).substring(1) + ";"); + } + } + return charBuf.join(""); + }); + } + _getSequence(entry) { + const name = entry.nodeName; + if (name !== "rdf:bag" && name !== "rdf:seq" && name !== "rdf:alt") { + return null; + } + return entry.childNodes.filter((node2) => node2.nodeName === "rdf:li"); + } + _parseArray(entry) { + if (!entry.hasChildNodes()) { + return; + } + const [seqNode] = entry.childNodes; + const sequence = this._getSequence(seqNode) || []; + this._metadataMap.set(entry.nodeName, sequence.map((node2) => node2.textContent.trim())); + } + _parse(xmlDocument) { + let rdf = xmlDocument.documentElement; + if (rdf.nodeName !== "rdf:rdf") { + rdf = rdf.firstChild; + while (rdf && rdf.nodeName !== "rdf:rdf") { + rdf = rdf.nextSibling; + } + } + if (!rdf || rdf.nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) { + return; + } + for (const desc2 of rdf.childNodes) { + if (desc2.nodeName !== "rdf:description") { + continue; + } + for (const entry of desc2.childNodes) { + const name = entry.nodeName; + switch (name) { + case "#text": + continue; + case "dc:creator": + case "dc:subject": + this._parseArray(entry); + continue; + } + this._metadataMap.set(name, entry.textContent.trim()); + } + } + } + get serializable() { + return { + parsedData: this._metadataMap, + rawData: this._data + }; + } + }; + MAX_DEPTH = 40; + StructElementType = { + PAGE_CONTENT: 1, + STREAM_CONTENT: 2, + OBJECT: 3, + ANNOTATION: 4, + ELEMENT: 5 + }; + StructTreeRoot = class _StructTreeRoot { + constructor(xref, rootDict, rootRef) { + this.xref = xref; + this.dict = rootDict; + this.ref = rootRef instanceof Ref ? rootRef : null; + this.roleMap = /* @__PURE__ */ new Map(); + this.structParentIds = null; + } + init() { + this.readRoleMap(); + } + #addIdToPage(pageRef, id, type) { + if (!(pageRef instanceof Ref) || id < 0) { + return; + } + this.structParentIds ||= new RefSetCache(); + let ids = this.structParentIds.get(pageRef); + if (!ids) { + ids = []; + this.structParentIds.put(pageRef, ids); + } + ids.push([id, type]); + } + addAnnotationIdToPage(pageRef, id) { + this.#addIdToPage(pageRef, id, StructElementType.ANNOTATION); + } + readRoleMap() { + const roleMapDict = this.dict.get("RoleMap"); + if (!(roleMapDict instanceof Dict)) { + return; + } + for (const [key, value] of roleMapDict) { + if (value instanceof Name2) { + this.roleMap.set(key, value.name); + } + } + } + static async canCreateStructureTree({ + catalogRef, + pdfManager, + newAnnotationsByPage + }) { + if (!(catalogRef instanceof Ref)) { + warn2("Cannot save the struct tree: no catalog reference."); + return false; + } + let nextKey = 0; + let hasNothingToUpdate = true; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const { + ref: pageRef + } = await pdfManager.getPage(pageIndex); + if (!(pageRef instanceof Ref)) { + warn2(`Cannot save the struct tree: page ${pageIndex} has no ref.`); + hasNothingToUpdate = true; + break; + } + for (const element of elements) { + if (element.accessibilityData?.type) { + element.parentTreeId = nextKey++; + hasNothingToUpdate = false; + } + } + } + if (hasNothingToUpdate) { + for (const elements of newAnnotationsByPage.values()) { + for (const element of elements) { + delete element.parentTreeId; + } + } + return false; + } + return true; + } + static async createStructureTree({ + newAnnotationsByPage, + xref, + catalogRef, + pdfManager, + changes + }) { + const root2 = await pdfManager.ensureCatalog("cloneDict"); + const cache2 = new RefSetCache(); + cache2.put(catalogRef, root2); + const structTreeRootRef = xref.getNewTemporaryRef(); + root2.set("StructTreeRoot", structTreeRootRef); + const structTreeRoot = new Dict(xref); + structTreeRoot.set("Type", Name2.get("StructTreeRoot")); + const parentTreeRef = xref.getNewTemporaryRef(); + structTreeRoot.set("ParentTree", parentTreeRef); + const kids = []; + structTreeRoot.set("K", kids); + cache2.put(structTreeRootRef, structTreeRoot); + const parentTree = new Dict(xref); + const nums = []; + parentTree.set("Nums", nums); + const nextKey = await this.#writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot: null, + kids, + nums, + xref, + pdfManager, + changes, + cache: cache2 + }); + structTreeRoot.set("ParentTreeNextKey", nextKey); + cache2.put(parentTreeRef, parentTree); + for (const [ref, obj2] of cache2.items()) { + changes.put(ref, { + data: obj2 + }); + } + } + async canUpdateStructTree({ + pdfManager, + newAnnotationsByPage + }) { + if (!this.ref) { + warn2("Cannot update the struct tree: no root reference."); + return false; + } + let nextKey = this.dict.get("ParentTreeNextKey"); + if (!Number.isInteger(nextKey) || nextKey < 0) { + warn2("Cannot update the struct tree: invalid next key."); + return false; + } + const parentTree = this.dict.get("ParentTree"); + if (!(parentTree instanceof Dict)) { + warn2("Cannot update the struct tree: ParentTree isn't a dict."); + return false; + } + const nums = parentTree.get("Nums"); + if (!Array.isArray(nums)) { + warn2("Cannot update the struct tree: nums isn't an array."); + return false; + } + const numberTree = new NumberTree(parentTree, this.xref); + for (const pageIndex of newAnnotationsByPage.keys()) { + const { + pageDict + } = await pdfManager.getPage(pageIndex); + if (!pageDict.has("StructParents")) { + continue; + } + const id = pageDict.get("StructParents"); + if (!Number.isInteger(id) || !Array.isArray(numberTree.get(id))) { + warn2(`Cannot save the struct tree: page ${pageIndex} has a wrong id.`); + return false; + } + } + let hasNothingToUpdate = true; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const { + pageDict + } = await pdfManager.getPage(pageIndex); + _StructTreeRoot.#collectParents({ + elements, + xref: this.xref, + pageDict, + numberTree + }); + for (const element of elements) { + if (element.accessibilityData?.type) { + if (!(element.accessibilityData.structParent >= 0)) { + element.parentTreeId = nextKey++; + } + hasNothingToUpdate = false; + } + } + } + if (hasNothingToUpdate) { + for (const elements of newAnnotationsByPage.values()) { + for (const element of elements) { + delete element.parentTreeId; + delete element.structTreeParent; + } + } + return false; + } + return true; + } + async updateStructureTree({ + newAnnotationsByPage, + pdfManager, + changes + }) { + const { + ref: structTreeRootRef, + xref + } = this; + const structTreeRoot = this.dict.clone(); + const cache2 = new RefSetCache(); + cache2.put(structTreeRootRef, structTreeRoot); + let parentTreeRef = structTreeRoot.getRaw("ParentTree"); + let parentTree; + if (parentTreeRef instanceof Ref) { + parentTree = xref.fetch(parentTreeRef); + } else { + parentTree = parentTreeRef; + parentTreeRef = xref.getNewTemporaryRef(); + structTreeRoot.set("ParentTree", parentTreeRef); + } + parentTree = parentTree.clone(); + cache2.put(parentTreeRef, parentTree); + let nums = parentTree.getRaw("Nums"); + let numsRef = null; + if (nums instanceof Ref) { + numsRef = nums; + nums = xref.fetch(numsRef); + } + nums = nums.slice(); + if (!numsRef) { + parentTree.set("Nums", nums); + } + const newNextKey = await _StructTreeRoot.#writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot: this, + kids: null, + nums, + xref, + pdfManager, + changes, + cache: cache2 + }); + if (newNextKey === -1) { + return; + } + structTreeRoot.set("ParentTreeNextKey", newNextKey); + if (numsRef) { + cache2.put(numsRef, nums); + } + for (const [ref, obj2] of cache2.items()) { + changes.put(ref, { + data: obj2 + }); + } + } + static async #writeKids({ + newAnnotationsByPage, + structTreeRootRef, + structTreeRoot, + kids, + nums, + xref, + pdfManager, + changes, + cache: cache2 + }) { + const objr = Name2.get("OBJR"); + let nextKey = -1; + let structTreePageObjs; + for (const [pageIndex, elements] of newAnnotationsByPage) { + const page = await pdfManager.getPage(pageIndex); + const { + ref: pageRef + } = page; + const isPageRef = pageRef instanceof Ref; + for (const { + accessibilityData, + ref, + parentTreeId, + structTreeParent + } of elements) { + if (!accessibilityData?.type) { + continue; + } + const { + structParent + } = accessibilityData; + if (structTreeRoot && Number.isInteger(structParent) && structParent >= 0) { + let objs = (structTreePageObjs ||= /* @__PURE__ */ new Map()).get(pageIndex); + if (objs === void 0) { + const structTreePage = new StructTreePage(structTreeRoot, page.pageDict); + objs = structTreePage.collectObjects(pageRef); + structTreePageObjs.set(pageIndex, objs); + } + const objRef = objs?.get(structParent); + if (objRef) { + const tagDict2 = xref.fetch(objRef).clone(); + _StructTreeRoot.#writeProperties(tagDict2, accessibilityData); + changes.put(objRef, { + data: tagDict2 + }); + continue; + } + } + nextKey = Math.max(nextKey, parentTreeId); + const tagRef = xref.getNewTemporaryRef(); + const tagDict = new Dict(xref); + _StructTreeRoot.#writeProperties(tagDict, accessibilityData); + await this.#updateParentTag({ + structTreeParent, + tagDict, + newTagRef: tagRef, + structTreeRootRef, + fallbackKids: kids, + xref, + cache: cache2 + }); + const objDict = new Dict(xref); + tagDict.set("K", objDict); + objDict.set("Type", objr); + if (isPageRef) { + objDict.set("Pg", pageRef); + } + objDict.set("Obj", ref); + cache2.put(tagRef, tagDict); + nums.push(parentTreeId, tagRef); + } + } + return nextKey + 1; + } + static #writeProperties(tagDict, { + type, + title, + lang, + alt, + expanded, + actualText + }) { + tagDict.set("S", Name2.get(type)); + if (title) { + tagDict.set("T", stringToAsciiOrUTF16BE(title)); + } + if (lang) { + tagDict.set("Lang", stringToAsciiOrUTF16BE(lang)); + } + if (alt) { + tagDict.set("Alt", stringToAsciiOrUTF16BE(alt)); + } + if (expanded) { + tagDict.set("E", stringToAsciiOrUTF16BE(expanded)); + } + if (actualText) { + tagDict.set("ActualText", stringToAsciiOrUTF16BE(actualText)); + } + } + static #collectParents({ + elements, + xref, + pageDict, + numberTree + }) { + const idToElements = /* @__PURE__ */ new Map(); + for (const element of elements) { + if (element.structTreeParentId) { + const id2 = parseInt(element.structTreeParentId.split("_mc")[1], 10); + let elems = idToElements.get(id2); + if (!elems) { + elems = []; + idToElements.set(id2, elems); + } + elems.push(element); + } + } + const id = pageDict.get("StructParents"); + if (!Number.isInteger(id)) { + return; + } + const parentArray = numberTree.get(id); + const updateElement = (kid, pageKid, kidRef) => { + const elems = idToElements.get(kid); + if (elems) { + const parentRef = pageKid.getRaw("P"); + const parentDict = xref.fetchIfRef(parentRef); + if (parentRef instanceof Ref && parentDict instanceof Dict) { + const params = { + ref: kidRef, + dict: pageKid + }; + for (const element of elems) { + element.structTreeParent = params; + } + } + return true; + } + return false; + }; + for (const kidRef of parentArray) { + if (!(kidRef instanceof Ref)) { + continue; + } + const pageKid = xref.fetch(kidRef); + const k = pageKid.get("K"); + if (Number.isInteger(k)) { + updateElement(k, pageKid, kidRef); + continue; + } + if (!Array.isArray(k)) { + continue; + } + for (let kid of k) { + kid = xref.fetchIfRef(kid); + if (Number.isInteger(kid) && updateElement(kid, pageKid, kidRef)) { + break; + } + if (!(kid instanceof Dict)) { + continue; + } + if (!isName(kid.get("Type"), "MCR")) { + break; + } + const mcid = kid.get("MCID"); + if (Number.isInteger(mcid) && updateElement(mcid, pageKid, kidRef)) { + break; + } + } + } + } + static async #updateParentTag({ + structTreeParent, + tagDict, + newTagRef, + structTreeRootRef, + fallbackKids, + xref, + cache: cache2 + }) { + let ref = null; + let parentRef; + if (structTreeParent) { + ({ + ref + } = structTreeParent); + parentRef = structTreeParent.dict.getRaw("P") || structTreeRootRef; + } else { + parentRef = structTreeRootRef; + } + tagDict.set("P", parentRef); + const parentDict = xref.fetchIfRef(parentRef); + if (!parentDict) { + fallbackKids.push(newTagRef); + return; + } + let cachedParentDict = cache2.get(parentRef); + if (!cachedParentDict) { + cachedParentDict = parentDict.clone(); + cache2.put(parentRef, cachedParentDict); + } + const parentKidsRaw = cachedParentDict.getRaw("K"); + let cachedParentKids = parentKidsRaw instanceof Ref ? cache2.get(parentKidsRaw) : null; + if (!cachedParentKids) { + cachedParentKids = xref.fetchIfRef(parentKidsRaw); + cachedParentKids = Array.isArray(cachedParentKids) ? cachedParentKids.slice() : [parentKidsRaw]; + const parentKidsRef = xref.getNewTemporaryRef(); + cachedParentDict.set("K", parentKidsRef); + cache2.put(parentKidsRef, cachedParentKids); + } + const index2 = cachedParentKids.indexOf(ref); + cachedParentKids.splice(index2 >= 0 ? index2 + 1 : cachedParentKids.length, 0, newTagRef); + } + }; + StructElementNode = class { + constructor(tree, dict) { + this.tree = tree; + this.xref = tree.xref; + this.dict = dict; + this.kids = []; + this.parseKids(); + } + get role() { + const nameObj = this.dict.get("S"); + const name = nameObj instanceof Name2 ? nameObj.name : ""; + const { + root: root2 + } = this.tree; + return root2.roleMap.get(name) ?? name; + } + parseKids() { + let pageObjId = null; + const objRef = this.dict.getRaw("Pg"); + if (objRef instanceof Ref) { + pageObjId = objRef.toString(); + } + const kids = this.dict.get("K"); + if (Array.isArray(kids)) { + for (const kid of kids) { + const element = this.parseKid(pageObjId, this.xref.fetchIfRef(kid)); + if (element) { + this.kids.push(element); + } + } + } else { + const element = this.parseKid(pageObjId, kids); + if (element) { + this.kids.push(element); + } + } + } + parseKid(pageObjId, kid) { + if (Number.isInteger(kid)) { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + return new StructElement({ + type: StructElementType.PAGE_CONTENT, + mcid: kid, + pageObjId + }); + } + if (!(kid instanceof Dict)) { + return null; + } + const pageRef = kid.getRaw("Pg"); + if (pageRef instanceof Ref) { + pageObjId = pageRef.toString(); + } + const type = kid.get("Type") instanceof Name2 ? kid.get("Type").name : null; + if (type === "MCR") { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + const kidRef = kid.getRaw("Stm"); + return new StructElement({ + type: StructElementType.STREAM_CONTENT, + refObjId: kidRef instanceof Ref ? kidRef.toString() : null, + pageObjId, + mcid: kid.get("MCID") + }); + } + if (type === "OBJR") { + if (this.tree.pageDict.objId !== pageObjId) { + return null; + } + const kidRef = kid.getRaw("Obj"); + return new StructElement({ + type: StructElementType.OBJECT, + refObjId: kidRef instanceof Ref ? kidRef.toString() : null, + pageObjId + }); + } + return new StructElement({ + type: StructElementType.ELEMENT, + dict: kid + }); + } + }; + StructElement = class { + constructor({ + type, + dict = null, + mcid = null, + pageObjId = null, + refObjId = null + }) { + this.type = type; + this.dict = dict; + this.mcid = mcid; + this.pageObjId = pageObjId; + this.refObjId = refObjId; + this.parentNode = null; + } + }; + StructTreePage = class { + constructor(structTreeRoot, pageDict) { + this.root = structTreeRoot; + this.xref = structTreeRoot?.xref ?? null; + this.rootDict = structTreeRoot?.dict ?? null; + this.pageDict = pageDict; + this.nodes = []; + } + collectObjects(pageRef) { + if (!this.root || !this.rootDict || !(pageRef instanceof Ref)) { + return null; + } + const parentTree = this.rootDict.get("ParentTree"); + if (!parentTree) { + return null; + } + const ids = this.root.structParentIds?.get(pageRef); + if (!ids) { + return null; + } + const map3 = /* @__PURE__ */ new Map(); + const numberTree = new NumberTree(parentTree, this.xref); + for (const [elemId] of ids) { + const obj2 = numberTree.getRaw(elemId); + if (obj2 instanceof Ref) { + map3.set(elemId, obj2); + } + } + return map3; + } + parse(pageRef) { + if (!this.root || !this.rootDict || !(pageRef instanceof Ref)) { + return; + } + const parentTree = this.rootDict.get("ParentTree"); + if (!parentTree) { + return; + } + const id = this.pageDict.get("StructParents"); + const ids = this.root.structParentIds?.get(pageRef); + if (!Number.isInteger(id) && !ids) { + return; + } + const map3 = /* @__PURE__ */ new Map(); + const numberTree = new NumberTree(parentTree, this.xref); + if (Number.isInteger(id)) { + const parentArray = numberTree.get(id); + if (Array.isArray(parentArray)) { + for (const ref of parentArray) { + if (ref instanceof Ref) { + this.addNode(this.xref.fetch(ref), map3); + } + } + } + } + if (!ids) { + return; + } + for (const [elemId, type] of ids) { + const obj2 = numberTree.get(elemId); + if (obj2) { + const elem = this.addNode(this.xref.fetchIfRef(obj2), map3); + if (elem?.kids?.length === 1 && elem.kids[0].type === StructElementType.OBJECT) { + elem.kids[0].type = type; + } + } + } + } + addNode(dict, map3, level = 0) { + if (level > MAX_DEPTH) { + warn2("StructTree MAX_DEPTH reached."); + return null; + } + if (!(dict instanceof Dict)) { + return null; + } + if (map3.has(dict)) { + return map3.get(dict); + } + const element = new StructElementNode(this, dict); + map3.set(dict, element); + const parent = dict.get("P"); + if (!(parent instanceof Dict) || isName(parent.get("Type"), "StructTreeRoot")) { + if (!this.addTopLevelNode(dict, element)) { + map3.delete(dict); + } + return element; + } + const parentNode = this.addNode(parent, map3, level + 1); + if (!parentNode) { + return element; + } + let save = false; + for (const kid of parentNode.kids) { + if (kid.type === StructElementType.ELEMENT && kid.dict === dict) { + kid.parentNode = element; + save = true; + } + } + if (!save) { + map3.delete(dict); + } + return element; + } + addTopLevelNode(dict, element) { + const obj2 = this.rootDict.get("K"); + if (!obj2) { + return false; + } + if (obj2 instanceof Dict) { + if (obj2.objId !== dict.objId) { + return false; + } + this.nodes[0] = element; + return true; + } + if (!Array.isArray(obj2)) { + return true; + } + let save = false; + for (let i = 0; i < obj2.length; i++) { + const kidRef = obj2[i]; + if (kidRef?.toString() === dict.objId) { + this.nodes[i] = element; + save = true; + } + } + return save; + } + get serializable() { + function nodeToSerializable(node2, parent, level = 0) { + if (level > MAX_DEPTH) { + warn2("StructTree too deep to be fully serialized."); + return; + } + const obj2 = /* @__PURE__ */ Object.create(null); + obj2.role = node2.role; + obj2.children = []; + parent.children.push(obj2); + let alt = node2.dict.get("Alt"); + if (typeof alt !== "string") { + alt = node2.dict.get("ActualText"); + } + if (typeof alt === "string") { + obj2.alt = stringToPDFString(alt); + } + const a = node2.dict.get("A"); + if (a instanceof Dict) { + const bbox = lookupNormalRect(a.getArray("BBox"), null); + if (bbox) { + obj2.bbox = bbox; + } else { + const width = a.get("Width"); + const height = a.get("Height"); + if (typeof width === "number" && width > 0 && typeof height === "number" && height > 0) { + obj2.bbox = [0, 0, width, height]; + } + } + } + const lang = node2.dict.get("Lang"); + if (typeof lang === "string") { + obj2.lang = stringToPDFString(lang); + } + for (const kid of node2.kids) { + const kidElement = kid.type === StructElementType.ELEMENT ? kid.parentNode : null; + if (kidElement) { + nodeToSerializable(kidElement, obj2, level + 1); + continue; + } else if (kid.type === StructElementType.PAGE_CONTENT || kid.type === StructElementType.STREAM_CONTENT) { + obj2.children.push({ + type: "content", + id: `p${kid.pageObjId}_mc${kid.mcid}` + }); + } else if (kid.type === StructElementType.OBJECT) { + obj2.children.push({ + type: "object", + id: kid.refObjId + }); + } else if (kid.type === StructElementType.ANNOTATION) { + obj2.children.push({ + type: "annotation", + id: `${AnnotationPrefix2}${kid.refObjId}` + }); + } + } + } + const root2 = /* @__PURE__ */ Object.create(null); + root2.children = []; + root2.role = "Root"; + for (const child of this.nodes) { + if (!child) { + continue; + } + nodeToSerializable(child, root2); + } + return root2; + } + }; + isRef2 = (v) => v instanceof Ref; + isValidExplicitDest2 = _isValidExplicitDest2.bind(null, isRef2, isName); + Catalog = class _Catalog { + #actualNumPages = null; + #catDict = null; + builtInCMapCache = /* @__PURE__ */ new Map(); + fontCache = new RefSetCache(); + globalColorSpaceCache = new GlobalColorSpaceCache(); + globalImageCache = new GlobalImageCache(); + nonBlendModesSet = new RefSet(); + pageDictCache = new RefSetCache(); + pageIndexCache = new RefSetCache(); + pageKidsCountCache = new RefSetCache(); + standardFontDataCache = /* @__PURE__ */ new Map(); + systemFontCache = /* @__PURE__ */ new Map(); + constructor(pdfManager, xref) { + this.pdfManager = pdfManager; + this.xref = xref; + this.#catDict = xref.getCatalogObj(); + if (!(this.#catDict instanceof Dict)) { + throw new FormatError3("Catalog object is not a dictionary."); + } + this.toplevelPagesDict; + } + cloneDict() { + return this.#catDict.clone(); + } + get version() { + const version4 = this.#catDict.get("Version"); + if (version4 instanceof Name2) { + if (PDF_VERSION_REGEXP.test(version4.name)) { + return shadow2(this, "version", version4.name); + } + warn2(`Invalid PDF catalog version: ${version4.name}`); + } + return shadow2(this, "version", null); + } + get lang() { + const lang = this.#catDict.get("Lang"); + return shadow2(this, "lang", lang && typeof lang === "string" ? stringToPDFString(lang) : null); + } + get needsRendering() { + const needsRendering = this.#catDict.get("NeedsRendering"); + return shadow2(this, "needsRendering", typeof needsRendering === "boolean" ? needsRendering : false); + } + get collection() { + let collection = null; + try { + const obj2 = this.#catDict.get("Collection"); + if (obj2 instanceof Dict && obj2.size > 0) { + collection = obj2; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info2("Cannot fetch Collection entry; assuming no collection is present."); + } + return shadow2(this, "collection", collection); + } + get acroForm() { + let acroForm = null; + try { + const obj2 = this.#catDict.get("AcroForm"); + if (obj2 instanceof Dict && obj2.size > 0) { + acroForm = obj2; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info2("Cannot fetch AcroForm entry; assuming no forms are present."); + } + return shadow2(this, "acroForm", acroForm); + } + get acroFormRef() { + const value = this.#catDict.getRaw("AcroForm"); + return shadow2(this, "acroFormRef", value instanceof Ref ? value : null); + } + get metadata() { + const streamRef = this.#catDict.getRaw("Metadata"); + if (!(streamRef instanceof Ref)) { + return shadow2(this, "metadata", null); + } + let metadata = null; + try { + const stream = this.xref.fetch(streamRef, !this.xref.encrypt?.encryptMetadata); + if (stream instanceof BaseStream && stream.dict instanceof Dict) { + const type = stream.dict.get("Type"); + const subtype = stream.dict.get("Subtype"); + if (isName(type, "Metadata") && isName(subtype, "XML")) { + const data = stringToUTF8String2(stream.getString()); + if (data) { + metadata = new MetadataParser(data).serializable; + } + } + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + info2(`Skipping invalid Metadata: "${ex}".`); + } + return shadow2(this, "metadata", metadata); + } + get markInfo() { + let markInfo = null; + try { + markInfo = this.#readMarkInfo(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Unable to read mark info."); + } + return shadow2(this, "markInfo", markInfo); + } + #readMarkInfo() { + const obj2 = this.#catDict.get("MarkInfo"); + if (!(obj2 instanceof Dict)) { + return null; + } + const markInfo = { + Marked: false, + UserProperties: false, + Suspects: false + }; + for (const key in markInfo) { + const value = obj2.get(key); + if (typeof value === "boolean") { + markInfo[key] = value; + } + } + return markInfo; + } + get structTreeRoot() { + let structTree = null; + try { + structTree = this.#readStructTreeRoot(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Unable read to structTreeRoot info."); + } + return shadow2(this, "structTreeRoot", structTree); + } + #readStructTreeRoot() { + const rawObj = this.#catDict.getRaw("StructTreeRoot"); + const obj2 = this.xref.fetchIfRef(rawObj); + if (!(obj2 instanceof Dict)) { + return null; + } + const root2 = new StructTreeRoot(this.xref, obj2, rawObj); + root2.init(); + return root2; + } + get toplevelPagesDict() { + const pagesObj = this.#catDict.get("Pages"); + if (!(pagesObj instanceof Dict)) { + throw new FormatError3("Invalid top-level pages dictionary."); + } + return shadow2(this, "toplevelPagesDict", pagesObj); + } + get documentOutline() { + let obj2 = null; + try { + obj2 = this.#readDocumentOutline(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Unable to read document outline."); + } + return shadow2(this, "documentOutline", obj2); + } + #readDocumentOutline() { + let obj2 = this.#catDict.get("Outlines"); + if (!(obj2 instanceof Dict)) { + return null; + } + obj2 = obj2.getRaw("First"); + if (!(obj2 instanceof Ref)) { + return null; + } + const root2 = { + items: [] + }; + const queue = [{ + obj: obj2, + parent: root2 + }]; + const processed = new RefSet(); + processed.put(obj2); + const xref = this.xref, blackColor = new Uint8ClampedArray(3); + while (queue.length > 0) { + const i = queue.shift(); + const outlineDict = xref.fetchIfRef(i.obj); + if (outlineDict === null) { + continue; + } + if (!outlineDict.has("Title")) { + warn2("Invalid outline item encountered."); + } + const data = { + url: null, + dest: null, + action: null + }; + _Catalog.parseDestDictionary({ + destDict: outlineDict, + resultObj: data, + docBaseUrl: this.baseUrl, + docAttachments: this.attachments + }); + const title = outlineDict.get("Title"); + const flags = outlineDict.get("F") || 0; + const color = outlineDict.getArray("C"); + const count = outlineDict.get("Count"); + let rgbColor = blackColor; + if (isNumberArray(color, 3) && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) { + rgbColor = ColorSpaceUtils.rgb.getRgb(color, 0); + } + const outlineItem = { + action: data.action, + attachment: data.attachment, + dest: data.dest, + url: data.url, + unsafeUrl: data.unsafeUrl, + newWindow: data.newWindow, + setOCGState: data.setOCGState, + title: typeof title === "string" ? stringToPDFString(title) : "", + color: rgbColor, + count: Number.isInteger(count) ? count : void 0, + bold: !!(flags & 2), + italic: !!(flags & 1), + items: [] + }; + i.parent.items.push(outlineItem); + obj2 = outlineDict.getRaw("First"); + if (obj2 instanceof Ref && !processed.has(obj2)) { + queue.push({ + obj: obj2, + parent: outlineItem + }); + processed.put(obj2); + } + obj2 = outlineDict.getRaw("Next"); + if (obj2 instanceof Ref && !processed.has(obj2)) { + queue.push({ + obj: obj2, + parent: i.parent + }); + processed.put(obj2); + } + } + return root2.items.length > 0 ? root2.items : null; + } + get permissions() { + let permissions = null; + try { + permissions = this.#readPermissions(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Unable to read permissions."); + } + return shadow2(this, "permissions", permissions); + } + #readPermissions() { + const encrypt = this.xref.trailer.get("Encrypt"); + if (!(encrypt instanceof Dict)) { + return null; + } + let flags = encrypt.get("P"); + if (typeof flags !== "number") { + return null; + } + flags += 2 ** 32; + const permissions = []; + for (const key in PermissionFlag2) { + const value = PermissionFlag2[key]; + if (flags & value) { + permissions.push(value); + } + } + return permissions; + } + get optionalContentConfig() { + let config2 = null; + try { + const properties = this.#catDict.get("OCProperties"); + if (!properties) { + return shadow2(this, "optionalContentConfig", null); + } + const defaultConfig = properties.get("D"); + if (!defaultConfig) { + return shadow2(this, "optionalContentConfig", null); + } + const groupsData = properties.get("OCGs"); + if (!Array.isArray(groupsData)) { + return shadow2(this, "optionalContentConfig", null); + } + const groupRefCache = new RefSetCache(); + for (const groupRef of groupsData) { + if (!(groupRef instanceof Ref) || groupRefCache.has(groupRef)) { + continue; + } + groupRefCache.put(groupRef, this.#readOptionalContentGroup(groupRef)); + } + config2 = this.#readOptionalContentConfig(defaultConfig, groupRefCache); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`Unable to read optional content config: ${ex}`); + } + return shadow2(this, "optionalContentConfig", config2); + } + #readOptionalContentGroup(groupRef) { + const group2 = this.xref.fetch(groupRef); + const obj2 = { + id: groupRef.toString(), + name: null, + intent: null, + usage: { + print: null, + view: null + }, + rbGroups: [] + }; + const name = group2.get("Name"); + if (typeof name === "string") { + obj2.name = stringToPDFString(name); + } + let intent = group2.getArray("Intent"); + if (!Array.isArray(intent)) { + intent = [intent]; + } + if (intent.every((i) => i instanceof Name2)) { + obj2.intent = intent.map((i) => i.name); + } + const usage = group2.get("Usage"); + if (!(usage instanceof Dict)) { + return obj2; + } + const usageObj = obj2.usage; + const print = usage.get("Print"); + if (print instanceof Dict) { + const printState = print.get("PrintState"); + if (printState instanceof Name2) { + switch (printState.name) { + case "ON": + case "OFF": + usageObj.print = { + printState: printState.name + }; + } + } + } + const view = usage.get("View"); + if (view instanceof Dict) { + const viewState = view.get("ViewState"); + if (viewState instanceof Name2) { + switch (viewState.name) { + case "ON": + case "OFF": + usageObj.view = { + viewState: viewState.name + }; + } + } + } + return obj2; + } + #readOptionalContentConfig(config2, groupRefCache) { + function parseOnOff(refs) { + const onParsed = []; + if (Array.isArray(refs)) { + for (const value of refs) { + if (value instanceof Ref && groupRefCache.has(value)) { + onParsed.push(value.toString()); + } + } + } + return onParsed; + } + function parseOrder(refs, nestedLevels = 0) { + if (!Array.isArray(refs)) { + return null; + } + const order = []; + for (const value of refs) { + if (value instanceof Ref && groupRefCache.has(value)) { + parsedOrderRefs.put(value); + order.push(value.toString()); + continue; + } + const nestedOrder = parseNestedOrder(value, nestedLevels); + if (nestedOrder) { + order.push(nestedOrder); + } + } + if (nestedLevels > 0) { + return order; + } + const hiddenGroups = []; + for (const [groupRef] of groupRefCache.items()) { + if (parsedOrderRefs.has(groupRef)) { + continue; + } + hiddenGroups.push(groupRef.toString()); + } + if (hiddenGroups.length) { + order.push({ + name: null, + order: hiddenGroups + }); + } + return order; + } + function parseNestedOrder(ref, nestedLevels) { + if (++nestedLevels > MAX_NESTED_LEVELS) { + warn2("parseNestedOrder - reached MAX_NESTED_LEVELS."); + return null; + } + const value = xref.fetchIfRef(ref); + if (!Array.isArray(value)) { + return null; + } + const nestedName = xref.fetchIfRef(value[0]); + if (typeof nestedName !== "string") { + return null; + } + const nestedOrder = parseOrder(value.slice(1), nestedLevels); + if (!nestedOrder?.length) { + return null; + } + return { + name: stringToPDFString(nestedName), + order: nestedOrder + }; + } + function parseRBGroups(rbGroups) { + if (!Array.isArray(rbGroups)) { + return; + } + for (const value of rbGroups) { + const rbGroup = xref.fetchIfRef(value); + if (!Array.isArray(rbGroup) || !rbGroup.length) { + continue; + } + const parsedRbGroup = /* @__PURE__ */ new Set(); + for (const ref of rbGroup) { + if (ref instanceof Ref && groupRefCache.has(ref) && !parsedRbGroup.has(ref.toString())) { + parsedRbGroup.add(ref.toString()); + groupRefCache.get(ref).rbGroups.push(parsedRbGroup); + } + } + } + } + const xref = this.xref, parsedOrderRefs = new RefSet(), MAX_NESTED_LEVELS = 10; + parseRBGroups(config2.get("RBGroups")); + return { + name: typeof config2.get("Name") === "string" ? stringToPDFString(config2.get("Name")) : null, + creator: typeof config2.get("Creator") === "string" ? stringToPDFString(config2.get("Creator")) : null, + baseState: config2.get("BaseState") instanceof Name2 ? config2.get("BaseState").name : null, + on: parseOnOff(config2.get("ON")), + off: parseOnOff(config2.get("OFF")), + order: parseOrder(config2.get("Order")), + groups: [...groupRefCache] + }; + } + setActualNumPages(num = null) { + this.#actualNumPages = num; + } + get hasActualNumPages() { + return this.#actualNumPages !== null; + } + get _pagesCount() { + const obj2 = this.toplevelPagesDict.get("Count"); + if (!Number.isInteger(obj2)) { + throw new FormatError3("Page count in top-level pages dictionary is not an integer."); + } + return shadow2(this, "_pagesCount", obj2); + } + get numPages() { + return this.#actualNumPages ?? this._pagesCount; + } + get destinations() { + const rawDests = this.#readDests(), dests = /* @__PURE__ */ Object.create(null); + for (const obj2 of rawDests) { + if (obj2 instanceof NameTree) { + for (const [key, value] of obj2.getAll()) { + const dest = fetchDest(value); + if (dest) { + dests[stringToPDFString(key, true)] = dest; + } + } + } else if (obj2 instanceof Dict) { + for (const [key, value] of obj2) { + const dest = fetchDest(value); + if (dest) { + dests[stringToPDFString(key, true)] ||= dest; + } + } + } + } + return shadow2(this, "destinations", dests); + } + getDestination(id) { + if (this.hasOwnProperty("destinations")) { + return this.destinations[id] ?? null; + } + const rawDests = this.#readDests(); + for (const obj2 of rawDests) { + if (obj2 instanceof NameTree || obj2 instanceof Dict) { + const dest = fetchDest(obj2.get(id)); + if (dest) { + return dest; + } + } + } + if (rawDests.length) { + const dest = this.destinations[id]; + if (dest) { + return dest; + } + } + return null; + } + #readDests() { + const obj2 = this.#catDict.get("Names"); + const rawDests = []; + if (obj2?.has("Dests")) { + rawDests.push(new NameTree(obj2.getRaw("Dests"), this.xref)); + } + if (this.#catDict.has("Dests")) { + rawDests.push(this.#catDict.get("Dests")); + } + return rawDests; + } + get pageLabels() { + let obj2 = null; + try { + obj2 = this.#readPageLabels(); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2("Unable to read page labels."); + } + return shadow2(this, "pageLabels", obj2); + } + #readPageLabels() { + const obj2 = this.#catDict.getRaw("PageLabels"); + if (!obj2) { + return null; + } + const pageLabels = new Array(this.numPages); + let style = null, prefix = ""; + const numberTree = new NumberTree(obj2, this.xref); + const nums = numberTree.getAll(); + let currentLabel = "", currentIndex = 1; + for (let i = 0, ii = this.numPages; i < ii; i++) { + const labelDict = nums.get(i); + if (labelDict !== void 0) { + if (!(labelDict instanceof Dict)) { + throw new FormatError3("PageLabel is not a dictionary."); + } + if (labelDict.has("Type") && !isName(labelDict.get("Type"), "PageLabel")) { + throw new FormatError3("Invalid type in PageLabel dictionary."); + } + if (labelDict.has("S")) { + const s = labelDict.get("S"); + if (!(s instanceof Name2)) { + throw new FormatError3("Invalid style in PageLabel dictionary."); + } + style = s.name; + } else { + style = null; + } + if (labelDict.has("P")) { + const p = labelDict.get("P"); + if (typeof p !== "string") { + throw new FormatError3("Invalid prefix in PageLabel dictionary."); + } + prefix = stringToPDFString(p); + } else { + prefix = ""; + } + if (labelDict.has("St")) { + const st = labelDict.get("St"); + if (!(Number.isInteger(st) && st >= 1)) { + throw new FormatError3("Invalid start in PageLabel dictionary."); + } + currentIndex = st; + } else { + currentIndex = 1; + } + } + switch (style) { + case "D": + currentLabel = currentIndex; + break; + case "R": + case "r": + currentLabel = toRomanNumerals(currentIndex, style === "r"); + break; + case "A": + case "a": + const LIMIT = 26; + const A_UPPER_CASE = 65, A_LOWER_CASE = 97; + const baseCharCode = style === "a" ? A_LOWER_CASE : A_UPPER_CASE; + const letterIndex = currentIndex - 1; + const character = String.fromCharCode(baseCharCode + letterIndex % LIMIT); + currentLabel = character.repeat(Math.floor(letterIndex / LIMIT) + 1); + break; + default: + if (style) { + throw new FormatError3(`Invalid style "${style}" in PageLabel dictionary.`); + } + currentLabel = ""; + } + pageLabels[i] = prefix + currentLabel; + currentIndex++; + } + return pageLabels; + } + get pageLayout() { + const obj2 = this.#catDict.get("PageLayout"); + let pageLayout = ""; + if (obj2 instanceof Name2) { + switch (obj2.name) { + case "SinglePage": + case "OneColumn": + case "TwoColumnLeft": + case "TwoColumnRight": + case "TwoPageLeft": + case "TwoPageRight": + pageLayout = obj2.name; + } + } + return shadow2(this, "pageLayout", pageLayout); + } + get pageMode() { + const obj2 = this.#catDict.get("PageMode"); + let pageMode = "UseNone"; + if (obj2 instanceof Name2) { + switch (obj2.name) { + case "UseNone": + case "UseOutlines": + case "UseThumbs": + case "FullScreen": + case "UseOC": + case "UseAttachments": + pageMode = obj2.name; + } + } + return shadow2(this, "pageMode", pageMode); + } + get viewerPreferences() { + const obj2 = this.#catDict.get("ViewerPreferences"); + if (!(obj2 instanceof Dict)) { + return shadow2(this, "viewerPreferences", null); + } + let prefs = null; + for (const [key, value] of obj2) { + let prefValue; + switch (key) { + case "HideToolbar": + case "HideMenubar": + case "HideWindowUI": + case "FitWindow": + case "CenterWindow": + case "DisplayDocTitle": + case "PickTrayByPDFSize": + if (typeof value === "boolean") { + prefValue = value; + } + break; + case "NonFullScreenPageMode": + if (value instanceof Name2) { + switch (value.name) { + case "UseNone": + case "UseOutlines": + case "UseThumbs": + case "UseOC": + prefValue = value.name; + break; + default: + prefValue = "UseNone"; + } + } + break; + case "Direction": + if (value instanceof Name2) { + switch (value.name) { + case "L2R": + case "R2L": + prefValue = value.name; + break; + default: + prefValue = "L2R"; + } + } + break; + case "ViewArea": + case "ViewClip": + case "PrintArea": + case "PrintClip": + if (value instanceof Name2) { + switch (value.name) { + case "MediaBox": + case "CropBox": + case "BleedBox": + case "TrimBox": + case "ArtBox": + prefValue = value.name; + break; + default: + prefValue = "CropBox"; + } + } + break; + case "PrintScaling": + if (value instanceof Name2) { + switch (value.name) { + case "None": + case "AppDefault": + prefValue = value.name; + break; + default: + prefValue = "AppDefault"; + } + } + break; + case "Duplex": + if (value instanceof Name2) { + switch (value.name) { + case "Simplex": + case "DuplexFlipShortEdge": + case "DuplexFlipLongEdge": + prefValue = value.name; + break; + default: + prefValue = "None"; + } + } + break; + case "PrintPageRange": + if (Array.isArray(value) && value.length % 2 === 0) { + const isValid = value.every((page, i, arr) => Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= this.numPages); + if (isValid) { + prefValue = value; + } + } + break; + case "NumCopies": + if (Number.isInteger(value) && value > 0) { + prefValue = value; + } + break; + default: + warn2(`Ignoring non-standard key in ViewerPreferences: ${key}.`); + continue; + } + if (prefValue === void 0) { + warn2(`Bad value, for key "${key}", in ViewerPreferences: ${value}.`); + continue; + } + prefs ??= /* @__PURE__ */ Object.create(null); + prefs[key] = prefValue; + } + return shadow2(this, "viewerPreferences", prefs); + } + get openAction() { + const obj2 = this.#catDict.get("OpenAction"); + const openAction = /* @__PURE__ */ Object.create(null); + if (obj2 instanceof Dict) { + const destDict = new Dict(this.xref); + destDict.set("A", obj2); + const resultObj = { + url: null, + dest: null, + action: null + }; + _Catalog.parseDestDictionary({ + destDict, + resultObj + }); + if (Array.isArray(resultObj.dest)) { + openAction.dest = resultObj.dest; + } else if (resultObj.action) { + openAction.action = resultObj.action; + } + } else if (isValidExplicitDest2(obj2)) { + openAction.dest = obj2; + } + return shadow2(this, "openAction", objectSize(openAction) > 0 ? openAction : null); + } + get attachments() { + const obj2 = this.#catDict.get("Names"); + let attachments = null; + if (obj2 instanceof Dict && obj2.has("EmbeddedFiles")) { + const nameTree = new NameTree(obj2.getRaw("EmbeddedFiles"), this.xref); + for (const [key, value] of nameTree.getAll()) { + const fs2 = new FileSpec(value, this.xref); + attachments ??= /* @__PURE__ */ Object.create(null); + attachments[stringToPDFString(key, true)] = fs2.serializable; + } + } + return shadow2(this, "attachments", attachments); + } + get xfaImages() { + const obj2 = this.#catDict.get("Names"); + let xfaImages = null; + if (obj2 instanceof Dict && obj2.has("XFAImages")) { + const nameTree = new NameTree(obj2.getRaw("XFAImages"), this.xref); + for (const [key, value] of nameTree.getAll()) { + if (value instanceof BaseStream) { + xfaImages ??= /* @__PURE__ */ new Map(); + xfaImages.set(stringToPDFString(key, true), value.getBytes()); + } + } + } + return shadow2(this, "xfaImages", xfaImages); + } + #collectJavaScript() { + const obj2 = this.#catDict.get("Names"); + let javaScript = null; + function appendIfJavaScriptDict(name, jsDict) { + if (!(jsDict instanceof Dict)) { + return; + } + if (!isName(jsDict.get("S"), "JavaScript")) { + return; + } + let js = jsDict.get("JS"); + if (js instanceof BaseStream) { + js = js.getString(); + } else if (typeof js !== "string") { + return; + } + js = stringToPDFString(js, true).replaceAll("\0", ""); + if (js) { + (javaScript ||= /* @__PURE__ */ new Map()).set(name, js); + } + } + if (obj2 instanceof Dict && obj2.has("JavaScript")) { + const nameTree = new NameTree(obj2.getRaw("JavaScript"), this.xref); + for (const [key, value] of nameTree.getAll()) { + appendIfJavaScriptDict(stringToPDFString(key, true), value); + } + } + const openAction = this.#catDict.get("OpenAction"); + if (openAction) { + appendIfJavaScriptDict("OpenAction", openAction); + } + return javaScript; + } + get jsActions() { + const javaScript = this.#collectJavaScript(); + let actions = collectActions(this.xref, this.#catDict, DocumentActionEventType); + if (javaScript) { + actions ||= /* @__PURE__ */ Object.create(null); + for (const [key, val] of javaScript) { + if (key in actions) { + actions[key].push(val); + } else { + actions[key] = [val]; + } + } + } + return shadow2(this, "jsActions", actions); + } + async cleanup(manuallyTriggered = false) { + clearGlobalCaches(); + this.globalColorSpaceCache.clear(); + this.globalImageCache.clear(manuallyTriggered); + this.pageKidsCountCache.clear(); + this.pageIndexCache.clear(); + this.pageDictCache.clear(); + this.nonBlendModesSet.clear(); + for (const { + dict + } of await Promise.all(this.fontCache)) { + delete dict.cacheKey; + } + this.fontCache.clear(); + this.builtInCMapCache.clear(); + this.standardFontDataCache.clear(); + this.systemFontCache.clear(); + } + async getPageDict(pageIndex) { + const nodesToVisit = [this.toplevelPagesDict]; + const visitedNodes = new RefSet(); + const pagesRef = this.#catDict.getRaw("Pages"); + if (pagesRef instanceof Ref) { + visitedNodes.put(pagesRef); + } + const xref = this.xref, pageKidsCountCache = this.pageKidsCountCache, pageIndexCache = this.pageIndexCache, pageDictCache = this.pageDictCache; + let currentPageIndex = 0; + while (nodesToVisit.length) { + const currentNode = nodesToVisit.pop(); + if (currentNode instanceof Ref) { + const count2 = pageKidsCountCache.get(currentNode); + if (count2 >= 0 && currentPageIndex + count2 <= pageIndex) { + currentPageIndex += count2; + continue; + } + if (visitedNodes.has(currentNode)) { + throw new FormatError3("Pages tree contains circular reference."); + } + visitedNodes.put(currentNode); + const obj2 = await (pageDictCache.get(currentNode) || xref.fetchAsync(currentNode)); + if (obj2 instanceof Dict) { + let type = obj2.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !obj2.has("Kids")) { + if (!pageKidsCountCache.has(currentNode)) { + pageKidsCountCache.put(currentNode, 1); + } + if (!pageIndexCache.has(currentNode)) { + pageIndexCache.put(currentNode, currentPageIndex); + } + if (currentPageIndex === pageIndex) { + return [obj2, currentNode]; + } + currentPageIndex++; + continue; + } + } + nodesToVisit.push(obj2); + continue; + } + if (!(currentNode instanceof Dict)) { + throw new FormatError3("Page dictionary kid reference points to wrong type of object."); + } + const { + objId + } = currentNode; + let count = currentNode.getRaw("Count"); + if (count instanceof Ref) { + count = await xref.fetchAsync(count); + } + if (Number.isInteger(count) && count >= 0) { + if (objId && !pageKidsCountCache.has(objId)) { + pageKidsCountCache.put(objId, count); + } + if (currentPageIndex + count <= pageIndex) { + currentPageIndex += count; + continue; + } + } + let kids = currentNode.getRaw("Kids"); + if (kids instanceof Ref) { + kids = await xref.fetchAsync(kids); + } + if (!Array.isArray(kids)) { + let type = currentNode.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !currentNode.has("Kids")) { + if (currentPageIndex === pageIndex) { + return [currentNode, null]; + } + currentPageIndex++; + continue; + } + throw new FormatError3("Page dictionary kids object is not an array."); + } + for (let last2 = kids.length - 1; last2 >= 0; last2--) { + const lastKid = kids[last2]; + nodesToVisit.push(lastKid); + if (currentNode === this.toplevelPagesDict && lastKid instanceof Ref && !pageDictCache.has(lastKid)) { + pageDictCache.put(lastKid, xref.fetchAsync(lastKid)); + } + } + } + throw new Error(`Page index ${pageIndex} not found.`); + } + async getAllPageDicts(recoveryMode = false) { + const { + ignoreErrors + } = this.pdfManager.evaluatorOptions; + const queue = [{ + currentNode: this.toplevelPagesDict, + posInKids: 0 + }]; + const visitedNodes = new RefSet(); + const pagesRef = this.#catDict.getRaw("Pages"); + if (pagesRef instanceof Ref) { + visitedNodes.put(pagesRef); + } + const map3 = /* @__PURE__ */ new Map(), xref = this.xref, pageIndexCache = this.pageIndexCache; + let pageIndex = 0; + function addPageDict(pageDict, pageRef) { + if (pageRef && !pageIndexCache.has(pageRef)) { + pageIndexCache.put(pageRef, pageIndex); + } + map3.set(pageIndex++, [pageDict, pageRef]); + } + function addPageError(error62) { + if (error62 instanceof XRefEntryException && !recoveryMode) { + throw error62; + } + if (recoveryMode && ignoreErrors && pageIndex === 0) { + warn2(`getAllPageDicts - Skipping invalid first page: "${error62}".`); + error62 = Dict.empty; + } + map3.set(pageIndex++, [error62, null]); + } + while (queue.length > 0) { + const queueItem = queue.at(-1); + const { + currentNode, + posInKids + } = queueItem; + let kids = currentNode.getRaw("Kids"); + if (kids instanceof Ref) { + try { + kids = await xref.fetchAsync(kids); + } catch (ex) { + addPageError(ex); + break; + } + } + if (!Array.isArray(kids)) { + addPageError(new FormatError3("Page dictionary kids object is not an array.")); + break; + } + if (posInKids >= kids.length) { + queue.pop(); + continue; + } + const kidObj = kids[posInKids]; + let obj2; + if (kidObj instanceof Ref) { + if (visitedNodes.has(kidObj)) { + addPageError(new FormatError3("Pages tree contains circular reference.")); + break; + } + visitedNodes.put(kidObj); + try { + obj2 = await xref.fetchAsync(kidObj); + } catch (ex) { + addPageError(ex); + break; + } + } else { + obj2 = kidObj; + } + if (!(obj2 instanceof Dict)) { + addPageError(new FormatError3("Page dictionary kid reference points to wrong type of object.")); + break; + } + let type = obj2.getRaw("Type"); + if (type instanceof Ref) { + try { + type = await xref.fetchAsync(type); + } catch (ex) { + addPageError(ex); + break; + } + } + if (isName(type, "Page") || !obj2.has("Kids")) { + addPageDict(obj2, kidObj instanceof Ref ? kidObj : null); + } else { + queue.push({ + currentNode: obj2, + posInKids: 0 + }); + } + queueItem.posInKids++; + } + return map3; + } + getPageIndex(pageRef) { + const cachedPageIndex = this.pageIndexCache.get(pageRef); + if (cachedPageIndex !== void 0) { + return Promise.resolve(cachedPageIndex); + } + const xref = this.xref; + function pagesBeforeRef(kidRef) { + let total2 = 0, parentRef; + return xref.fetchAsync(kidRef).then(function(node2) { + if (isRefsEqual(kidRef, pageRef) && !isDict(node2, "Page") && !(node2 instanceof Dict && !node2.has("Type") && node2.has("Contents"))) { + throw new FormatError3("The reference does not point to a /Page dictionary."); + } + if (!node2) { + return null; + } + if (!(node2 instanceof Dict)) { + throw new FormatError3("Node must be a dictionary."); + } + parentRef = node2.getRaw("Parent"); + return node2.getAsync("Parent"); + }).then(function(parent) { + if (!parent) { + return null; + } + if (!(parent instanceof Dict)) { + throw new FormatError3("Parent must be a dictionary."); + } + return parent.getAsync("Kids"); + }).then(function(kids) { + if (!kids) { + return null; + } + const kidPromises = []; + let found = false; + for (const kid of kids) { + if (!(kid instanceof Ref)) { + throw new FormatError3("Kid must be a reference."); + } + if (isRefsEqual(kid, kidRef)) { + found = true; + break; + } + kidPromises.push(xref.fetchAsync(kid).then(function(obj2) { + if (!(obj2 instanceof Dict)) { + throw new FormatError3("Kid node must be a dictionary."); + } + if (obj2.has("Count")) { + total2 += obj2.get("Count"); + } else { + total2++; + } + })); + } + if (!found) { + throw new FormatError3("Kid reference not found in parent's kids."); + } + return Promise.all(kidPromises).then(() => [total2, parentRef]); + }); + } + let total = 0; + const next = (ref) => pagesBeforeRef(ref).then((args) => { + if (!args) { + this.pageIndexCache.put(pageRef, total); + return total; + } + const [count, parentRef] = args; + total += count; + return next(parentRef); + }); + return next(pageRef); + } + get baseUrl() { + const uri = this.#catDict.get("URI"); + if (uri instanceof Dict) { + const base = uri.get("Base"); + if (typeof base === "string") { + const absoluteUrl = createValidAbsoluteUrl2(base, null, { + tryConvertEncoding: true + }); + if (absoluteUrl) { + return shadow2(this, "baseUrl", absoluteUrl.href); + } + } + } + return shadow2(this, "baseUrl", this.pdfManager.docBaseUrl); + } + static parseDestDictionary({ + destDict, + resultObj, + docBaseUrl = null, + docAttachments = null + }) { + if (!(destDict instanceof Dict)) { + warn2("parseDestDictionary: `destDict` must be a dictionary."); + return; + } + let action = destDict.get("A"), url2, dest; + if (!(action instanceof Dict)) { + if (destDict.has("Dest")) { + action = destDict.get("Dest"); + } else { + action = destDict.get("AA"); + if (action instanceof Dict) { + if (action.has("D")) { + action = action.get("D"); + } else if (action.has("U")) { + action = action.get("U"); + } + } + } + } + if (action instanceof Dict) { + const actionType = action.get("S"); + if (!(actionType instanceof Name2)) { + warn2("parseDestDictionary: Invalid type in Action dictionary."); + return; + } + const actionName = actionType.name; + switch (actionName) { + case "ResetForm": + const flags = action.get("Flags"); + const include = ((typeof flags === "number" ? flags : 0) & 1) === 0; + const fields = []; + const refs = []; + for (const obj2 of action.get("Fields") || []) { + if (obj2 instanceof Ref) { + refs.push(obj2.toString()); + } else if (typeof obj2 === "string") { + fields.push(stringToPDFString(obj2)); + } + } + resultObj.resetForm = { + fields, + refs, + include + }; + break; + case "URI": + url2 = action.get("URI"); + if (url2 instanceof Name2) { + url2 = "/" + url2.name; + } + break; + case "GoTo": + dest = action.get("D"); + break; + case "Launch": + case "GoToR": + const urlDict = action.get("F"); + if (urlDict instanceof Dict) { + const fs2 = new FileSpec(urlDict, null, true); + const { + rawFilename + } = fs2.serializable; + url2 = rawFilename; + } else if (typeof urlDict === "string") { + url2 = urlDict; + } + const remoteDest = fetchRemoteDest(action); + if (remoteDest && typeof url2 === "string") { + url2 = url2.split("#", 1)[0] + "#" + remoteDest; + } + const newWindow = action.get("NewWindow"); + if (typeof newWindow === "boolean") { + resultObj.newWindow = newWindow; + } + break; + case "GoToE": + const target = action.get("T"); + let attachment; + if (docAttachments && target instanceof Dict) { + const relationship = target.get("R"); + const name = target.get("N"); + if (isName(relationship, "C") && typeof name === "string") { + attachment = docAttachments[stringToPDFString(name, true)]; + } + } + if (attachment) { + resultObj.attachment = attachment; + const attachmentDest = fetchRemoteDest(action); + if (attachmentDest) { + resultObj.attachmentDest = attachmentDest; + } + } else { + warn2(`parseDestDictionary - unimplemented "GoToE" action.`); + } + break; + case "Named": + const namedAction = action.get("N"); + if (namedAction instanceof Name2) { + resultObj.action = namedAction.name; + } + break; + case "SetOCGState": + const state = action.get("State"); + const preserveRB = action.get("PreserveRB"); + if (!Array.isArray(state) || state.length === 0) { + break; + } + const stateArr = []; + for (const elem of state) { + if (elem instanceof Name2) { + switch (elem.name) { + case "ON": + case "OFF": + case "Toggle": + stateArr.push(elem.name); + break; + } + } else if (elem instanceof Ref) { + stateArr.push(elem.toString()); + } + } + if (stateArr.length !== state.length) { + break; + } + resultObj.setOCGState = { + state: stateArr, + preserveRB: typeof preserveRB === "boolean" ? preserveRB : true + }; + break; + case "JavaScript": + const jsAction = action.get("JS"); + let js; + if (jsAction instanceof BaseStream) { + js = jsAction.getString(); + } else if (typeof jsAction === "string") { + js = jsAction; + } + const jsURL = js && recoverJsURL(stringToPDFString(js, true)); + if (jsURL) { + url2 = jsURL.url; + resultObj.newWindow = jsURL.newWindow; + break; + } + default: + if (actionName === "JavaScript" || actionName === "SubmitForm") { + break; + } + warn2(`parseDestDictionary - unsupported action: "${actionName}".`); + break; + } + } else if (destDict.has("Dest")) { + dest = destDict.get("Dest"); + } + if (typeof url2 === "string") { + const absoluteUrl = createValidAbsoluteUrl2(url2, docBaseUrl, { + addDefaultProtocol: true, + tryConvertEncoding: true + }); + if (absoluteUrl) { + resultObj.url = absoluteUrl.href; + } + resultObj.unsafeUrl = url2; + } + if (dest) { + if (dest instanceof Name2) { + dest = dest.name; + } + if (typeof dest === "string") { + resultObj.dest = stringToPDFString(dest, true); + } else if (isValidExplicitDest2(dest)) { + resultObj.dest = dest; + } + } + } + }; + ObjectLoader = class _ObjectLoader { + refSet = new RefSet(); + constructor(dict, keys2, xref) { + this.dict = dict; + this.keys = keys2; + this.xref = xref; + } + async load() { + const { + keys: keys2, + dict + } = this; + const nodesToVisit = []; + for (const key of keys2) { + const rawValue = dict.getRaw(key); + if (rawValue !== void 0) { + nodesToVisit.push(rawValue); + } + } + await this.#walk(nodesToVisit); + this.refSet = null; + } + async #walk(nodesToVisit) { + const nodesToRevisit = []; + const pendingRequests = []; + while (nodesToVisit.length) { + let currentNode = nodesToVisit.pop(); + if (currentNode instanceof Ref) { + if (this.refSet.has(currentNode)) { + continue; + } + try { + this.refSet.put(currentNode); + currentNode = this.xref.fetch(currentNode); + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + warn2(`ObjectLoader.#walk - requesting all data: "${ex}".`); + await this.xref.stream.manager.requestAllChunks(); + return; + } + nodesToRevisit.push(currentNode); + pendingRequests.push({ + begin: ex.begin, + end: ex.end + }); + } + } + if (currentNode instanceof BaseStream) { + const baseStreams = currentNode.getBaseStreams(); + if (baseStreams) { + let foundMissingData = false; + for (const stream of baseStreams) { + if (stream.isDataLoaded) { + continue; + } + foundMissingData = true; + pendingRequests.push({ + begin: stream.start, + end: stream.end + }); + } + if (foundMissingData) { + nodesToRevisit.push(currentNode); + } + } + } + addChildren(currentNode, nodesToVisit); + } + if (pendingRequests.length) { + await this.xref.stream.manager.requestRanges(pendingRequests); + for (const node2 of nodesToRevisit) { + if (node2 instanceof Ref) { + this.refSet.remove(node2); + } + } + await this.#walk(nodesToRevisit); + } + } + static async load(obj2, keys2, xref) { + if (xref.stream.isDataLoaded) { + return; + } + const objLoader = new _ObjectLoader(obj2, keys2, xref); + await objLoader.load(); + } + }; + $acceptWhitespace = Symbol(); + $addHTML = Symbol(); + $appendChild = Symbol(); + $childrenToHTML = Symbol(); + $clean = Symbol(); + $cleanPage = Symbol(); + $cleanup = Symbol(); + $clone = Symbol(); + $consumed = Symbol(); + $content = Symbol("content"); + $data = Symbol("data"); + $dump = Symbol(); + $extra = Symbol("extra"); + $finalize = Symbol(); + $flushHTML = Symbol(); + $getAttributeIt = Symbol(); + $getAttributes = Symbol(); + $getAvailableSpace = Symbol(); + $getChildrenByClass = Symbol(); + $getChildrenByName = Symbol(); + $getChildrenByNameIt = Symbol(); + $getDataValue = Symbol(); + $getExtra = Symbol(); + $getRealChildrenByNameIt = Symbol(); + $getChildren = Symbol(); + $getContainedChildren = Symbol(); + $getNextPage = Symbol(); + $getSubformParent = Symbol(); + $getParent = Symbol(); + $getTemplateRoot = Symbol(); + $globalData = Symbol(); + $hasSettableValue = Symbol(); + $ids = Symbol(); + $indexOf = Symbol(); + $insertAt = Symbol(); + $isCDATAXml = Symbol(); + $isBindable = Symbol(); + $isDataValue = Symbol(); + $isDescendent = Symbol(); + $isNsAgnostic = Symbol(); + $isSplittable = Symbol(); + $isThereMoreWidth = Symbol(); + $isTransparent = Symbol(); + $isUsable = Symbol(); + $lastAttribute = Symbol(); + $namespaceId = Symbol("namespaceId"); + $nodeName = Symbol("nodeName"); + $nsAttributes = Symbol(); + $onChild = Symbol(); + $onChildCheck = Symbol(); + $onText = Symbol(); + $pushGlyphs = Symbol(); + $popPara = Symbol(); + $pushPara = Symbol(); + $removeChild = Symbol(); + $root = Symbol("root"); + $resolvePrototypes = Symbol(); + $searchNode = Symbol(); + $setId = Symbol(); + $setSetAttributes = Symbol(); + $setValue = Symbol(); + $tabIndex = Symbol(); + $text = Symbol(); + $toPages = Symbol(); + $toHTML = Symbol(); + $toString = Symbol(); + $toStyle = Symbol(); + $uid = Symbol("uid"); + es_iterator_flat_map2 = __webpack_require__2(531); + $buildXFAObject = Symbol(); + NamespaceIds = { + config: { + id: 0, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xci/") + }, + connectionSet: { + id: 1, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-connection-set/") + }, + datasets: { + id: 2, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-data/") + }, + form: { + id: 3, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-form/") + }, + localeSet: { + id: 4, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-locale-set/") + }, + pdf: { + id: 5, + check: (ns) => ns === "http://ns.adobe.com/xdp/pdf/" + }, + signature: { + id: 6, + check: (ns) => ns === "http://www.w3.org/2000/09/xmldsig#" + }, + sourceSet: { + id: 7, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-source-set/") + }, + stylesheet: { + id: 8, + check: (ns) => ns === "http://www.w3.org/1999/XSL/Transform" + }, + template: { + id: 9, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xfa-template/") + }, + xdc: { + id: 10, + check: (ns) => ns.startsWith("http://www.xfa.org/schema/xdc/") + }, + xdp: { + id: 11, + check: (ns) => ns === "http://ns.adobe.com/xdp/" + }, + xfdf: { + id: 12, + check: (ns) => ns === "http://ns.adobe.com/xfdf/" + }, + xhtml: { + id: 13, + check: (ns) => ns === "http://www.w3.org/1999/xhtml" + }, + xmpmeta: { + id: 14, + check: (ns) => ns === "http://ns.adobe.com/xmpmeta/" + } + }; + dimConverters = { + pt: (x) => x, + cm: (x) => x / 2.54 * 72, + mm: (x) => x / (10 * 2.54) * 72, + in: (x) => x * 72, + px: (x) => x + }; + measurementPattern = /([+-]?\d+\.?\d*)(.*)/; + HTMLResult = class _HTMLResult { + static get FAILURE() { + return shadow2(this, "FAILURE", new _HTMLResult(false, null, null, null)); + } + static get EMPTY() { + return shadow2(this, "EMPTY", new _HTMLResult(true, null, null, null)); + } + constructor(success2, html, bbox, breakNode) { + this.success = success2; + this.html = html; + this.bbox = bbox; + this.breakNode = breakNode; + } + isBreak() { + return !!this.breakNode; + } + static breakNode(node2) { + return new _HTMLResult(false, null, null, node2); + } + static success(html, bbox = null) { + return new _HTMLResult(true, html, bbox, null); + } + }; + FontFinder = class { + constructor(pdfFonts) { + this.fonts = /* @__PURE__ */ new Map(); + this.cache = /* @__PURE__ */ new Map(); + this.warned = /* @__PURE__ */ new Set(); + this.defaultFont = null; + this.add(pdfFonts); + } + add(pdfFonts, reallyMissingFonts = null) { + for (const pdfFont of pdfFonts) { + this.addPdfFont(pdfFont); + } + for (const pdfFont of this.fonts.values()) { + if (!pdfFont.regular) { + pdfFont.regular = pdfFont.italic || pdfFont.bold || pdfFont.bolditalic; + } + } + if (!reallyMissingFonts || reallyMissingFonts.size === 0) { + return; + } + const myriad = this.fonts.get("PdfJS-Fallback-PdfJS-XFA"); + for (const missing of reallyMissingFonts) { + this.fonts.set(missing, myriad); + } + } + addPdfFont(pdfFont) { + const cssFontInfo = pdfFont.cssFontInfo; + const name = cssFontInfo.fontFamily; + let font = this.fonts.get(name); + if (!font) { + font = /* @__PURE__ */ Object.create(null); + this.fonts.set(name, font); + if (!this.defaultFont) { + this.defaultFont = font; + } + } + let property2 = ""; + const fontWeight = parseFloat(cssFontInfo.fontWeight); + if (parseFloat(cssFontInfo.italicAngle) !== 0) { + property2 = fontWeight >= 700 ? "bolditalic" : "italic"; + } else if (fontWeight >= 700) { + property2 = "bold"; + } + if (!property2) { + if (pdfFont.name.includes("Bold") || pdfFont.psName?.includes("Bold")) { + property2 = "bold"; + } + if (pdfFont.name.includes("Italic") || pdfFont.name.endsWith("It") || pdfFont.psName?.includes("Italic") || pdfFont.psName?.endsWith("It")) { + property2 += "italic"; + } + } + if (!property2) { + property2 = "regular"; + } + font[property2] = pdfFont; + } + getDefault() { + return this.defaultFont; + } + find(fontName, mustWarn = true) { + let font = this.fonts.get(fontName) || this.cache.get(fontName); + if (font) { + return font; + } + const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi; + let name = fontName.replaceAll(pattern, ""); + font = this.fonts.get(name); + if (font) { + this.cache.set(fontName, font); + return font; + } + name = name.toLowerCase(); + const maybe = []; + for (const [family, pdfFont] of this.fonts.entries()) { + if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + if (maybe.length === 0) { + for (const [, pdfFont] of this.fonts.entries()) { + if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length === 0) { + name = name.replaceAll(/psmt|mt/gi, ""); + for (const [family, pdfFont] of this.fonts.entries()) { + if (family.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length === 0) { + for (const pdfFont of this.fonts.values()) { + if (pdfFont.regular.name?.replaceAll(pattern, "").toLowerCase().startsWith(name)) { + maybe.push(pdfFont); + } + } + } + if (maybe.length >= 1) { + if (maybe.length !== 1 && mustWarn) { + warn2(`XFA - Too many choices to guess the correct font: ${fontName}`); + } + this.cache.set(fontName, maybe[0]); + return maybe[0]; + } + if (mustWarn && !this.warned.has(fontName)) { + this.warned.add(fontName); + warn2(`XFA - Cannot find the font: ${fontName}`); + } + return null; + } + }; + WIDTH_FACTOR = 1.02; + text_FontInfo = class { + constructor(xfaFont, margin, lineHeight, fontFinder) { + this.lineHeight = lineHeight; + this.paraMargin = margin || { + top: 0, + bottom: 0, + left: 0, + right: 0 + }; + if (!xfaFont) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + return; + } + this.xfaFont = { + typeface: xfaFont.typeface, + posture: xfaFont.posture, + weight: xfaFont.weight, + size: xfaFont.size, + letterSpacing: xfaFont.letterSpacing + }; + const typeface = fontFinder.find(xfaFont.typeface); + if (!typeface) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + return; + } + this.pdfFont = selectFont(xfaFont, typeface); + if (!this.pdfFont) { + [this.pdfFont, this.xfaFont] = this.defaultFont(fontFinder); + } + } + defaultFont(fontFinder) { + const font = fontFinder.find("Helvetica", false) || fontFinder.find("Myriad Pro", false) || fontFinder.find("Arial", false) || fontFinder.getDefault(); + if (font?.regular) { + const pdfFont = font.regular; + const info3 = pdfFont.cssFontInfo; + const xfaFont2 = { + typeface: info3.fontFamily, + posture: "normal", + weight: "normal", + size: 10, + letterSpacing: 0 + }; + return [pdfFont, xfaFont2]; + } + const xfaFont = { + typeface: "Courier", + posture: "normal", + weight: "normal", + size: 10, + letterSpacing: 0 + }; + return [null, xfaFont]; + } + }; + FontSelector = class { + constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder) { + this.fontFinder = fontFinder; + this.stack = [new text_FontInfo(defaultXfaFont, defaultParaMargin, defaultLineHeight, fontFinder)]; + } + pushData(xfaFont, margin, lineHeight) { + const lastFont = this.stack.at(-1); + for (const name of ["typeface", "posture", "weight", "size", "letterSpacing"]) { + if (!xfaFont[name]) { + xfaFont[name] = lastFont.xfaFont[name]; + } + } + for (const name of ["top", "bottom", "left", "right"]) { + if (isNaN(margin[name])) { + margin[name] = lastFont.paraMargin[name]; + } + } + const fontInfo = new text_FontInfo(xfaFont, margin, lineHeight || lastFont.lineHeight, this.fontFinder); + if (!fontInfo.pdfFont) { + fontInfo.pdfFont = lastFont.pdfFont; + } + this.stack.push(fontInfo); + } + popFont() { + this.stack.pop(); + } + topFont() { + return this.stack.at(-1); + } + }; + TextMeasure = class { + constructor(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts) { + this.glyphs = []; + this.fontSelector = new FontSelector(defaultXfaFont, defaultParaMargin, defaultLineHeight, fonts); + this.extraHeight = 0; + } + pushData(xfaFont, margin, lineHeight) { + this.fontSelector.pushData(xfaFont, margin, lineHeight); + } + popFont(xfaFont) { + return this.fontSelector.popFont(); + } + addPara() { + const lastFont = this.fontSelector.topFont(); + this.extraHeight += lastFont.paraMargin.top + lastFont.paraMargin.bottom; + } + addString(str) { + if (!str) { + return; + } + const lastFont = this.fontSelector.topFont(); + const fontSize = lastFont.xfaFont.size; + if (lastFont.pdfFont) { + const letterSpacing = lastFont.xfaFont.letterSpacing; + const pdfFont = lastFont.pdfFont; + const fontLineHeight = pdfFont.lineHeight || 1.2; + const lineHeight = lastFont.lineHeight || Math.max(1.2, fontLineHeight) * fontSize; + const lineGap = pdfFont.lineGap === void 0 ? 0.2 : pdfFont.lineGap; + const noGap = fontLineHeight - lineGap; + const firstLineHeight = Math.max(1, noGap) * fontSize; + const scale = fontSize / 1e3; + const fallbackWidth = pdfFont.defaultWidth || pdfFont.charsToGlyphs(" ")[0].width; + for (const line2 of str.split(/[\u2029\n]/)) { + const encodedLine = pdfFont.encodeString(line2).join(""); + const glyphs = pdfFont.charsToGlyphs(encodedLine); + for (const glyph of glyphs) { + const width = glyph.width || fallbackWidth; + this.glyphs.push([width * scale + letterSpacing, lineHeight, firstLineHeight, glyph.unicode, false]); + } + this.glyphs.push([0, 0, 0, "\n", true]); + } + this.glyphs.pop(); + return; + } + for (const line2 of str.split(/[\u2029\n]/)) { + for (const char2 of line2.split("")) { + this.glyphs.push([fontSize, 1.2 * fontSize, fontSize, char2, false]); + } + this.glyphs.push([0, 0, 0, "\n", true]); + } + this.glyphs.pop(); + } + compute(maxWidth) { + let lastSpacePos = -1, lastSpaceWidth = 0, width = 0, height = 0, currentLineWidth = 0, currentLineHeight = 0; + let isBroken = false; + let isFirstLine = true; + for (let i = 0, ii = this.glyphs.length; i < ii; i++) { + const [glyphWidth, lineHeight, firstLineHeight, char2, isEOL] = this.glyphs[i]; + const isSpace = char2 === " "; + const glyphHeight = isFirstLine ? firstLineHeight : lineHeight; + if (isEOL) { + width = Math.max(width, currentLineWidth); + currentLineWidth = 0; + height += currentLineHeight; + currentLineHeight = glyphHeight; + lastSpacePos = -1; + lastSpaceWidth = 0; + isFirstLine = false; + continue; + } + if (isSpace) { + if (currentLineWidth + glyphWidth > maxWidth) { + width = Math.max(width, currentLineWidth); + currentLineWidth = 0; + height += currentLineHeight; + currentLineHeight = glyphHeight; + lastSpacePos = -1; + lastSpaceWidth = 0; + isBroken = true; + isFirstLine = false; + } else { + currentLineHeight = Math.max(glyphHeight, currentLineHeight); + lastSpaceWidth = currentLineWidth; + currentLineWidth += glyphWidth; + lastSpacePos = i; + } + continue; + } + if (currentLineWidth + glyphWidth > maxWidth) { + height += currentLineHeight; + currentLineHeight = glyphHeight; + if (lastSpacePos !== -1) { + i = lastSpacePos; + width = Math.max(width, lastSpaceWidth); + currentLineWidth = 0; + lastSpacePos = -1; + lastSpaceWidth = 0; + } else { + width = Math.max(width, currentLineWidth); + currentLineWidth = glyphWidth; + } + isBroken = true; + isFirstLine = false; + continue; + } + currentLineWidth += glyphWidth; + currentLineHeight = Math.max(glyphHeight, currentLineHeight); + } + width = Math.max(width, currentLineWidth); + height += currentLineHeight + this.extraHeight; + return { + width: WIDTH_FACTOR * width, + height, + isBroken + }; + } + }; + namePattern = /^[^.[]+/; + indexPattern = /^[^\]]+/; + operators = { + dot: 0, + dotDot: 1, + dotHash: 2, + dotBracket: 3, + dotParen: 4 + }; + shortcuts = /* @__PURE__ */ new Map([["$data", (root2, current) => root2.datasets ? root2.datasets.data : root2], ["$record", (root2, current) => (root2.datasets ? root2.datasets.data : root2)[$getChildren]()[0]], ["$template", (root2, current) => root2.template], ["$connectionSet", (root2, current) => root2.connectionSet], ["$form", (root2, current) => root2.form], ["$layout", (root2, current) => root2.layout], ["$host", (root2, current) => root2.host], ["$dataWindow", (root2, current) => root2.dataWindow], ["$event", (root2, current) => root2.event], ["!", (root2, current) => root2.datasets], ["$xfa", (root2, current) => root2], ["xfa", (root2, current) => root2], ["$", (root2, current) => current]]); + somCache = /* @__PURE__ */ new WeakMap(); + _applyPrototype = Symbol(); + _attributes = Symbol(); + _attributeNames = Symbol(); + _children = Symbol("_children"); + _cloneAttribute = Symbol(); + _dataValue = Symbol(); + _defaultValue = Symbol(); + _filteredChildrenGenerator = Symbol(); + _getPrototype = Symbol(); + _getUnsetAttributes = Symbol(); + _hasChildren = Symbol(); + _max = Symbol(); + _options = Symbol(); + _parent = Symbol("parent"); + _resolvePrototypesHelper = Symbol(); + _setAttributes = Symbol(); + _validator = Symbol(); + uid2 = 0; + NS_DATASETS = NamespaceIds.datasets.id; + XFAObject = class _XFAObject { + constructor(nsId, name, hasChildren = false) { + this[$namespaceId] = nsId; + this[$nodeName] = name; + this[_hasChildren] = hasChildren; + this[_parent] = null; + this[_children] = []; + this[$uid] = `${name}${uid2++}`; + this[$globalData] = null; + } + get isXFAObject() { + return true; + } + get isXFAObjectArray() { + return false; + } + createNodes(path2) { + let root2 = this, node2 = null; + for (const { + name, + index: index2 + } of path2) { + for (let i = 0, ii = isFinite(index2) ? index2 : 0; i <= ii; i++) { + const nsId = root2[$namespaceId] === NS_DATASETS ? -1 : root2[$namespaceId]; + node2 = new XmlObject(nsId, name); + root2[$appendChild](node2); + } + root2 = node2; + } + return node2; + } + [$onChild](child) { + if (!this[_hasChildren] || !this[$onChildCheck](child)) { + return false; + } + const name = child[$nodeName]; + const node2 = this[name]; + if (node2 instanceof XFAObjectArray) { + if (node2.push(child)) { + this[$appendChild](child); + return true; + } + } else { + if (node2 !== null) { + this[$removeChild](node2); + } + this[name] = child; + this[$appendChild](child); + return true; + } + let id = ""; + if (this.id) { + id = ` (id: ${this.id})`; + } else if (this.name) { + id = ` (name: ${this.name} ${this.h.value})`; + } + warn2(`XFA - node "${this[$nodeName]}"${id} has already enough "${name}"!`); + return false; + } + [$onChildCheck](child) { + return this.hasOwnProperty(child[$nodeName]) && child[$namespaceId] === this[$namespaceId]; + } + [$isNsAgnostic]() { + return false; + } + [$acceptWhitespace]() { + return false; + } + [$isCDATAXml]() { + return false; + } + [$isBindable]() { + return false; + } + [$popPara]() { + if (this.para) { + this[$getTemplateRoot]()[$extra].paraStack.pop(); + } + } + [$pushPara]() { + this[$getTemplateRoot]()[$extra].paraStack.push(this.para); + } + [$setId](ids) { + if (this.id && this[$namespaceId] === NamespaceIds.template.id) { + ids.set(this.id, this); + } + } + [$getTemplateRoot]() { + return this[$globalData].template; + } + [$isSplittable]() { + return false; + } + [$isThereMoreWidth]() { + return false; + } + [$appendChild](child) { + child[_parent] = this; + this[_children].push(child); + if (!child[$globalData] && this[$globalData]) { + child[$globalData] = this[$globalData]; + } + } + [$removeChild](child) { + const i = this[_children].indexOf(child); + this[_children].splice(i, 1); + } + [$hasSettableValue]() { + return this.hasOwnProperty("value"); + } + [$setValue](_3) { + } + [$onText](_3) { + } + [$finalize]() { + } + [$clean](builder) { + delete this[_hasChildren]; + if (this[$cleanup]) { + builder.clean(this[$cleanup]); + delete this[$cleanup]; + } + } + [$indexOf](child) { + return this[_children].indexOf(child); + } + [$insertAt](i, child) { + child[_parent] = this; + this[_children].splice(i, 0, child); + if (!child[$globalData] && this[$globalData]) { + child[$globalData] = this[$globalData]; + } + } + [$isTransparent]() { + return !this.name; + } + [$lastAttribute]() { + return ""; + } + [$text]() { + if (this[_children].length === 0) { + return this[$content]; + } + return this[_children].map((c) => c[$text]()).join(""); + } + get [_attributeNames]() { + const proto = Object.getPrototypeOf(this); + if (!proto._attributes) { + const attributes = proto._attributes = /* @__PURE__ */ new Set(); + for (const name of Object.getOwnPropertyNames(this)) { + if (this[name] === null || this[name] instanceof _XFAObject || this[name] instanceof XFAObjectArray) { + break; + } + attributes.add(name); + } + } + return shadow2(this, _attributeNames, proto._attributes); + } + [$isDescendent](parent) { + let node2 = this; + while (node2) { + if (node2 === parent) { + return true; + } + node2 = node2[$getParent](); + } + return false; + } + [$getParent]() { + return this[_parent]; + } + [$getSubformParent]() { + return this[$getParent](); + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[name]; + } + [$dump]() { + const dumped = /* @__PURE__ */ Object.create(null); + if (this[$content]) { + dumped.$content = this[$content]; + } + for (const name of Object.getOwnPropertyNames(this)) { + const value = this[name]; + if (value === null) { + continue; + } + if (value instanceof _XFAObject) { + dumped[name] = value[$dump](); + } else if (value instanceof XFAObjectArray) { + if (!value.isEmpty()) { + dumped[name] = value.dump(); + } + } else { + dumped[name] = value; + } + } + return dumped; + } + [$toStyle]() { + return null; + } + [$toHTML]() { + return HTMLResult.EMPTY; + } + *[$getContainedChildren]() { + for (const node2 of this[$getChildren]()) { + yield node2; + } + } + *[_filteredChildrenGenerator](filter2, include) { + for (const node2 of this[$getContainedChildren]()) { + if (!filter2 || include === filter2.has(node2[$nodeName])) { + const availableSpace = this[$getAvailableSpace](); + const res = node2[$toHTML](availableSpace); + if (!res.success) { + this[$extra].failingNode = node2; + } + yield res; + } + } + } + [$flushHTML]() { + return null; + } + [$addHTML](html, bbox) { + this[$extra].children.push(html); + } + [$getAvailableSpace]() { + } + [$childrenToHTML]({ + filter: filter2 = null, + include = true + }) { + if (!this[$extra].generator) { + this[$extra].generator = this[_filteredChildrenGenerator](filter2, include); + } else { + const availableSpace = this[$getAvailableSpace](); + const res = this[$extra].failingNode[$toHTML](availableSpace); + if (!res.success) { + return res; + } + if (res.html) { + this[$addHTML](res.html, res.bbox); + } + delete this[$extra].failingNode; + } + while (true) { + const gen = this[$extra].generator.next(); + if (gen.done) { + break; + } + const res = gen.value; + if (!res.success) { + return res; + } + if (res.html) { + this[$addHTML](res.html, res.bbox); + } + } + this[$extra].generator = null; + return HTMLResult.EMPTY; + } + [$setSetAttributes](attributes) { + this[_setAttributes] = new Set(Object.keys(attributes)); + } + [_getUnsetAttributes](protoAttributes) { + const allAttr = this[_attributeNames]; + const setAttr = this[_setAttributes]; + return [...protoAttributes].filter((x) => allAttr.has(x) && !setAttr.has(x)); + } + [$resolvePrototypes](ids, ancestors = /* @__PURE__ */ new Set()) { + for (const child of this[_children]) { + child[_resolvePrototypesHelper](ids, ancestors); + } + } + [_resolvePrototypesHelper](ids, ancestors) { + const proto = this[_getPrototype](ids, ancestors); + if (proto) { + this[_applyPrototype](proto, ids, ancestors); + } else { + this[$resolvePrototypes](ids, ancestors); + } + } + [_getPrototype](ids, ancestors) { + const { + use, + usehref + } = this; + if (!use && !usehref) { + return null; + } + let proto = null; + let somExpression = null; + let id = null; + let ref = use; + if (usehref) { + ref = usehref; + if (usehref.startsWith("#som(") && usehref.endsWith(")")) { + somExpression = usehref.slice("#som(".length, -1); + } else if (usehref.startsWith(".#som(") && usehref.endsWith(")")) { + somExpression = usehref.slice(".#som(".length, -1); + } else if (usehref.startsWith("#")) { + id = usehref.slice(1); + } else if (usehref.startsWith(".#")) { + id = usehref.slice(2); + } + } else if (use.startsWith("#")) { + id = use.slice(1); + } else { + somExpression = use; + } + this.use = this.usehref = ""; + if (id) { + proto = ids.get(id); + } else { + proto = searchNode(ids.get($root), this, somExpression, true, false); + if (proto) { + proto = proto[0]; + } + } + if (!proto) { + warn2(`XFA - Invalid prototype reference: ${ref}.`); + return null; + } + if (proto[$nodeName] !== this[$nodeName]) { + warn2(`XFA - Incompatible prototype: ${proto[$nodeName]} !== ${this[$nodeName]}.`); + return null; + } + if (ancestors.has(proto)) { + warn2(`XFA - Cycle detected in prototypes use.`); + return null; + } + ancestors.add(proto); + const protoProto = proto[_getPrototype](ids, ancestors); + if (protoProto) { + proto[_applyPrototype](protoProto, ids, ancestors); + } + proto[$resolvePrototypes](ids, ancestors); + ancestors.delete(proto); + return proto; + } + [_applyPrototype](proto, ids, ancestors) { + if (ancestors.has(proto)) { + warn2(`XFA - Cycle detected in prototypes use.`); + return; + } + if (!this[$content] && proto[$content]) { + this[$content] = proto[$content]; + } + const newAncestors = new Set(ancestors); + newAncestors.add(proto); + for (const unsetAttrName of this[_getUnsetAttributes](proto[_setAttributes])) { + this[unsetAttrName] = proto[unsetAttrName]; + if (this[_setAttributes]) { + this[_setAttributes].add(unsetAttrName); + } + } + for (const name of Object.getOwnPropertyNames(this)) { + if (this[_attributeNames].has(name)) { + continue; + } + const value = this[name]; + const protoValue = proto[name]; + if (value instanceof XFAObjectArray) { + for (const child of value[_children]) { + child[_resolvePrototypesHelper](ids, ancestors); + } + for (let i = value[_children].length, ii = protoValue[_children].length; i < ii; i++) { + const child = proto[_children][i][$clone](); + if (value.push(child)) { + child[_parent] = this; + this[_children].push(child); + child[_resolvePrototypesHelper](ids, ancestors); + } else { + break; + } + } + continue; + } + if (value !== null) { + value[$resolvePrototypes](ids, ancestors); + if (protoValue) { + value[_applyPrototype](protoValue, ids, ancestors); + } + continue; + } + if (protoValue !== null) { + const child = protoValue[$clone](); + child[_parent] = this; + this[name] = child; + this[_children].push(child); + child[_resolvePrototypesHelper](ids, ancestors); + } + } + } + static [_cloneAttribute](obj2) { + if (Array.isArray(obj2)) { + return obj2.map((x) => _XFAObject[_cloneAttribute](x)); + } + if (typeof obj2 === "object" && obj2 !== null) { + return Object.assign({}, obj2); + } + return obj2; + } + [$clone]() { + const clone3 = Object.create(Object.getPrototypeOf(this)); + for (const $symbol of Object.getOwnPropertySymbols(this)) { + try { + clone3[$symbol] = this[$symbol]; + } catch { + shadow2(clone3, $symbol, this[$symbol]); + } + } + clone3[$uid] = `${clone3[$nodeName]}${uid2++}`; + clone3[_children] = []; + for (const name of Object.getOwnPropertyNames(this)) { + if (this[_attributeNames].has(name)) { + clone3[name] = _XFAObject[_cloneAttribute](this[name]); + continue; + } + const value = this[name]; + clone3[name] = value instanceof XFAObjectArray ? new XFAObjectArray(value[_max]) : null; + } + for (const child of this[_children]) { + const name = child[$nodeName]; + const clonedChild = child[$clone](); + clone3[_children].push(clonedChild); + clonedChild[_parent] = clone3; + if (clone3[name] === null) { + clone3[name] = clonedChild; + } else { + clone3[name][_children].push(clonedChild); + } + } + return clone3; + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[_children].filter((c) => c[$nodeName] === name); + } + [$getChildrenByClass](name) { + return this[name]; + } + [$getChildrenByName](name, allTransparent, first2 = true) { + return Array.from(this[$getChildrenByNameIt](name, allTransparent, first2)); + } + *[$getChildrenByNameIt](name, allTransparent, first2 = true) { + if (name === "parent") { + yield this[_parent]; + return; + } + for (const child of this[_children]) { + if (child[$nodeName] === name) { + yield child; + } + if (child.name === name) { + yield child; + } + if (allTransparent || child[$isTransparent]()) { + yield* child[$getChildrenByNameIt](name, allTransparent, false); + } + } + if (first2 && this[_attributeNames].has(name)) { + yield new XFAAttribute(this, name, this[name]); + } + } + }; + XFAObjectArray = class _XFAObjectArray { + constructor(max2 = Infinity) { + this[_max] = max2; + this[_children] = []; + } + get isXFAObject() { + return false; + } + get isXFAObjectArray() { + return true; + } + push(child) { + const len = this[_children].length; + if (len <= this[_max]) { + this[_children].push(child); + return true; + } + warn2(`XFA - node "${child[$nodeName]}" accepts no more than ${this[_max]} children`); + return false; + } + isEmpty() { + return this[_children].length === 0; + } + dump() { + return this[_children].length === 1 ? this[_children][0][$dump]() : this[_children].map((x) => x[$dump]()); + } + [$clone]() { + const clone3 = new _XFAObjectArray(this[_max]); + clone3[_children] = this[_children].map((c) => c[$clone]()); + return clone3; + } + get children() { + return this[_children]; + } + clear() { + this[_children].length = 0; + } + }; + XFAAttribute = class { + constructor(node2, name, value) { + this[_parent] = node2; + this[$nodeName] = name; + this[$content] = value; + this[$consumed] = false; + this[$uid] = `attribute${uid2++}`; + } + [$getParent]() { + return this[_parent]; + } + [$isDataValue]() { + return true; + } + [$getDataValue]() { + return this[$content].trim(); + } + [$setValue](value) { + value = value.value || ""; + this[$content] = value.toString(); + } + [$text]() { + return this[$content]; + } + [$isDescendent](parent) { + return this[_parent] === parent || this[_parent][$isDescendent](parent); + } + }; + XmlObject = class _XmlObject extends XFAObject { + constructor(nsId, name, attributes = {}) { + super(nsId, name); + this[$content] = ""; + this[_dataValue] = null; + if (name !== "#text") { + const map3 = /* @__PURE__ */ new Map(); + this[_attributes] = map3; + for (const [attrName, value] of Object.entries(attributes)) { + map3.set(attrName, new XFAAttribute(this, attrName, value)); + } + if (attributes.hasOwnProperty($nsAttributes)) { + const dataNode = attributes[$nsAttributes].xfa.dataNode; + if (dataNode !== void 0) { + if (dataNode === "dataGroup") { + this[_dataValue] = false; + } else if (dataNode === "dataValue") { + this[_dataValue] = true; + } + } + } + } + this[$consumed] = false; + } + [$toString](buf) { + const tagName = this[$nodeName]; + if (tagName === "#text") { + buf.push(encodeToXmlString(this[$content])); + return; + } + const utf8TagName = utf8StringToString(tagName); + const prefix = this[$namespaceId] === NS_DATASETS ? "xfa:" : ""; + buf.push(`<${prefix}${utf8TagName}`); + for (const [name, value] of this[_attributes].entries()) { + const utf8Name = utf8StringToString(name); + buf.push(` ${utf8Name}="${encodeToXmlString(value[$content])}"`); + } + if (this[_dataValue] !== null) { + if (this[_dataValue]) { + buf.push(` xfa:dataNode="dataValue"`); + } else { + buf.push(` xfa:dataNode="dataGroup"`); + } + } + if (!this[$content] && this[_children].length === 0) { + buf.push("/>"); + return; + } + buf.push(">"); + if (this[$content]) { + if (typeof this[$content] === "string") { + buf.push(encodeToXmlString(this[$content])); + } else { + this[$content][$toString](buf); + } + } else { + for (const child of this[_children]) { + child[$toString](buf); + } + } + buf.push(``); + } + [$onChild](child) { + if (this[$content]) { + const node2 = new _XmlObject(this[$namespaceId], "#text"); + this[$appendChild](node2); + node2[$content] = this[$content]; + this[$content] = ""; + } + this[$appendChild](child); + return true; + } + [$onText](str) { + this[$content] += str; + } + [$finalize]() { + if (this[$content] && this[_children].length > 0) { + const node2 = new _XmlObject(this[$namespaceId], "#text"); + this[$appendChild](node2); + node2[$content] = this[$content]; + delete this[$content]; + } + } + [$toHTML]() { + if (this[$nodeName] === "#text") { + return HTMLResult.success({ + name: "#text", + value: this[$content] + }); + } + return HTMLResult.EMPTY; + } + [$getChildren](name = null) { + if (!name) { + return this[_children]; + } + return this[_children].filter((c) => c[$nodeName] === name); + } + [$getAttributes]() { + return this[_attributes]; + } + [$getChildrenByClass](name) { + const value = this[_attributes].get(name); + if (value !== void 0) { + return value; + } + return this[$getChildren](name); + } + *[$getChildrenByNameIt](name, allTransparent) { + const value = this[_attributes].get(name); + if (value) { + yield value; + } + for (const child of this[_children]) { + if (child[$nodeName] === name) { + yield child; + } + if (allTransparent) { + yield* child[$getChildrenByNameIt](name, allTransparent); + } + } + } + *[$getAttributeIt](name, skipConsumed) { + const value = this[_attributes].get(name); + if (value && (!skipConsumed || !value[$consumed])) { + yield value; + } + for (const child of this[_children]) { + yield* child[$getAttributeIt](name, skipConsumed); + } + } + *[$getRealChildrenByNameIt](name, allTransparent, skipConsumed) { + for (const child of this[_children]) { + if (child[$nodeName] === name && (!skipConsumed || !child[$consumed])) { + yield child; + } + if (allTransparent) { + yield* child[$getRealChildrenByNameIt](name, allTransparent, skipConsumed); + } + } + } + [$isDataValue]() { + if (this[_dataValue] === null) { + return this[_children].length === 0 || this[_children][0][$namespaceId] === NamespaceIds.xhtml.id; + } + return this[_dataValue]; + } + [$getDataValue]() { + if (this[_dataValue] === null) { + if (this[_children].length === 0) { + return this[$content].trim(); + } + if (this[_children][0][$namespaceId] === NamespaceIds.xhtml.id) { + return this[_children][0][$text]().trim(); + } + return null; + } + return this[$content].trim(); + } + [$setValue](value) { + value = value.value || ""; + this[$content] = value.toString(); + } + [$dump](hasNS = false) { + const dumped = /* @__PURE__ */ Object.create(null); + if (hasNS) { + dumped.$ns = this[$namespaceId]; + } + if (this[$content]) { + dumped.$content = this[$content]; + } + dumped.$name = this[$nodeName]; + dumped.children = []; + for (const child of this[_children]) { + dumped.children.push(child[$dump](hasNS)); + } + dumped.attributes = /* @__PURE__ */ Object.create(null); + for (const [name, value] of this[_attributes]) { + dumped.attributes[name] = value[$content]; + } + return dumped; + } + }; + ContentObject = class extends XFAObject { + constructor(nsId, name) { + super(nsId, name); + this[$content] = ""; + } + [$onText](text2) { + this[$content] += text2; + } + [$finalize]() { + } + }; + OptionObject = class extends ContentObject { + constructor(nsId, name, options) { + super(nsId, name); + this[_options] = options; + } + [$finalize]() { + this[$content] = getKeyword({ + data: this[$content], + defaultValue: this[_options][0], + validate: (k) => this[_options].includes(k) + }); + } + [$clean](builder) { + super[$clean](builder); + delete this[_options]; + } + }; + StringObject = class extends ContentObject { + [$finalize]() { + this[$content] = this[$content].trim(); + } + }; + IntegerObject = class extends ContentObject { + constructor(nsId, name, defaultValue, validator) { + super(nsId, name); + this[_defaultValue] = defaultValue; + this[_validator] = validator; + } + [$finalize]() { + this[$content] = getInteger({ + data: this[$content], + defaultValue: this[_defaultValue], + validate: this[_validator] + }); + } + [$clean](builder) { + super[$clean](builder); + delete this[_defaultValue]; + delete this[_validator]; + } + }; + Option01 = class extends IntegerObject { + constructor(nsId, name) { + super(nsId, name, 0, (n) => n === 1); + } + }; + Option10 = class extends IntegerObject { + constructor(nsId, name) { + super(nsId, name, 1, (n) => n === 0); + } + }; + converters = { + anchorType(node2, style) { + const parent = node2[$getSubformParent](); + if (!parent || parent.layout && parent.layout !== "position") { + return; + } + if (!("transform" in style)) { + style.transform = ""; + } + switch (node2.anchorType) { + case "bottomCenter": + style.transform += "translate(-50%, -100%)"; + break; + case "bottomLeft": + style.transform += "translate(0,-100%)"; + break; + case "bottomRight": + style.transform += "translate(-100%,-100%)"; + break; + case "middleCenter": + style.transform += "translate(-50%,-50%)"; + break; + case "middleLeft": + style.transform += "translate(0,-50%)"; + break; + case "middleRight": + style.transform += "translate(-100%,-50%)"; + break; + case "topCenter": + style.transform += "translate(-50%,0)"; + break; + case "topRight": + style.transform += "translate(-100%,0)"; + break; + } + }, + dimensions(node2, style) { + const parent = node2[$getSubformParent](); + let width = node2.w; + const height = node2.h; + if (parent.layout?.includes("row")) { + const extra = parent[$extra]; + const colSpan = node2.colSpan; + let w; + if (colSpan === -1) { + w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn)); + extra.currentColumn = 0; + } else { + w = Math.sumPrecise(extra.columnWidths.slice(extra.currentColumn, extra.currentColumn + colSpan)); + extra.currentColumn = (extra.currentColumn + node2.colSpan) % extra.columnWidths.length; + } + if (!isNaN(w)) { + width = node2.w = w; + } + } + style.width = width !== "" ? measureToString(width) : "auto"; + style.height = height !== "" ? measureToString(height) : "auto"; + }, + position(node2, style) { + const parent = node2[$getSubformParent](); + if (parent?.layout && parent.layout !== "position") { + return; + } + style.position = "absolute"; + style.left = measureToString(node2.x); + style.top = measureToString(node2.y); + }, + rotate(node2, style) { + if (node2.rotate) { + if (!("transform" in style)) { + style.transform = ""; + } + style.transform += `rotate(-${node2.rotate}deg)`; + style.transformOrigin = "top left"; + } + }, + presence(node2, style) { + switch (node2.presence) { + case "invisible": + style.visibility = "hidden"; + break; + case "hidden": + case "inactive": + style.display = "none"; + break; + } + }, + hAlign(node2, style) { + if (node2[$nodeName] === "para") { + switch (node2.hAlign) { + case "justifyAll": + style.textAlign = "justify-all"; + break; + case "radix": + style.textAlign = "left"; + break; + default: + style.textAlign = node2.hAlign; + } + } else { + switch (node2.hAlign) { + case "left": + style.alignSelf = "start"; + break; + case "center": + style.alignSelf = "center"; + break; + case "right": + style.alignSelf = "end"; + break; + } + } + }, + margin(node2, style) { + if (node2.margin) { + style.margin = node2.margin[$toStyle]().margin; + } + } + }; + TEMPLATE_NS_ID = NamespaceIds.template.id; + SVG_NS2 = "http://www.w3.org/2000/svg"; + MAX_ATTEMPTS_FOR_LRTB_LAYOUT = 2; + MAX_EMPTY_PAGES = 3; + DEFAULT_TAB_INDEX = 5e3; + HEADING_PATTERN = /^H(\d+)$/; + MIMES = /* @__PURE__ */ new Set(["image/gif", "image/jpeg", "image/jpg", "image/pjpeg", "image/png", "image/apng", "image/x-png", "image/bmp", "image/x-ms-bmp", "image/tiff", "image/tif", "application/octet-stream"]); + IMAGES_HEADERS = [[[66, 77], "image/bmp"], [[255, 216, 255], "image/jpeg"], [[73, 73, 42, 0], "image/tiff"], [[77, 77, 0, 42], "image/tiff"], [[71, 73, 70, 56, 57, 97], "image/gif"], [[137, 80, 78, 71, 13, 10, 26, 10], "image/png"]]; + AppearanceFilter = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "appearanceFilter"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Arc = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "arc", true); + this.circular = getInteger({ + data: attributes.circular, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.startAngle = getFloat({ + data: attributes.startAngle, + defaultValue: 0, + validate: (x) => true + }); + this.sweepAngle = getFloat({ + data: attributes.sweepAngle, + defaultValue: 360, + validate: (x) => true + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.edge = null; + this.fill = null; + } + [$toHTML]() { + const edge = this.edge || new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = /* @__PURE__ */ Object.create(null); + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } else { + style.fill = "transparent"; + } + style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); + style.stroke = edgeStyle.color; + let arc; + const attributes = { + xmlns: SVG_NS2, + style: { + width: "100%", + height: "100%", + overflow: "visible" + } + }; + if (this.sweepAngle === 360) { + arc = { + name: "ellipse", + attributes: { + xmlns: SVG_NS2, + cx: "50%", + cy: "50%", + rx: "50%", + ry: "50%", + style + } + }; + } else { + const startAngle = this.startAngle * Math.PI / 180; + const sweepAngle = this.sweepAngle * Math.PI / 180; + const largeArc = this.sweepAngle > 180 ? 1 : 0; + const [x1, y1, x2, y2] = [50 * (1 + Math.cos(startAngle)), 50 * (1 - Math.sin(startAngle)), 50 * (1 + Math.cos(startAngle + sweepAngle)), 50 * (1 - Math.sin(startAngle + sweepAngle))]; + arc = { + name: "path", + attributes: { + xmlns: SVG_NS2, + d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`, + vectorEffect: "non-scaling-stroke", + style + } + }; + Object.assign(attributes, { + viewBox: "0 0 100 100", + preserveAspectRatio: "none" + }); + } + const svg = { + name: "svg", + children: [arc], + attributes + }; + const parent = this[$getParent]()[$getParent](); + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } + }; + Area = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "area", true); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: (n) => n >= 1 || n === -1 + }); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.desc = null; + this.extras = null; + this.area = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$isTransparent]() { + return true; + } + [$isBindable]() { + return true; + } + [$addHTML](html, bbox) { + const [x, y, w, h] = bbox; + this[$extra].width = Math.max(this[$extra].width, x + w); + this[$extra].height = Math.max(this[$extra].height, y + h); + this[$extra].children.push(html); + } + [$getAvailableSpace]() { + return this[$extra].availableSpace; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "position"); + const attributes = { + style, + id: this[$uid], + class: ["xfaArea"] + }; + if (isPrintOnly(this)) { + attributes.class.push("xfaPrintOnly"); + } + if (this.name) { + attributes.xfaName = this.name; + } + const children = []; + this[$extra] = { + children, + width: 0, + height: 0, + availableSpace + }; + const result2 = this[$childrenToHTML]({ + filter: /* @__PURE__ */ new Set(["area", "draw", "field", "exclGroup", "subform", "subformSet"]), + include: true + }); + if (!result2.success) { + if (result2.isBreak()) { + return result2; + } + delete this[$extra]; + return HTMLResult.FAILURE; + } + style.width = measureToString(this[$extra].width); + style.height = measureToString(this[$extra].height); + const html = { + name: "div", + attributes, + children + }; + const bbox = [this.x, this.y, this[$extra].width, this[$extra].height]; + delete this[$extra]; + return HTMLResult.success(html, bbox); + } + }; + Assist = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "assist", true); + this.id = attributes.id || ""; + this.role = attributes.role || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.speak = null; + this.toolTip = null; + } + [$toHTML]() { + return this.toolTip?.[$content] || null; + } + }; + Barcode = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "barcode", true); + this.charEncoding = getKeyword({ + data: attributes.charEncoding ? attributes.charEncoding.toLowerCase() : "", + defaultValue: "", + validate: (k) => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) + }); + this.checksum = getStringOption(attributes.checksum, ["none", "1mod10", "1mod10_1mod11", "2mod10", "auto"]); + this.dataColumnCount = getInteger({ + data: attributes.dataColumnCount, + defaultValue: -1, + validate: (x) => x >= 0 + }); + this.dataLength = getInteger({ + data: attributes.dataLength, + defaultValue: -1, + validate: (x) => x >= 0 + }); + this.dataPrep = getStringOption(attributes.dataPrep, ["none", "flateCompress"]); + this.dataRowCount = getInteger({ + data: attributes.dataRowCount, + defaultValue: -1, + validate: (x) => x >= 0 + }); + this.endChar = attributes.endChar || ""; + this.errorCorrectionLevel = getInteger({ + data: attributes.errorCorrectionLevel, + defaultValue: -1, + validate: (x) => x >= 0 && x <= 8 + }); + this.id = attributes.id || ""; + this.moduleHeight = getMeasurement(attributes.moduleHeight, "5mm"); + this.moduleWidth = getMeasurement(attributes.moduleWidth, "0.25mm"); + this.printCheckDigit = getInteger({ + data: attributes.printCheckDigit, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.rowColumnRatio = getRatio(attributes.rowColumnRatio); + this.startChar = attributes.startChar || ""; + this.textLocation = getStringOption(attributes.textLocation, ["below", "above", "aboveEmbedded", "belowEmbedded", "none"]); + this.truncate = getInteger({ + data: attributes.truncate, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.type = getStringOption(attributes.type ? attributes.type.toLowerCase() : "", ["aztec", "codabar", "code2of5industrial", "code2of5interleaved", "code2of5matrix", "code2of5standard", "code3of9", "code3of9extended", "code11", "code49", "code93", "code128", "code128a", "code128b", "code128c", "code128sscc", "datamatrix", "ean8", "ean8add2", "ean8add5", "ean13", "ean13add2", "ean13add5", "ean13pwcd", "fim", "logmars", "maxicode", "msi", "pdf417", "pdf417macro", "plessey", "postauscust2", "postauscust3", "postausreplypaid", "postausstandard", "postukrm4scc", "postusdpbc", "postusimb", "postusstandard", "postus5zip", "qrcode", "rfid", "rss14", "rss14expanded", "rss14limited", "rss14stacked", "rss14stackedomni", "rss14truncated", "telepen", "ucc128", "ucc128random", "ucc128sscc", "upca", "upcaadd2", "upcaadd5", "upcapwcd", "upce", "upceadd2", "upceadd5", "upcean2", "upcean5", "upsmaxicode"]); + this.upsMode = getStringOption(attributes.upsMode, ["usCarrier", "internationalCarrier", "secureSymbol", "standardSymbol"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.wideNarrowRatio = getRatio(attributes.wideNarrowRatio); + this.encrypt = null; + this.extras = null; + } + }; + Bind = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bind", true); + this.match = getStringOption(attributes.match, ["once", "dataRef", "global", "none"]); + this.ref = attributes.ref || ""; + this.picture = null; + } + }; + BindItems = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bindItems"); + this.connection = attributes.connection || ""; + this.labelRef = attributes.labelRef || ""; + this.ref = attributes.ref || ""; + this.valueRef = attributes.valueRef || ""; + } + }; + Bookend = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "bookend"); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + BooleanElement = class extends Option01 { + constructor(attributes) { + super(TEMPLATE_NS_ID, "boolean"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] === 1 ? "1" : "0"); + } + }; + Border = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "border", true); + this.break = getStringOption(attributes.break, ["close", "open"]); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.corner = new XFAObjectArray(4); + this.edge = new XFAObjectArray(4); + this.extras = null; + this.fill = null; + this.margin = null; + } + [$getExtra]() { + if (!this[$extra]) { + const edges = this.edge.children.slice(); + if (edges.length < 4) { + const defaultEdge = edges.at(-1) || new Edge({}); + for (let i = edges.length; i < 4; i++) { + edges.push(defaultEdge); + } + } + const widths = edges.map((edge) => edge.thickness); + const insets = [0, 0, 0, 0]; + if (this.margin) { + insets[0] = this.margin.topInset; + insets[1] = this.margin.rightInset; + insets[2] = this.margin.bottomInset; + insets[3] = this.margin.leftInset; + } + this[$extra] = { + widths, + insets, + edges + }; + } + return this[$extra]; + } + [$toStyle]() { + const { + edges + } = this[$getExtra](); + const edgeStyles = edges.map((node2) => { + const style2 = node2[$toStyle](); + style2.color ||= "#000000"; + return style2; + }); + const style = /* @__PURE__ */ Object.create(null); + if (this.margin) { + Object.assign(style, this.margin[$toStyle]()); + } + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } + if (this.corner.children.some((node2) => node2.radius !== 0)) { + const cornerStyles = this.corner.children.map((node2) => node2[$toStyle]()); + if (cornerStyles.length === 2 || cornerStyles.length === 3) { + const last2 = cornerStyles.at(-1); + for (let i = cornerStyles.length; i < 4; i++) { + cornerStyles.push(last2); + } + } + style.borderRadius = cornerStyles.map((s) => s.radius).join(" "); + } + switch (this.presence) { + case "invisible": + case "hidden": + style.borderStyle = ""; + break; + case "inactive": + style.borderStyle = "none"; + break; + default: + style.borderStyle = edgeStyles.map((s) => s.style).join(" "); + break; + } + style.borderWidth = edgeStyles.map((s) => s.width).join(" "); + style.borderColor = edgeStyles.map((s) => s.color).join(" "); + return style; + } + }; + Break = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "break", true); + this.after = getStringOption(attributes.after, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); + this.afterTarget = attributes.afterTarget || ""; + this.before = getStringOption(attributes.before, ["auto", "contentArea", "pageArea", "pageEven", "pageOdd"]); + this.beforeTarget = attributes.beforeTarget || ""; + this.bookendLeader = attributes.bookendLeader || ""; + this.bookendTrailer = attributes.bookendTrailer || ""; + this.id = attributes.id || ""; + this.overflowLeader = attributes.overflowLeader || ""; + this.overflowTarget = attributes.overflowTarget || ""; + this.overflowTrailer = attributes.overflowTrailer || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + }; + BreakAfter = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "breakAfter", true); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.target = attributes.target || ""; + this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.script = null; + } + }; + BreakBefore = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "breakBefore", true); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.startNew = getInteger({ + data: attributes.startNew, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.target = attributes.target || ""; + this.targetType = getStringOption(attributes.targetType, ["auto", "contentArea", "pageArea"]); + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.script = null; + } + [$toHTML](availableSpace) { + this[$extra] = {}; + return HTMLResult.FAILURE; + } + }; + Button = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "button", true); + this.highlight = getStringOption(attributes.highlight, ["inverted", "none", "outline", "push"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toHTML](availableSpace) { + const parent = this[$getParent](); + const grandpa = parent[$getParent](); + const htmlButton = { + name: "button", + attributes: { + id: this[$uid], + class: ["xfaButton"], + style: {} + }, + children: [] + }; + for (const event of grandpa.event.children) { + if (event.activity !== "click" || !event.script) { + continue; + } + const jsURL = recoverJsURL(event.script[$content]); + if (!jsURL) { + continue; + } + const href = fixURL(jsURL.url); + if (!href) { + continue; + } + htmlButton.children.push({ + name: "a", + attributes: { + id: "link" + this[$uid], + href, + newWindow: jsURL.newWindow, + class: ["xfaLink"], + style: {} + }, + children: [] + }); + } + return HTMLResult.success(htmlButton); + } + }; + Calculate = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "calculate", true); + this.id = attributes.id || ""; + this.override = getStringOption(attributes.override, ["disabled", "error", "ignore", "warning"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.message = null; + this.script = null; + } + }; + Caption = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "caption", true); + this.id = attributes.id || ""; + this.placement = getStringOption(attributes.placement, ["left", "bottom", "inline", "right", "top"]); + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.reserve = Math.ceil(getMeasurement(attributes.reserve)); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.font = null; + this.margin = null; + this.para = null; + this.value = null; + } + [$setValue](value) { + _setValue(this, value); + } + [$getExtra](availableSpace) { + if (!this[$extra]) { + let { + width, + height + } = availableSpace; + switch (this.placement) { + case "left": + case "right": + case "inline": + width = this.reserve <= 0 ? width : this.reserve; + break; + case "top": + case "bottom": + height = this.reserve <= 0 ? height : this.reserve; + break; + } + this[$extra] = layoutNode(this, { + width, + height + }); + } + return this[$extra]; + } + [$toHTML](availableSpace) { + if (!this.value) { + return HTMLResult.EMPTY; + } + this[$pushPara](); + const value = this.value[$toHTML](availableSpace).html; + if (!value) { + this[$popPara](); + return HTMLResult.EMPTY; + } + const savedReserve = this.reserve; + if (this.reserve <= 0) { + const { + w, + h + } = this[$getExtra](availableSpace); + switch (this.placement) { + case "left": + case "right": + case "inline": + this.reserve = w; + break; + case "top": + case "bottom": + this.reserve = h; + break; + } + } + const children = []; + if (typeof value === "string") { + children.push({ + name: "#text", + value + }); + } else { + children.push(value); + } + const style = toStyle(this, "font", "margin", "visibility"); + switch (this.placement) { + case "left": + case "right": + if (this.reserve > 0) { + style.width = measureToString(this.reserve); + } + break; + case "top": + case "bottom": + if (this.reserve > 0) { + style.height = measureToString(this.reserve); + } + break; + } + setPara(this, null, value); + this[$popPara](); + this.reserve = savedReserve; + return HTMLResult.success({ + name: "div", + attributes: { + style, + class: ["xfaCaption"] + }, + children + }); + } + }; + Certificate = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "certificate"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Certificates = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "certificates", true); + this.credentialServerPolicy = getStringOption(attributes.credentialServerPolicy, ["optional", "required"]); + this.id = attributes.id || ""; + this.url = attributes.url || ""; + this.urlPolicy = attributes.urlPolicy || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encryption = null; + this.issuers = null; + this.keyUsage = null; + this.oids = null; + this.signing = null; + this.subjectDNs = null; + } + }; + CheckButton = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "checkButton", true); + this.id = attributes.id || ""; + this.mark = getStringOption(attributes.mark, ["default", "check", "circle", "cross", "diamond", "square", "star"]); + this.shape = getStringOption(attributes.shape, ["square", "round"]); + this.size = getMeasurement(attributes.size, "10pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "margin"); + const size3 = measureToString(this.size); + style.width = style.height = size3; + let type; + let className; + let groupId; + const field = this[$getParent]()[$getParent](); + const items = field.items.children.length && field.items.children[0][$toHTML]().html || []; + const exportedValue = { + on: (items[0] !== void 0 ? items[0] : "on").toString(), + off: (items[1] !== void 0 ? items[1] : "off").toString() + }; + const value = field.value?.[$text]() || "off"; + const checked = value === exportedValue.on || void 0; + const container = field[$getSubformParent](); + const fieldId = field[$uid]; + let dataId; + if (container instanceof ExclGroup) { + groupId = container[$uid]; + type = "radio"; + className = "xfaRadio"; + dataId = container[$data]?.[$uid] || container[$uid]; + } else { + type = "checkbox"; + className = "xfaCheckbox"; + dataId = field[$data]?.[$uid] || field[$uid]; + } + const input2 = { + name: "input", + attributes: { + class: [className], + style, + fieldId, + dataId, + type, + checked, + xfaOn: exportedValue.on, + xfaOff: exportedValue.off, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (groupId) { + input2.attributes.name = groupId; + } + if (isRequired(field)) { + input2.attributes["aria-required"] = true; + input2.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [input2] + }); + } + }; + ChoiceList = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "choiceList", true); + this.commitOn = getStringOption(attributes.commitOn, ["select", "exit"]); + this.id = attributes.id || ""; + this.open = getStringOption(attributes.open, ["userControl", "always", "multiSelect", "onEntry"]); + this.textEntry = getInteger({ + data: attributes.textEntry, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "margin"); + const ui = this[$getParent](); + const field = ui[$getParent](); + const fontSize = field.font?.size || 10; + const optionStyle = { + fontSize: `calc(${fontSize}px * var(--total-scale-factor))` + }; + const children = []; + if (field.items.children.length > 0) { + const items = field.items; + let displayedIndex = 0; + let saveIndex = 0; + if (items.children.length === 2) { + displayedIndex = items.children[0].save; + saveIndex = 1 - displayedIndex; + } + const displayed = items.children[displayedIndex][$toHTML]().html; + const values3 = items.children[saveIndex][$toHTML]().html; + let selected = false; + const value = field.value?.[$text]() || ""; + for (let i = 0, ii = displayed.length; i < ii; i++) { + const option = { + name: "option", + attributes: { + value: values3[i] || displayed[i], + style: optionStyle + }, + value: displayed[i] + }; + if (values3[i] === value) { + option.attributes.selected = selected = true; + } + children.push(option); + } + if (!selected) { + children.splice(0, 0, { + name: "option", + attributes: { + hidden: true, + selected: true + }, + value: " " + }); + } + } + const selectAttributes = { + class: ["xfaSelect"], + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + style, + "aria-label": ariaLabel(field), + "aria-required": false + }; + if (isRequired(field)) { + selectAttributes["aria-required"] = true; + selectAttributes.required = true; + } + if (this.open === "multiSelect") { + selectAttributes.multiple = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [{ + name: "select", + children, + attributes: selectAttributes + }] + }); + } + }; + Color = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "color", true); + this.cSpace = getStringOption(attributes.cSpace, ["SRGB"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.value = attributes.value ? getColor(attributes.value) : ""; + this.extras = null; + } + [$hasSettableValue]() { + return false; + } + [$toStyle]() { + return this.value ? Util2.makeHexColor(this.value.r, this.value.g, this.value.b) : null; + } + }; + Comb = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "comb"); + this.id = attributes.id || ""; + this.numberOfCells = getInteger({ + data: attributes.numberOfCells, + defaultValue: 0, + validate: (x) => x >= 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Connect = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "connect", true); + this.connection = attributes.connection || ""; + this.id = attributes.id || ""; + this.ref = attributes.ref || ""; + this.usage = getStringOption(attributes.usage, ["exportAndImport", "exportOnly", "importOnly"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.picture = null; + } + }; + ContentArea = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "contentArea", true); + this.h = getMeasurement(attributes.h); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = getMeasurement(attributes.w); + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.desc = null; + this.extras = null; + } + [$toHTML](availableSpace) { + const left = measureToString(this.x); + const top = measureToString(this.y); + const style = { + left, + top, + width: measureToString(this.w), + height: measureToString(this.h) + }; + const classNames = ["xfaContentarea"]; + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + return HTMLResult.success({ + name: "div", + children: [], + attributes: { + style, + class: classNames, + id: this[$uid] + } + }); + } + }; + Corner = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "corner", true); + this.id = attributes.id || ""; + this.inverted = getInteger({ + data: attributes.inverted, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.join = getStringOption(attributes.join, ["square", "round"]); + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.radius = getMeasurement(attributes.radius); + this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); + this.thickness = getMeasurement(attributes.thickness, "0.5pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle]() { + const style = toStyle(this, "visibility"); + style.radius = measureToString(this.join === "square" ? 0 : this.radius); + return style; + } + }; + DateElement = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "date"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date6 = this[$content].trim(); + this[$content] = date6 ? new Date(date6) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } + }; + DateTime = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "dateTime"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date6 = this[$content].trim(); + this[$content] = date6 ? new Date(date6) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } + }; + DateTimeEdit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "dateTimeEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.picker = getStringOption(attributes.picker, ["host", "none"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + const field = this[$getParent]()[$getParent](); + const html = { + name: "input", + attributes: { + type: "text", + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } + }; + Decimal = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "decimal"); + this.fracDigits = getInteger({ + data: attributes.fracDigits, + defaultValue: 2, + validate: (x) => true + }); + this.id = attributes.id || ""; + this.leadDigits = getInteger({ + data: attributes.leadDigits, + defaultValue: -1, + validate: (x) => true + }); + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number4 = parseFloat(this[$content].trim()); + this[$content] = isNaN(number4) ? null : number4; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } + }; + DefaultUi = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "defaultUi", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + }; + Desc = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "desc", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + }; + DigestMethod = class extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "digestMethod", ["", "SHA1", "SHA256", "SHA512", "RIPEMD160"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + DigestMethods = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "digestMethods", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.digestMethod = new XFAObjectArray(); + } + }; + Draw = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "draw", true); + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: (n) => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.rotate = getInteger({ + data: attributes.rotate, + defaultValue: 0, + validate: (x) => x % 90 === 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.border = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.font = null; + this.keep = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.ui = null; + this.value = null; + this.setProperty = new XFAObjectArray(); + } + [$setValue](value) { + _setValue(this, value); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.presence === "hidden" || this.presence === "inactive") { + return HTMLResult.EMPTY; + } + fixDimensions(this); + this[$pushPara](); + const savedW = this.w; + const savedH = this.h; + const { + w, + h, + isBroken + } = layoutNode(this, availableSpace); + if (w && this.w === "") { + if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { + this[$popPara](); + return HTMLResult.FAILURE; + } + this.w = w; + } + if (h && this.h === "") { + this.h = h; + } + setFirstUnsplittable(this); + if (!checkDimensions(this, availableSpace)) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.FAILURE; + } + unsetFirstUnsplittable(this); + const style = toStyle(this, "font", "hAlign", "dimensions", "position", "presence", "rotate", "anchorType", "border", "margin"); + setMinMaxDimensions(this, style); + if (style.margin) { + style.padding = style.margin; + delete style.margin; + } + const classNames = ["xfaDraw"]; + if (this.font) { + classNames.push("xfaFont"); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + const attributes = { + style, + id: this[$uid], + class: classNames + }; + if (this.name) { + attributes.xfaName = this.name; + } + const html = { + name: "div", + attributes, + children: [] + }; + applyAssist(this, attributes); + const bbox = computeBbox(this, html, availableSpace); + const value = this.value ? this.value[$toHTML](availableSpace).html : null; + if (value === null) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.success(createWrapper(this, html), bbox); + } + html.children.push(value); + setPara(this, style, value); + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.success(createWrapper(this, html), bbox); + } + }; + Edge = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "edge", true); + this.cap = getStringOption(attributes.cap, ["square", "butt", "round"]); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.stroke = getStringOption(attributes.stroke, ["solid", "dashDot", "dashDotDot", "dashed", "dotted", "embossed", "etched", "lowered", "raised"]); + this.thickness = getMeasurement(attributes.thickness, "0.5pt"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle]() { + const style = toStyle(this, "visibility"); + Object.assign(style, { + linecap: this.cap, + width: measureToString(this.thickness), + color: this.color ? this.color[$toStyle]() : "#000000", + style: "" + }); + if (this.presence !== "visible") { + style.style = "none"; + } else { + switch (this.stroke) { + case "solid": + style.style = "solid"; + break; + case "dashDot": + style.style = "dashed"; + break; + case "dashDotDot": + style.style = "dashed"; + break; + case "dashed": + style.style = "dashed"; + break; + case "dotted": + style.style = "dotted"; + break; + case "embossed": + style.style = "ridge"; + break; + case "etched": + style.style = "groove"; + break; + case "lowered": + style.style = "inset"; + break; + case "raised": + style.style = "outset"; + break; + } + } + return style; + } + }; + Encoding = class extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encoding", ["adbe.x509.rsa_sha1", "adbe.pkcs7.detached", "adbe.pkcs7.sha1"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Encodings = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encodings", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encoding = new XFAObjectArray(); + } + }; + Encrypt = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encrypt", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = null; + } + }; + EncryptData = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptData", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["encrypt", "decrypt"]); + this.target = attributes.target || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.filter = null; + this.manifest = null; + } + }; + Encryption = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryption", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } + }; + EncryptionMethod = class extends OptionObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptionMethod", ["", "AES256-CBC", "TRIPLEDES-CBC", "AES128-CBC", "AES192-CBC"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + EncryptionMethods = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "encryptionMethods", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.encryptionMethod = new XFAObjectArray(); + } + }; + Event2 = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "event", true); + this.activity = getStringOption(attributes.activity, ["click", "change", "docClose", "docReady", "enter", "exit", "full", "indexChange", "initialize", "mouseDown", "mouseEnter", "mouseExit", "mouseUp", "postExecute", "postOpen", "postPrint", "postSave", "postSign", "postSubmit", "preExecute", "preOpen", "prePrint", "preSave", "preSign", "preSubmit", "ready", "validationState"]); + this.id = attributes.id || ""; + this.listen = getStringOption(attributes.listen, ["refOnly", "refAndDescendents"]); + this.name = attributes.name || ""; + this.ref = attributes.ref || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.encryptData = null; + this.execute = null; + this.script = null; + this.signData = null; + this.submit = null; + } + }; + ExData = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exData"); + this.contentType = attributes.contentType || ""; + this.href = attributes.href || ""; + this.id = attributes.id || ""; + this.maxLength = getInteger({ + data: attributes.maxLength, + defaultValue: -1, + validate: (x) => x >= -1 + }); + this.name = attributes.name || ""; + this.rid = attributes.rid || ""; + this.transferEncoding = getStringOption(attributes.transferEncoding, ["none", "base64", "package"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$isCDATAXml]() { + return this.contentType === "text/html"; + } + [$onChild](child) { + if (this.contentType === "text/html" && child[$namespaceId] === NamespaceIds.xhtml.id) { + this[$content] = child; + return true; + } + if (this.contentType === "text/xml") { + this[$content] = child; + return true; + } + return false; + } + [$toHTML](availableSpace) { + if (this.contentType !== "text/html" || !this[$content]) { + return HTMLResult.EMPTY; + } + return this[$content][$toHTML](availableSpace); + } + }; + ExObject = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exObject", true); + this.archive = attributes.archive || ""; + this.classId = attributes.classId || ""; + this.codeBase = attributes.codeBase || ""; + this.codeType = attributes.codeType || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + }; + ExclGroup = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "exclGroup", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.accessKey = attributes.accessKey || ""; + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: (n) => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.border = null; + this.calculate = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.validate = null; + this.connect = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + } + [$isBindable]() { + return true; + } + [$hasSettableValue]() { + return true; + } + [$setValue](value) { + for (const field of this.field.children) { + if (!field.value) { + const nodeValue = new Value({}); + field[$appendChild](nodeValue); + field.value = nodeValue; + } + field.value[$setValue](value); + } + } + [$isThereMoreWidth]() { + return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); + } + [$isSplittable]() { + const parent = this[$getSubformParent](); + if (!parent[$isSplittable]()) { + return false; + } + if (this[$extra]._isSplittable !== void 0) { + return this[$extra]._isSplittable; + } + if (this.layout === "position" || this.layout.includes("row")) { + this[$extra]._isSplittable = false; + return false; + } + if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { + return false; + } + this[$extra]._isSplittable = true; + return true; + } + [$flushHTML]() { + return flushHTML(this); + } + [$addHTML](html, bbox) { + addHTML(this, html, bbox); + } + [$getAvailableSpace]() { + return getAvailableSpace(this); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { + return HTMLResult.EMPTY; + } + fixDimensions(this); + const children = []; + const attributes = { + id: this[$uid], + class: [] + }; + setAccess(this, attributes.class); + this[$extra] ||= /* @__PURE__ */ Object.create(null); + Object.assign(this[$extra], { + children, + attributes, + attempt: 0, + line: null, + numberInLine: 0, + availableSpace: { + width: Math.min(this.w || Infinity, availableSpace.width), + height: Math.min(this.h || Infinity, availableSpace.height) + }, + width: 0, + height: 0, + prevHeight: 0, + currentWidth: 0 + }); + const isSplittable = this[$isSplittable](); + if (!isSplittable) { + setFirstUnsplittable(this); + } + if (!checkDimensions(this, availableSpace)) { + return HTMLResult.FAILURE; + } + const filter2 = /* @__PURE__ */ new Set(["field"]); + if (this.layout.includes("row")) { + const columnWidths = this[$getSubformParent]().columnWidths; + if (Array.isArray(columnWidths) && columnWidths.length > 0) { + this[$extra].columnWidths = columnWidths; + this[$extra].currentColumn = 0; + } + } + const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); + const classNames = ["xfaExclgroup"]; + const cl = layoutClass(this); + if (cl) { + classNames.push(cl); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + attributes.style = style; + attributes.class = classNames; + if (this.name) { + attributes.xfaName = this.name; + } + this[$pushPara](); + const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; + const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; + for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { + if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { + this[$extra].numberInLine = 0; + } + const result2 = this[$childrenToHTML]({ + filter: filter2, + include: true + }); + if (result2.success) { + break; + } + if (result2.isBreak()) { + this[$popPara](); + return result2; + } + if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !this[$getTemplateRoot]()[$extra].noLayoutFailure) { + this[$extra].attempt = maxRun; + break; + } + } + this[$popPara](); + if (!isSplittable) { + unsetFirstUnsplittable(this); + } + if (this[$extra].attempt === maxRun) { + if (!isSplittable) { + delete this[$extra]; + } + return HTMLResult.FAILURE; + } + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + const width = Math.max(this[$extra].width + marginH, this.w || 0); + const height = Math.max(this[$extra].height + marginV, this.h || 0); + const bbox = [this.x, this.y, width, height]; + if (this.w === "") { + style.width = measureToString(width); + } + if (this.h === "") { + style.height = measureToString(height); + } + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + delete this[$extra]; + return HTMLResult.success(createWrapper(this, html), bbox); + } + }; + Execute = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "execute"); + this.connection = attributes.connection || ""; + this.executeType = getStringOption(attributes.executeType, ["import", "remerge"]); + this.id = attributes.id || ""; + this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Extras = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "extras", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.extras = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + }; + Field = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "field", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.accessKey = attributes.accessKey || ""; + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: (n) => n >= 1 || n === -1 + }); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.rotate = getInteger({ + data: attributes.rotate, + defaultValue: 0, + validate: (x) => x % 90 === 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.border = null; + this.calculate = null; + this.caption = null; + this.desc = null; + this.extras = null; + this.font = null; + this.format = null; + this.items = new XFAObjectArray(2); + this.keep = null; + this.margin = null; + this.para = null; + this.traversal = null; + this.ui = null; + this.validate = null; + this.value = null; + this.bindItems = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + } + [$isBindable]() { + return true; + } + [$setValue](value) { + _setValue(this, value); + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (!this.ui) { + this.ui = new Ui({}); + this.ui[$globalData] = this[$globalData]; + this[$appendChild](this.ui); + let node2; + switch (this.items.children.length) { + case 0: + node2 = new TextEdit({}); + this.ui.textEdit = node2; + break; + case 1: + node2 = new CheckButton({}); + this.ui.checkButton = node2; + break; + case 2: + node2 = new ChoiceList({}); + this.ui.choiceList = node2; + break; + } + this.ui[$appendChild](node2); + } + if (!this.ui || this.presence === "hidden" || this.presence === "inactive" || this.h === 0 || this.w === 0) { + return HTMLResult.EMPTY; + } + if (this.caption) { + delete this.caption[$extra]; + } + this[$pushPara](); + const caption = this.caption ? this.caption[$toHTML](availableSpace).html : null; + const savedW = this.w; + const savedH = this.h; + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + let borderDims = null; + if (this.w === "" || this.h === "") { + let width = null; + let height = null; + let uiW = 0; + let uiH = 0; + if (this.ui.checkButton) { + uiW = uiH = this.ui.checkButton.size; + } else { + const { + w, + h + } = layoutNode(this, availableSpace); + if (w !== null) { + uiW = w; + uiH = h; + } else { + uiH = fonts_getMetrics(this.font, true).lineNoGap; + } + } + borderDims = getBorderDims(this.ui[$getExtra]()); + uiW += borderDims.w; + uiH += borderDims.h; + if (this.caption) { + const { + w, + h, + isBroken + } = this.caption[$getExtra](availableSpace); + if (isBroken && this[$getSubformParent]()[$isThereMoreWidth]()) { + this[$popPara](); + return HTMLResult.FAILURE; + } + width = w; + height = h; + switch (this.caption.placement) { + case "left": + case "right": + case "inline": + width += uiW; + break; + case "top": + case "bottom": + height += uiH; + break; + } + } else { + width = uiW; + height = uiH; + } + if (width && this.w === "") { + width += marginH; + this.w = Math.min(this.maxW <= 0 ? Infinity : this.maxW, this.minW + 1 < width ? width : this.minW); + } + if (height && this.h === "") { + height += marginV; + this.h = Math.min(this.maxH <= 0 ? Infinity : this.maxH, this.minH + 1 < height ? height : this.minH); + } + } + this[$popPara](); + fixDimensions(this); + setFirstUnsplittable(this); + if (!checkDimensions(this, availableSpace)) { + this.w = savedW; + this.h = savedH; + this[$popPara](); + return HTMLResult.FAILURE; + } + unsetFirstUnsplittable(this); + const style = toStyle(this, "font", "dimensions", "position", "rotate", "anchorType", "presence", "margin", "hAlign"); + setMinMaxDimensions(this, style); + const classNames = ["xfaField"]; + if (this.font) { + classNames.push("xfaFont"); + } + if (isPrintOnly(this)) { + classNames.push("xfaPrintOnly"); + } + const attributes = { + style, + id: this[$uid], + class: classNames + }; + if (style.margin) { + style.padding = style.margin; + delete style.margin; + } + setAccess(this, classNames); + if (this.name) { + attributes.xfaName = this.name; + } + const children = []; + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + const borderStyle = this.border ? this.border[$toStyle]() : null; + const bbox = computeBbox(this, html, availableSpace); + const ui = this.ui[$toHTML]().html; + if (!ui) { + Object.assign(style, borderStyle); + return HTMLResult.success(createWrapper(this, html), bbox); + } + if (this[$tabIndex]) { + if (ui.children?.[0]) { + ui.children[0].attributes.tabindex = this[$tabIndex]; + } else { + ui.attributes.tabindex = this[$tabIndex]; + } + } + ui.attributes.style ||= /* @__PURE__ */ Object.create(null); + let aElement = null; + if (this.ui.button) { + if (ui.children.length === 1) { + [aElement] = ui.children.splice(0, 1); + } + Object.assign(ui.attributes.style, borderStyle); + } else { + Object.assign(style, borderStyle); + } + children.push(ui); + if (this.value) { + if (this.ui.imageEdit) { + ui.children.push(this.value[$toHTML]().html); + } else if (!this.ui.button) { + let value = ""; + if (this.value.exData) { + value = this.value.exData[$text](); + } else if (this.value.text) { + value = this.value.text[$getExtra](); + } else { + const htmlValue = this.value[$toHTML]().html; + if (htmlValue !== null) { + value = htmlValue.children[0].value; + } + } + if (this.ui.textEdit && this.value.text?.maxChars) { + ui.children[0].attributes.maxLength = this.value.text.maxChars; + } + if (value) { + if (this.ui.numericEdit) { + value = parseFloat(value); + value = isNaN(value) ? "" : value.toString(); + } + if (ui.children[0].name === "textarea") { + ui.children[0].attributes.textContent = value; + } else { + ui.children[0].attributes.value = value; + } + } + } + } + if (!this.ui.imageEdit && ui.children?.[0] && this.h) { + borderDims = borderDims || getBorderDims(this.ui[$getExtra]()); + let captionHeight = 0; + if (this.caption && ["top", "bottom"].includes(this.caption.placement)) { + captionHeight = this.caption.reserve; + if (captionHeight <= 0) { + captionHeight = this.caption[$getExtra](availableSpace).h; + } + const inputHeight = this.h - captionHeight - marginV - borderDims.h; + ui.children[0].attributes.style.height = measureToString(inputHeight); + } else { + ui.children[0].attributes.style.height = "100%"; + } + } + if (aElement) { + ui.children.push(aElement); + } + if (!caption) { + if (ui.attributes.class) { + ui.attributes.class.push("xfaLeft"); + } + this.w = savedW; + this.h = savedH; + return HTMLResult.success(createWrapper(this, html), bbox); + } + if (this.ui.button) { + if (style.padding) { + delete style.padding; + } + if (caption.name === "div") { + caption.name = "span"; + } + ui.children.push(caption); + return HTMLResult.success(html, bbox); + } else if (this.ui.checkButton) { + caption.attributes.class[0] = "xfaCaptionForCheckButton"; + } + ui.attributes.class ||= []; + ui.children.splice(0, 0, caption); + switch (this.caption.placement) { + case "left": + ui.attributes.class.push("xfaLeft"); + break; + case "right": + ui.attributes.class.push("xfaRight"); + break; + case "top": + ui.attributes.class.push("xfaTop"); + break; + case "bottom": + ui.attributes.class.push("xfaBottom"); + break; + case "inline": + ui.attributes.class.push("xfaLeft"); + break; + } + this.w = savedW; + this.h = savedH; + return HTMLResult.success(createWrapper(this, html), bbox); + } + }; + Fill = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "fill", true); + this.id = attributes.id || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + this.linear = null; + this.pattern = null; + this.radial = null; + this.solid = null; + this.stipple = null; + } + [$toStyle]() { + const parent = this[$getParent](); + const grandpa = parent[$getParent](); + const ggrandpa = grandpa[$getParent](); + const style = /* @__PURE__ */ Object.create(null); + let propName = "color"; + let altPropName = propName; + if (parent instanceof Border) { + propName = "background-color"; + altPropName = "background"; + if (ggrandpa instanceof Ui) { + style.backgroundColor = "white"; + } + } + if (parent instanceof Rectangle2 || parent instanceof Arc) { + propName = altPropName = "fill"; + style.fill = "white"; + } + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "extras" || name === "color") { + continue; + } + const obj2 = this[name]; + if (!(obj2 instanceof XFAObject)) { + continue; + } + const color = obj2[$toStyle](this.color); + if (color) { + style[color.startsWith("#") ? propName : altPropName] = color; + } + return style; + } + if (this.color?.value) { + const color = this.color[$toStyle](); + style[color.startsWith("#") ? propName : altPropName] = color; + } + return style; + } + }; + Filter = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "filter", true); + this.addRevocationInfo = getStringOption(attributes.addRevocationInfo, ["", "required", "optional", "none"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.version = getInteger({ + data: this.version, + defaultValue: 5, + validate: (x) => x >= 1 && x <= 5 + }); + this.appearanceFilter = null; + this.certificates = null; + this.digestMethods = null; + this.encodings = null; + this.encryptionMethods = null; + this.handler = null; + this.lockDocument = null; + this.mdp = null; + this.reasons = null; + this.timeStamp = null; + } + }; + Float = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "float"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number4 = parseFloat(this[$content].trim()); + this[$content] = isNaN(number4) ? null : number4; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } + }; + template_Font = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "font", true); + this.baselineShift = getMeasurement(attributes.baselineShift); + this.fontHorizontalScale = getFloat({ + data: attributes.fontHorizontalScale, + defaultValue: 100, + validate: (x) => x >= 0 + }); + this.fontVerticalScale = getFloat({ + data: attributes.fontVerticalScale, + defaultValue: 100, + validate: (x) => x >= 0 + }); + this.id = attributes.id || ""; + this.kerningMode = getStringOption(attributes.kerningMode, ["none", "pair"]); + this.letterSpacing = getMeasurement(attributes.letterSpacing, "0"); + this.lineThrough = getInteger({ + data: attributes.lineThrough, + defaultValue: 0, + validate: (x) => x === 1 || x === 2 + }); + this.lineThroughPeriod = getStringOption(attributes.lineThroughPeriod, ["all", "word"]); + this.overline = getInteger({ + data: attributes.overline, + defaultValue: 0, + validate: (x) => x === 1 || x === 2 + }); + this.overlinePeriod = getStringOption(attributes.overlinePeriod, ["all", "word"]); + this.posture = getStringOption(attributes.posture, ["normal", "italic"]); + this.size = getMeasurement(attributes.size, "10pt"); + this.typeface = attributes.typeface || "Courier"; + this.underline = getInteger({ + data: attributes.underline, + defaultValue: 0, + validate: (x) => x === 1 || x === 2 + }); + this.underlinePeriod = getStringOption(attributes.underlinePeriod, ["all", "word"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.weight = getStringOption(attributes.weight, ["normal", "bold"]); + this.extras = null; + this.fill = null; + } + [$clean](builder) { + super[$clean](builder); + this[$globalData].usedTypefaces.add(this.typeface); + } + [$toStyle]() { + const style = toStyle(this, "fill"); + const color = style.color; + if (color) { + if (color === "#000000") { + delete style.color; + } else if (!color.startsWith("#")) { + style.background = color; + style.backgroundClip = "text"; + style.color = "transparent"; + } + } + if (this.baselineShift) { + style.verticalAlign = measureToString(this.baselineShift); + } + style.fontKerning = this.kerningMode === "none" ? "none" : "normal"; + style.letterSpacing = measureToString(this.letterSpacing); + if (this.lineThrough !== 0) { + style.textDecoration = "line-through"; + if (this.lineThrough === 2) { + style.textDecorationStyle = "double"; + } + } + if (this.overline !== 0) { + style.textDecoration = "overline"; + if (this.overline === 2) { + style.textDecorationStyle = "double"; + } + } + style.fontStyle = this.posture; + style.fontSize = measureToString(0.99 * this.size); + setFontFamily(this, this, this[$globalData].fontFinder, style); + if (this.underline !== 0) { + style.textDecoration = "underline"; + if (this.underline === 2) { + style.textDecorationStyle = "double"; + } + } + style.fontWeight = this.weight; + return style; + } + }; + Format = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "format", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.picture = null; + } + }; + Handler = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "handler"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Hyphenation = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "hyphenation"); + this.excludeAllCaps = getInteger({ + data: attributes.excludeAllCaps, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.excludeInitialCap = getInteger({ + data: attributes.excludeInitialCap, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.hyphenate = getInteger({ + data: attributes.hyphenate, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.id = attributes.id || ""; + this.pushCharacterCount = getInteger({ + data: attributes.pushCharacterCount, + defaultValue: 3, + validate: (x) => x >= 0 + }); + this.remainCharacterCount = getInteger({ + data: attributes.remainCharacterCount, + defaultValue: 3, + validate: (x) => x >= 0 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.wordCharacterCount = getInteger({ + data: attributes.wordCharacterCount, + defaultValue: 7, + validate: (x) => x >= 0 + }); + } + }; + Image2 = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "image"); + this.aspect = getStringOption(attributes.aspect, ["fit", "actual", "height", "none", "width"]); + this.contentType = attributes.contentType || ""; + this.href = attributes.href || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.transferEncoding = getStringOption(attributes.transferEncoding, ["base64", "none", "package"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$toHTML]() { + if (this.contentType && !MIMES.has(this.contentType.toLowerCase())) { + return HTMLResult.EMPTY; + } + let buffer2 = this[$globalData].images?.get(this.href); + if (!buffer2 && (this.href || !this[$content])) { + return HTMLResult.EMPTY; + } + if (!buffer2 && this.transferEncoding === "base64") { + buffer2 = fromBase64Util2(this[$content]); + } + if (!buffer2) { + return HTMLResult.EMPTY; + } + if (!this.contentType) { + for (const [header, type] of IMAGES_HEADERS) { + if (buffer2.length > header.length && header.every((x, i) => x === buffer2[i])) { + this.contentType = type; + break; + } + } + if (!this.contentType) { + return HTMLResult.EMPTY; + } + } + const blob = new Blob([buffer2], { + type: this.contentType + }); + let style; + switch (this.aspect) { + case "fit": + case "actual": + break; + case "height": + style = { + height: "100%", + objectFit: "fill" + }; + break; + case "none": + style = { + width: "100%", + height: "100%", + objectFit: "fill" + }; + break; + case "width": + style = { + width: "100%", + objectFit: "fill" + }; + break; + } + const parent = this[$getParent](); + return HTMLResult.success({ + name: "img", + attributes: { + class: ["xfaImage"], + style, + src: URL.createObjectURL(blob), + alt: parent ? ariaLabel(parent[$getParent]()) : null + } + }); + } + }; + ImageEdit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "imageEdit", true); + this.data = getStringOption(attributes.data, ["link", "embed"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + if (this.data === "embed") { + return HTMLResult.success({ + name: "div", + children: [], + attributes: {} + }); + } + return HTMLResult.EMPTY; + } + }; + Integer = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "integer"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const number4 = parseInt(this[$content].trim(), 10); + this[$content] = isNaN(number4) ? null : number4; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] !== null ? this[$content].toString() : ""); + } + }; + Issuers = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "issuers", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } + }; + Items = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "items", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.ref = attributes.ref || ""; + this.save = getInteger({ + data: attributes.save, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + [$toHTML]() { + const output2 = []; + for (const child of this[$getChildren]()) { + output2.push(child[$text]()); + } + return HTMLResult.success(output2); + } + }; + Keep = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "keep", true); + this.id = attributes.id || ""; + const options = ["none", "contentArea", "pageArea"]; + this.intact = getStringOption(attributes.intact, options); + this.next = getStringOption(attributes.next, options); + this.previous = getStringOption(attributes.previous, options); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + }; + KeyUsage = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "keyUsage"); + const options = ["", "yes", "no"]; + this.crlSign = getStringOption(attributes.crlSign, options); + this.dataEncipherment = getStringOption(attributes.dataEncipherment, options); + this.decipherOnly = getStringOption(attributes.decipherOnly, options); + this.digitalSignature = getStringOption(attributes.digitalSignature, options); + this.encipherOnly = getStringOption(attributes.encipherOnly, options); + this.id = attributes.id || ""; + this.keyAgreement = getStringOption(attributes.keyAgreement, options); + this.keyCertSign = getStringOption(attributes.keyCertSign, options); + this.keyEncipherment = getStringOption(attributes.keyEncipherment, options); + this.nonRepudiation = getStringOption(attributes.nonRepudiation, options); + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Line2 = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "line", true); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.slope = getStringOption(attributes.slope, ["\\", "/"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.edge = null; + } + [$toHTML]() { + const parent = this[$getParent]()[$getParent](); + const edge = this.edge || new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = /* @__PURE__ */ Object.create(null); + const thickness = edge.presence === "visible" ? edge.thickness : 0; + style.strokeWidth = measureToString(thickness); + style.stroke = edgeStyle.color; + let x1, y1, x2, y2; + let width = "100%"; + let height = "100%"; + if (parent.w <= thickness) { + [x1, y1, x2, y2] = ["50%", 0, "50%", "100%"]; + width = style.strokeWidth; + } else if (parent.h <= thickness) { + [x1, y1, x2, y2] = [0, "50%", "100%", "50%"]; + height = style.strokeWidth; + } else if (this.slope === "\\") { + [x1, y1, x2, y2] = [0, 0, "100%", "100%"]; + } else { + [x1, y1, x2, y2] = [0, "100%", "100%", 0]; + } + const line2 = { + name: "line", + attributes: { + xmlns: SVG_NS2, + x1, + y1, + x2, + y2, + style + } + }; + const svg = { + name: "svg", + children: [line2], + attributes: { + xmlns: SVG_NS2, + width, + height, + style: { + overflow: "visible" + } + } + }; + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } + }; + Linear = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "linear", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["toRight", "toBottom", "toLeft", "toTop"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const transf = this.type.replace(/([RBLT])/, " $1").toLowerCase(); + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + return `linear-gradient(${transf}, ${startColor}, ${endColor})`; + } + }; + LockDocument = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "lockDocument"); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + this[$content] = getStringOption(this[$content], ["auto", "0", "1"]); + } + }; + Manifest = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "manifest", true); + this.action = getStringOption(attributes.action, ["include", "all", "exclude"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.ref = new XFAObjectArray(); + } + }; + Margin = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "margin", true); + this.bottomInset = getMeasurement(attributes.bottomInset, "0"); + this.id = attributes.id || ""; + this.leftInset = getMeasurement(attributes.leftInset, "0"); + this.rightInset = getMeasurement(attributes.rightInset, "0"); + this.topInset = getMeasurement(attributes.topInset, "0"); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toStyle]() { + return { + margin: measureToString(this.topInset) + " " + measureToString(this.rightInset) + " " + measureToString(this.bottomInset) + " " + measureToString(this.leftInset) + }; + } + }; + Mdp = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "mdp"); + this.id = attributes.id || ""; + this.permissions = getInteger({ + data: attributes.permissions, + defaultValue: 2, + validate: (x) => x === 1 || x === 3 + }); + this.signatureType = getStringOption(attributes.signatureType, ["filler", "author"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Medium = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "medium"); + this.id = attributes.id || ""; + this.imagingBBox = getBBox(attributes.imagingBBox); + this.long = getMeasurement(attributes.long); + this.orientation = getStringOption(attributes.orientation, ["portrait", "landscape"]); + this.short = getMeasurement(attributes.short); + this.stock = attributes.stock || ""; + this.trayIn = getStringOption(attributes.trayIn, ["auto", "delegate", "pageFront"]); + this.trayOut = getStringOption(attributes.trayOut, ["auto", "delegate"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Message = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "message", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.text = new XFAObjectArray(); + } + }; + NumericEdit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "numericEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + const field = this[$getParent]()[$getParent](); + const html = { + name: "input", + attributes: { + type: "text", + fieldId: field[$uid], + dataId: field[$data]?.[$uid] || field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } + }; + Occur = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "occur", true); + this.id = attributes.id || ""; + this.initial = attributes.initial !== "" ? getInteger({ + data: attributes.initial, + defaultValue: "", + validate: (x) => true + }) : ""; + this.max = attributes.max !== "" ? getInteger({ + data: attributes.max, + defaultValue: 1, + validate: (x) => true + }) : ""; + this.min = attributes.min !== "" ? getInteger({ + data: attributes.min, + defaultValue: 1, + validate: (x) => true + }) : ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$clean]() { + const parent = this[$getParent](); + const originalMin = this.min; + if (this.min === "") { + this.min = parent instanceof PageArea || parent instanceof PageSet ? 0 : 1; + } + if (this.max === "") { + if (originalMin === "") { + this.max = parent instanceof PageArea || parent instanceof PageSet ? -1 : 1; + } else { + this.max = this.min; + } + } + if (this.max !== -1 && this.max < this.min) { + this.max = this.min; + } + if (this.initial === "") { + this.initial = parent instanceof Template ? 1 : this.min; + } + } + }; + Oid = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "oid"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Oids = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "oids", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.oid = new XFAObjectArray(); + } + }; + Overflow = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "overflow"); + this.id = attributes.id || ""; + this.leader = attributes.leader || ""; + this.target = attributes.target || ""; + this.trailer = attributes.trailer || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$getExtra]() { + if (!this[$extra]) { + const parent = this[$getParent](); + const root2 = this[$getTemplateRoot](); + const target = root2[$searchNode](this.target, parent); + const leader = root2[$searchNode](this.leader, parent); + const trailer = root2[$searchNode](this.trailer, parent); + this[$extra] = { + target: target?.[0] || null, + leader: leader?.[0] || null, + trailer: trailer?.[0] || null, + addLeader: false, + addTrailer: false + }; + } + return this[$extra]; + } + }; + PageArea = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pageArea", true); + this.blankOrNotBlank = getStringOption(attributes.blankOrNotBlank, ["any", "blank", "notBlank"]); + this.id = attributes.id || ""; + this.initialNumber = getInteger({ + data: attributes.initialNumber, + defaultValue: 1, + validate: (x) => true + }); + this.name = attributes.name || ""; + this.numbered = getInteger({ + data: attributes.numbered, + defaultValue: 1, + validate: (x) => true + }); + this.oddOrEven = getStringOption(attributes.oddOrEven, ["any", "even", "odd"]); + this.pagePosition = getStringOption(attributes.pagePosition, ["any", "first", "last", "only", "rest"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.desc = null; + this.extras = null; + this.medium = null; + this.occur = null; + this.area = new XFAObjectArray(); + this.contentArea = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + } + [$isUsable]() { + if (!this[$extra]) { + this[$extra] = { + numberOfUse: 0 + }; + return true; + } + return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; + } + [$cleanPage]() { + delete this[$extra]; + } + [$getNextPage]() { + this[$extra] ||= { + numberOfUse: 0 + }; + const parent = this[$getParent](); + if (parent.relation === "orderedOccurrence") { + if (this[$isUsable]()) { + this[$extra].numberOfUse += 1; + return this; + } + } + return parent[$getNextPage](); + } + [$getAvailableSpace]() { + return this[$extra].space || { + width: 0, + height: 0 + }; + } + [$toHTML]() { + this[$extra] ||= { + numberOfUse: 1 + }; + const children = []; + this[$extra].children = children; + const style = /* @__PURE__ */ Object.create(null); + if (this.medium && this.medium.short && this.medium.long) { + style.width = measureToString(this.medium.short); + style.height = measureToString(this.medium.long); + this[$extra].space = { + width: this.medium.short, + height: this.medium.long + }; + if (this.medium.orientation === "landscape") { + const x = style.width; + style.width = style.height; + style.height = x; + this[$extra].space = { + width: this.medium.long, + height: this.medium.short + }; + } + } else { + warn2("XFA - No medium specified in pageArea: please file a bug."); + } + this[$childrenToHTML]({ + filter: /* @__PURE__ */ new Set(["area", "draw", "field", "subform"]), + include: true + }); + this[$childrenToHTML]({ + filter: /* @__PURE__ */ new Set(["contentArea"]), + include: true + }); + return HTMLResult.success({ + name: "div", + children, + attributes: { + class: ["xfaPage"], + id: this[$uid], + style, + xfaName: this.name + } + }); + } + }; + PageSet = class _PageSet extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pageSet", true); + this.duplexImposition = getStringOption(attributes.duplexImposition, ["longEdge", "shortEdge"]); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relation = getStringOption(attributes.relation, ["orderedOccurrence", "duplexPaginated", "simplexPaginated"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.occur = null; + this.pageArea = new XFAObjectArray(); + this.pageSet = new XFAObjectArray(); + } + [$cleanPage]() { + for (const page of this.pageArea.children) { + page[$cleanPage](); + } + for (const page of this.pageSet.children) { + page[$cleanPage](); + } + } + [$isUsable]() { + return !this.occur || this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max; + } + [$getNextPage]() { + this[$extra] ||= { + numberOfUse: 1, + pageIndex: -1, + pageSetIndex: -1 + }; + if (this.relation === "orderedOccurrence") { + if (this[$extra].pageIndex + 1 < this.pageArea.children.length) { + this[$extra].pageIndex += 1; + const pageArea = this.pageArea.children[this[$extra].pageIndex]; + return pageArea[$getNextPage](); + } + if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) { + this[$extra].pageSetIndex += 1; + return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage](); + } + if (this[$isUsable]()) { + this[$extra].numberOfUse += 1; + this[$extra].pageIndex = -1; + this[$extra].pageSetIndex = -1; + return this[$getNextPage](); + } + const parent = this[$getParent](); + if (parent instanceof _PageSet) { + return parent[$getNextPage](); + } + this[$cleanPage](); + return this[$getNextPage](); + } + const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber; + const parity = pageNumber % 2 === 0 ? "even" : "odd"; + const position = pageNumber === 0 ? "first" : "rest"; + let page = this.pageArea.children.find((p) => p.oddOrEven === parity && p.pagePosition === position); + if (page) { + return page; + } + page = this.pageArea.children.find((p) => p.oddOrEven === "any" && p.pagePosition === position); + if (page) { + return page; + } + page = this.pageArea.children.find((p) => p.oddOrEven === "any" && p.pagePosition === "any"); + if (page) { + return page; + } + return this.pageArea.children[0]; + } + }; + Para = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "para", true); + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.lineHeight = attributes.lineHeight ? getMeasurement(attributes.lineHeight, "0pt") : ""; + this.marginLeft = attributes.marginLeft ? getMeasurement(attributes.marginLeft, "0pt") : ""; + this.marginRight = attributes.marginRight ? getMeasurement(attributes.marginRight, "0pt") : ""; + this.orphans = getInteger({ + data: attributes.orphans, + defaultValue: 0, + validate: (x) => x >= 0 + }); + this.preserve = attributes.preserve || ""; + this.radixOffset = attributes.radixOffset ? getMeasurement(attributes.radixOffset, "0pt") : ""; + this.spaceAbove = attributes.spaceAbove ? getMeasurement(attributes.spaceAbove, "0pt") : ""; + this.spaceBelow = attributes.spaceBelow ? getMeasurement(attributes.spaceBelow, "0pt") : ""; + this.tabDefault = attributes.tabDefault ? getMeasurement(this.tabDefault) : ""; + this.tabStops = (attributes.tabStops || "").trim().split(/\s+/).map((x, i) => i % 2 === 1 ? getMeasurement(x) : x); + this.textIndent = attributes.textIndent ? getMeasurement(attributes.textIndent, "0pt") : ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.vAlign = getStringOption(attributes.vAlign, ["top", "bottom", "middle"]); + this.widows = getInteger({ + data: attributes.widows, + defaultValue: 0, + validate: (x) => x >= 0 + }); + this.hyphenation = null; + } + [$toStyle]() { + const style = toStyle(this, "hAlign"); + if (this.marginLeft !== "") { + style.paddingLeft = measureToString(this.marginLeft); + } + if (this.marginRight !== "") { + style.paddingRight = measureToString(this.marginRight); + } + if (this.spaceAbove !== "") { + style.paddingTop = measureToString(this.spaceAbove); + } + if (this.spaceBelow !== "") { + style.paddingBottom = measureToString(this.spaceBelow); + } + if (this.textIndent !== "") { + style.textIndent = measureToString(this.textIndent); + fixTextIndent(style); + } + if (this.lineHeight > 0) { + style.lineHeight = measureToString(this.lineHeight); + } + if (this.tabDefault !== "") { + style.tabSize = measureToString(this.tabDefault); + } + if (this.tabStops.length > 0) { + } + if (this.hyphenatation) { + Object.assign(style, this.hyphenatation[$toStyle]()); + } + return style; + } + }; + PasswordEdit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "passwordEdit", true); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.passwordChar = attributes.passwordChar || "*"; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.margin = null; + } + }; + template_Pattern = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "pattern", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["crossHatch", "crossDiagonal", "diagonalLeft", "diagonalRight", "horizontal", "vertical"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + const width = 5; + const cmd = "repeating-linear-gradient"; + const colors = `${startColor},${startColor} ${width}px,${endColor} ${width}px,${endColor} ${2 * width}px`; + switch (this.type) { + case "crossHatch": + return `${cmd}(to top,${colors}) ${cmd}(to right,${colors})`; + case "crossDiagonal": + return `${cmd}(45deg,${colors}) ${cmd}(-45deg,${colors})`; + case "diagonalLeft": + return `${cmd}(45deg,${colors})`; + case "diagonalRight": + return `${cmd}(-45deg,${colors})`; + case "horizontal": + return `${cmd}(to top,${colors})`; + case "vertical": + return `${cmd}(to right,${colors})`; + } + return ""; + } + }; + Picture = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "picture"); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Proto = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "proto", true); + this.appearanceFilter = new XFAObjectArray(); + this.arc = new XFAObjectArray(); + this.area = new XFAObjectArray(); + this.assist = new XFAObjectArray(); + this.barcode = new XFAObjectArray(); + this.bindItems = new XFAObjectArray(); + this.bookend = new XFAObjectArray(); + this.boolean = new XFAObjectArray(); + this.border = new XFAObjectArray(); + this.break = new XFAObjectArray(); + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.button = new XFAObjectArray(); + this.calculate = new XFAObjectArray(); + this.caption = new XFAObjectArray(); + this.certificate = new XFAObjectArray(); + this.certificates = new XFAObjectArray(); + this.checkButton = new XFAObjectArray(); + this.choiceList = new XFAObjectArray(); + this.color = new XFAObjectArray(); + this.comb = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.contentArea = new XFAObjectArray(); + this.corner = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.dateTimeEdit = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.defaultUi = new XFAObjectArray(); + this.desc = new XFAObjectArray(); + this.digestMethod = new XFAObjectArray(); + this.digestMethods = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.edge = new XFAObjectArray(); + this.encoding = new XFAObjectArray(); + this.encodings = new XFAObjectArray(); + this.encrypt = new XFAObjectArray(); + this.encryptData = new XFAObjectArray(); + this.encryption = new XFAObjectArray(); + this.encryptionMethod = new XFAObjectArray(); + this.encryptionMethods = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.execute = new XFAObjectArray(); + this.extras = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.fill = new XFAObjectArray(); + this.filter = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.font = new XFAObjectArray(); + this.format = new XFAObjectArray(); + this.handler = new XFAObjectArray(); + this.hyphenation = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.imageEdit = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.issuers = new XFAObjectArray(); + this.items = new XFAObjectArray(); + this.keep = new XFAObjectArray(); + this.keyUsage = new XFAObjectArray(); + this.line = new XFAObjectArray(); + this.linear = new XFAObjectArray(); + this.lockDocument = new XFAObjectArray(); + this.manifest = new XFAObjectArray(); + this.margin = new XFAObjectArray(); + this.mdp = new XFAObjectArray(); + this.medium = new XFAObjectArray(); + this.message = new XFAObjectArray(); + this.numericEdit = new XFAObjectArray(); + this.occur = new XFAObjectArray(); + this.oid = new XFAObjectArray(); + this.oids = new XFAObjectArray(); + this.overflow = new XFAObjectArray(); + this.pageArea = new XFAObjectArray(); + this.pageSet = new XFAObjectArray(); + this.para = new XFAObjectArray(); + this.passwordEdit = new XFAObjectArray(); + this.pattern = new XFAObjectArray(); + this.picture = new XFAObjectArray(); + this.radial = new XFAObjectArray(); + this.reason = new XFAObjectArray(); + this.reasons = new XFAObjectArray(); + this.rectangle = new XFAObjectArray(); + this.ref = new XFAObjectArray(); + this.script = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + this.signData = new XFAObjectArray(); + this.signature = new XFAObjectArray(); + this.signing = new XFAObjectArray(); + this.solid = new XFAObjectArray(); + this.speak = new XFAObjectArray(); + this.stipple = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + this.subjectDN = new XFAObjectArray(); + this.subjectDNs = new XFAObjectArray(); + this.submit = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.textEdit = new XFAObjectArray(); + this.time = new XFAObjectArray(); + this.timeStamp = new XFAObjectArray(); + this.toolTip = new XFAObjectArray(); + this.traversal = new XFAObjectArray(); + this.traverse = new XFAObjectArray(); + this.ui = new XFAObjectArray(); + this.validate = new XFAObjectArray(); + this.value = new XFAObjectArray(); + this.variables = new XFAObjectArray(); + } + }; + Radial = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "radial", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["toEdge", "toCenter"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](startColor) { + startColor = startColor ? startColor[$toStyle]() : "#FFFFFF"; + const endColor = this.color ? this.color[$toStyle]() : "#000000"; + const colors = this.type === "toEdge" ? `${startColor},${endColor}` : `${endColor},${startColor}`; + return `radial-gradient(circle at center, ${colors})`; + } + }; + Reason = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "reason"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Reasons = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "reasons", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.reason = new XFAObjectArray(); + } + }; + Rectangle2 = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "rectangle", true); + this.hand = getStringOption(attributes.hand, ["even", "left", "right"]); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.corner = new XFAObjectArray(4); + this.edge = new XFAObjectArray(4); + this.fill = null; + } + [$toHTML]() { + const edge = this.edge.children.length ? this.edge.children[0] : new Edge({}); + const edgeStyle = edge[$toStyle](); + const style = /* @__PURE__ */ Object.create(null); + if (this.fill?.presence === "visible") { + Object.assign(style, this.fill[$toStyle]()); + } else { + style.fill = "transparent"; + } + style.strokeWidth = measureToString(edge.presence === "visible" ? edge.thickness : 0); + style.stroke = edgeStyle.color; + const corner = this.corner.children.length ? this.corner.children[0] : new Corner({}); + const cornerStyle = corner[$toStyle](); + const rect = { + name: "rect", + attributes: { + xmlns: SVG_NS2, + width: "100%", + height: "100%", + x: 0, + y: 0, + rx: cornerStyle.radius, + ry: cornerStyle.radius, + style + } + }; + const svg = { + name: "svg", + children: [rect], + attributes: { + xmlns: SVG_NS2, + style: { + overflow: "visible" + }, + width: "100%", + height: "100%" + } + }; + const parent = this[$getParent]()[$getParent](); + if (hasMargin(parent)) { + return HTMLResult.success({ + name: "div", + attributes: { + style: { + display: "inline", + width: "100%", + height: "100%" + } + }, + children: [svg] + }); + } + svg.attributes.style.position = "absolute"; + return HTMLResult.success(svg); + } + }; + RefElement = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "ref"); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Script = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "script"); + this.binding = attributes.binding || ""; + this.contentType = attributes.contentType || ""; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.runAt = getStringOption(attributes.runAt, ["client", "both", "server"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + SetProperty = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "setProperty"); + this.connection = attributes.connection || ""; + this.ref = attributes.ref || ""; + this.target = attributes.target || ""; + } + }; + SignData = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signData", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["sign", "clear", "verify"]); + this.ref = attributes.ref || ""; + this.target = attributes.target || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.filter = null; + this.manifest = null; + } + }; + Signature = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signature", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["PDF1.3", "PDF1.6"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.border = null; + this.extras = null; + this.filter = null; + this.manifest = null; + this.margin = null; + } + }; + Signing = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "signing", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.certificate = new XFAObjectArray(); + } + }; + Solid = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "solid", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + } + [$toStyle](startColor) { + return startColor ? startColor[$toStyle]() : "#FFFFFF"; + } + }; + Speak = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "speak"); + this.disable = getInteger({ + data: attributes.disable, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.id = attributes.id || ""; + this.priority = getStringOption(attributes.priority, ["custom", "caption", "name", "toolTip"]); + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Stipple = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "stipple", true); + this.id = attributes.id || ""; + this.rate = getInteger({ + data: attributes.rate, + defaultValue: 50, + validate: (x) => x >= 0 && x <= 100 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.color = null; + this.extras = null; + } + [$toStyle](bgColor) { + const alpha = this.rate / 100; + return Util2.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha)); + } + }; + Subform = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subform", true); + this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]); + this.allowMacro = getInteger({ + data: attributes.allowMacro, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]); + this.colSpan = getInteger({ + data: attributes.colSpan, + defaultValue: 1, + validate: (n) => n >= 1 || n === -1 + }); + this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map((x) => x === "-1" ? -1 : getMeasurement(x)); + this.h = attributes.h ? getMeasurement(attributes.h) : ""; + this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]); + this.id = attributes.id || ""; + this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]); + this.locale = attributes.locale || ""; + this.maxH = getMeasurement(attributes.maxH, "0pt"); + this.maxW = getMeasurement(attributes.maxW, "0pt"); + this.mergeMode = getStringOption(attributes.mergeMode, ["consumeData", "matchTemplate"]); + this.minH = getMeasurement(attributes.minH, "0pt"); + this.minW = getMeasurement(attributes.minW, "0pt"); + this.name = attributes.name || ""; + this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]); + this.relevant = getRelevant(attributes.relevant); + this.restoreState = getStringOption(attributes.restoreState, ["manual", "auto"]); + this.scope = getStringOption(attributes.scope, ["name", "none"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.w = attributes.w ? getMeasurement(attributes.w) : ""; + this.x = getMeasurement(attributes.x, "0pt"); + this.y = getMeasurement(attributes.y, "0pt"); + this.assist = null; + this.bind = null; + this.bookend = null; + this.border = null; + this.break = null; + this.calculate = null; + this.desc = null; + this.extras = null; + this.keep = null; + this.margin = null; + this.occur = null; + this.overflow = null; + this.pageSet = null; + this.para = null; + this.traversal = null; + this.validate = null; + this.variables = null; + this.area = new XFAObjectArray(); + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.connect = new XFAObjectArray(); + this.draw = new XFAObjectArray(); + this.event = new XFAObjectArray(); + this.exObject = new XFAObjectArray(); + this.exclGroup = new XFAObjectArray(); + this.field = new XFAObjectArray(); + this.proto = new XFAObjectArray(); + this.setProperty = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + [$getSubformParent]() { + const parent = this[$getParent](); + if (parent instanceof SubformSet) { + return parent[$getSubformParent](); + } + return parent; + } + [$isBindable]() { + return true; + } + [$isThereMoreWidth]() { + return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth](); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$flushHTML]() { + return flushHTML(this); + } + [$addHTML](html, bbox) { + addHTML(this, html, bbox); + } + [$getAvailableSpace]() { + return getAvailableSpace(this); + } + [$isSplittable]() { + const parent = this[$getSubformParent](); + if (!parent[$isSplittable]()) { + return false; + } + if (this[$extra]._isSplittable !== void 0) { + return this[$extra]._isSplittable; + } + if (this.layout === "position" || this.layout.includes("row")) { + this[$extra]._isSplittable = false; + return false; + } + if (this.keep && this.keep.intact !== "none") { + this[$extra]._isSplittable = false; + return false; + } + if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) { + return false; + } + this[$extra]._isSplittable = true; + return true; + } + [$toHTML](availableSpace) { + setTabIndex(this); + if (this.break) { + if (this.break.after !== "auto" || this.break.afterTarget !== "") { + const node2 = new BreakAfter({ + targetType: this.break.after, + target: this.break.afterTarget, + startNew: this.break.startNew.toString() + }); + node2[$globalData] = this[$globalData]; + this[$appendChild](node2); + this.breakAfter.push(node2); + } + if (this.break.before !== "auto" || this.break.beforeTarget !== "") { + const node2 = new BreakBefore({ + targetType: this.break.before, + target: this.break.beforeTarget, + startNew: this.break.startNew.toString() + }); + node2[$globalData] = this[$globalData]; + this[$appendChild](node2); + this.breakBefore.push(node2); + } + if (this.break.overflowTarget !== "") { + const node2 = new Overflow({ + target: this.break.overflowTarget, + leader: this.break.overflowLeader, + trailer: this.break.overflowTrailer + }); + node2[$globalData] = this[$globalData]; + this[$appendChild](node2); + this.overflow.push(node2); + } + this[$removeChild](this.break); + this.break = null; + } + if (this.presence === "hidden" || this.presence === "inactive") { + return HTMLResult.EMPTY; + } + if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) { + warn2("XFA - Several breakBefore or breakAfter in subforms: please file a bug."); + } + if (this.breakBefore.children.length >= 1) { + const breakBefore = this.breakBefore.children[0]; + if (handleBreak(breakBefore)) { + return HTMLResult.breakNode(breakBefore); + } + } + if (this[$extra]?.afterBreakAfter) { + return HTMLResult.EMPTY; + } + fixDimensions(this); + const children = []; + const attributes = { + id: this[$uid], + class: [] + }; + setAccess(this, attributes.class); + this[$extra] ||= /* @__PURE__ */ Object.create(null); + Object.assign(this[$extra], { + children, + line: null, + attributes, + attempt: 0, + numberInLine: 0, + availableSpace: { + width: Math.min(this.w || Infinity, availableSpace.width), + height: Math.min(this.h || Infinity, availableSpace.height) + }, + width: 0, + height: 0, + prevHeight: 0, + currentWidth: 0 + }); + const root2 = this[$getTemplateRoot](); + const savedNoLayoutFailure = root2[$extra].noLayoutFailure; + const isSplittable = this[$isSplittable](); + if (!isSplittable) { + setFirstUnsplittable(this); + } + if (!checkDimensions(this, availableSpace)) { + return HTMLResult.FAILURE; + } + const filter2 = /* @__PURE__ */ new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]); + if (this.layout.includes("row")) { + const columnWidths = this[$getSubformParent]().columnWidths; + if (Array.isArray(columnWidths) && columnWidths.length > 0) { + this[$extra].columnWidths = columnWidths; + this[$extra].currentColumn = 0; + } + } + const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign"); + const classNames = ["xfaSubform"]; + const cl = layoutClass(this); + if (cl) { + classNames.push(cl); + } + attributes.style = style; + attributes.class = classNames; + if (this.name) { + attributes.xfaName = this.name; + } + if (this.overflow) { + const overflowExtra = this.overflow[$getExtra](); + if (overflowExtra.addLeader) { + overflowExtra.addLeader = false; + handleOverflow(this, overflowExtra.leader, availableSpace); + } + } + this[$pushPara](); + const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb"; + const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1; + for (; this[$extra].attempt < maxRun; this[$extra].attempt++) { + if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) { + this[$extra].numberInLine = 0; + } + const result3 = this[$childrenToHTML]({ + filter: filter2, + include: true + }); + if (result3.success) { + break; + } + if (result3.isBreak()) { + this[$popPara](); + return result3; + } + if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root2[$extra].noLayoutFailure) { + this[$extra].attempt = maxRun; + break; + } + } + this[$popPara](); + if (!isSplittable) { + unsetFirstUnsplittable(this); + } + root2[$extra].noLayoutFailure = savedNoLayoutFailure; + if (this[$extra].attempt === maxRun) { + if (this.overflow) { + this[$getTemplateRoot]()[$extra].overflowNode = this.overflow; + } + if (!isSplittable) { + delete this[$extra]; + } + return HTMLResult.FAILURE; + } + if (this.overflow) { + const overflowExtra = this.overflow[$getExtra](); + if (overflowExtra.addTrailer) { + overflowExtra.addTrailer = false; + handleOverflow(this, overflowExtra.trailer, availableSpace); + } + } + let marginH = 0; + let marginV = 0; + if (this.margin) { + marginH = this.margin.leftInset + this.margin.rightInset; + marginV = this.margin.topInset + this.margin.bottomInset; + } + const width = Math.max(this[$extra].width + marginH, this.w || 0); + const height = Math.max(this[$extra].height + marginV, this.h || 0); + const bbox = [this.x, this.y, width, height]; + if (this.w === "") { + style.width = measureToString(width); + } + if (this.h === "") { + style.height = measureToString(height); + } + if ((style.width === "0px" || style.height === "0px") && children.length === 0) { + return HTMLResult.EMPTY; + } + const html = { + name: "div", + attributes, + children + }; + applyAssist(this, attributes); + const result2 = HTMLResult.success(createWrapper(this, html), bbox); + if (this.breakAfter.children.length >= 1) { + const breakAfter = this.breakAfter.children[0]; + if (handleBreak(breakAfter)) { + this[$extra].afterBreakAfter = result2; + return HTMLResult.breakNode(breakAfter); + } + } + delete this[$extra]; + return result2; + } + }; + SubformSet = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subformSet", true); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.relation = getStringOption(attributes.relation, ["ordered", "choice", "unordered"]); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.bookend = null; + this.break = null; + this.desc = null; + this.extras = null; + this.occur = null; + this.overflow = null; + this.breakAfter = new XFAObjectArray(); + this.breakBefore = new XFAObjectArray(); + this.subform = new XFAObjectArray(); + this.subformSet = new XFAObjectArray(); + } + *[$getContainedChildren]() { + yield* getContainedChildren(this); + } + [$getSubformParent]() { + let parent = this[$getParent](); + while (!(parent instanceof Subform)) { + parent = parent[$getParent](); + } + return parent; + } + [$isBindable]() { + return true; + } + }; + SubjectDN = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subjectDN"); + this.delimiter = attributes.delimiter || ","; + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + this[$content] = new Map(this[$content].split(this.delimiter).map((kv) => { + kv = kv.split("=", 2); + kv[0] = kv[0].trim(); + return kv; + })); + } + }; + SubjectDNs = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "subjectDNs", true); + this.id = attributes.id || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.subjectDN = new XFAObjectArray(); + } + }; + Submit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "submit", true); + this.embedPDF = getInteger({ + data: attributes.embedPDF, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.format = getStringOption(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]); + this.id = attributes.id || ""; + this.target = attributes.target || ""; + this.textEncoding = getKeyword({ + data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "", + defaultValue: "", + validate: (k) => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/) + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.xdpContent = attributes.xdpContent || ""; + this.encrypt = null; + this.encryptData = new XFAObjectArray(); + this.signData = new XFAObjectArray(); + } + }; + Template = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "template", true); + this.baseProfile = getStringOption(attributes.baseProfile, ["full", "interactiveForms"]); + this.extras = null; + this.subform = new XFAObjectArray(); + } + [$finalize]() { + if (this.subform.children.length === 0) { + warn2("XFA - No subforms in template node."); + } + if (this.subform.children.length >= 2) { + warn2("XFA - Several subforms in template node: please file a bug."); + } + this[$tabIndex] = DEFAULT_TAB_INDEX; + } + [$isSplittable]() { + return true; + } + [$searchNode](expr, container) { + if (expr.startsWith("#")) { + return [this[$ids].get(expr.slice(1))]; + } + return searchNode(this, container, expr, true, true); + } + *[$toPages]() { + if (!this.subform.children.length) { + return HTMLResult.success({ + name: "div", + children: [] + }); + } + this[$extra] = { + overflowNode: null, + firstUnsplittable: null, + currentContentArea: null, + currentPageArea: null, + noLayoutFailure: false, + pageNumber: 1, + pagePosition: "first", + oddOrEven: "odd", + blankOrNotBlank: "nonBlank", + paraStack: [] + }; + const root2 = this.subform.children[0]; + root2.pageSet[$cleanPage](); + const pageAreas = root2.pageSet.pageArea.children; + const mainHtml = { + name: "div", + children: [] + }; + let pageArea = null; + let breakBefore = null; + let breakBeforeTarget = null; + if (root2.breakBefore.children.length >= 1) { + breakBefore = root2.breakBefore.children[0]; + breakBeforeTarget = breakBefore.target; + } else if (root2.subform.children.length >= 1 && root2.subform.children[0].breakBefore.children.length >= 1) { + breakBefore = root2.subform.children[0].breakBefore.children[0]; + breakBeforeTarget = breakBefore.target; + } else if (root2.break?.beforeTarget) { + breakBefore = root2.break; + breakBeforeTarget = breakBefore.beforeTarget; + } else if (root2.subform.children.length >= 1 && root2.subform.children[0].break?.beforeTarget) { + breakBefore = root2.subform.children[0].break; + breakBeforeTarget = breakBefore.beforeTarget; + } + if (breakBefore) { + const target = this[$searchNode](breakBeforeTarget, breakBefore[$getParent]()); + if (target instanceof PageArea) { + pageArea = target; + breakBefore[$extra] = {}; + } + } + pageArea ||= pageAreas[0]; + pageArea[$extra] = { + numberOfUse: 1 + }; + const pageAreaParent = pageArea[$getParent](); + pageAreaParent[$extra] = { + numberOfUse: 1, + pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea), + pageSetIndex: 0 + }; + let targetPageArea; + let leader = null; + let trailer = null; + let hasSomething = true; + let hasSomethingCounter = 0; + let startIndex = 0; + while (true) { + if (!hasSomething) { + mainHtml.children.pop(); + if (++hasSomethingCounter === MAX_EMPTY_PAGES) { + warn2("XFA - Something goes wrong: please file a bug."); + return mainHtml; + } + } else { + hasSomethingCounter = 0; + } + targetPageArea = null; + this[$extra].currentPageArea = pageArea; + const page = pageArea[$toHTML]().html; + mainHtml.children.push(page); + if (leader) { + this[$extra].noLayoutFailure = true; + page.children.push(leader[$toHTML](pageArea[$extra].space).html); + leader = null; + } + if (trailer) { + this[$extra].noLayoutFailure = true; + page.children.push(trailer[$toHTML](pageArea[$extra].space).html); + trailer = null; + } + const contentAreas = pageArea.contentArea.children; + const htmlContentAreas = page.children.filter((node2) => node2.attributes.class.includes("xfaContentarea")); + hasSomething = false; + this[$extra].firstUnsplittable = null; + this[$extra].noLayoutFailure = false; + const flush = (index2) => { + const html = root2[$flushHTML](); + if (html) { + hasSomething ||= html.children?.length > 0; + htmlContentAreas[index2].children.push(html); + } + }; + for (let i = startIndex, ii = contentAreas.length; i < ii; i++) { + const contentArea = this[$extra].currentContentArea = contentAreas[i]; + const space = { + width: contentArea.w, + height: contentArea.h + }; + startIndex = 0; + if (leader) { + htmlContentAreas[i].children.push(leader[$toHTML](space).html); + leader = null; + } + if (trailer) { + htmlContentAreas[i].children.push(trailer[$toHTML](space).html); + trailer = null; + } + const html = root2[$toHTML](space); + if (html.success) { + if (html.html) { + hasSomething ||= html.html.children?.length > 0; + htmlContentAreas[i].children.push(html.html); + } else if (!hasSomething && mainHtml.children.length > 1) { + mainHtml.children.pop(); + } + return mainHtml; + } + if (html.isBreak()) { + const node2 = html.breakNode; + flush(i); + if (node2.targetType === "auto") { + continue; + } + if (node2.leader) { + leader = this[$searchNode](node2.leader, node2[$getParent]()); + leader = leader ? leader[0] : null; + } + if (node2.trailer) { + trailer = this[$searchNode](node2.trailer, node2[$getParent]()); + trailer = trailer ? trailer[0] : null; + } + if (node2.targetType === "pageArea") { + targetPageArea = node2[$extra].target; + i = Infinity; + } else if (!node2[$extra].target) { + i = node2[$extra].index; + } else { + targetPageArea = node2[$extra].target; + startIndex = node2[$extra].index + 1; + i = Infinity; + } + continue; + } + if (this[$extra].overflowNode) { + const node2 = this[$extra].overflowNode; + this[$extra].overflowNode = null; + const overflowExtra = node2[$getExtra](); + const target = overflowExtra.target; + overflowExtra.addLeader = overflowExtra.leader !== null; + overflowExtra.addTrailer = overflowExtra.trailer !== null; + flush(i); + const currentIndex = i; + i = Infinity; + if (target instanceof PageArea) { + targetPageArea = target; + } else if (target instanceof ContentArea) { + const index2 = contentAreas.indexOf(target); + if (index2 !== -1) { + if (index2 > currentIndex) { + i = index2 - 1; + } else { + startIndex = index2; + } + } else { + targetPageArea = target[$getParent](); + startIndex = targetPageArea.contentArea.children.indexOf(target); + } + } + continue; + } + flush(i); + } + this[$extra].pageNumber += 1; + if (targetPageArea) { + if (targetPageArea[$isUsable]()) { + targetPageArea[$extra].numberOfUse += 1; + } else { + targetPageArea = null; + } + } + pageArea = targetPageArea || pageArea[$getNextPage](); + yield null; + } + } + }; + Text = class extends ContentObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "text"); + this.id = attributes.id || ""; + this.maxChars = getInteger({ + data: attributes.maxChars, + defaultValue: 0, + validate: (x) => x >= 0 + }); + this.name = attributes.name || ""; + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$acceptWhitespace]() { + return true; + } + [$onChild](child) { + if (child[$namespaceId] === NamespaceIds.xhtml.id) { + this[$content] = child; + return true; + } + warn2(`XFA - Invalid content in Text: ${child[$nodeName]}.`); + return false; + } + [$onText](str) { + if (this[$content] instanceof XFAObject) { + return; + } + super[$onText](str); + } + [$finalize]() { + if (typeof this[$content] === "string") { + this[$content] = this[$content].replaceAll("\r\n", "\n"); + } + } + [$getExtra]() { + if (typeof this[$content] === "string") { + return this[$content].split(/[\u2029\u2028\n]/).filter((line2) => !!line2).join("\n"); + } + return this[$content][$text](); + } + [$toHTML](availableSpace) { + if (typeof this[$content] === "string") { + const html = valueToHtml(this[$content]).html; + if (this[$content].includes("\u2029")) { + html.name = "div"; + html.children = []; + this[$content].split("\u2029").map((para) => para.split(/[\u2028\n]/).flatMap((line2) => [{ + name: "span", + value: line2 + }, { + name: "br" + }])).forEach((lines) => { + html.children.push({ + name: "p", + children: lines + }); + }); + } else if (/[\u2028\n]/.test(this[$content])) { + html.name = "div"; + html.children = []; + this[$content].split(/[\u2028\n]/).forEach((line2) => { + html.children.push({ + name: "span", + value: line2 + }, { + name: "br" + }); + }); + } + return HTMLResult.success(html); + } + return this[$content][$toHTML](availableSpace); + } + }; + TextEdit = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "textEdit", true); + this.allowRichText = getInteger({ + data: attributes.allowRichText, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.hScrollPolicy = getStringOption(attributes.hScrollPolicy, ["auto", "off", "on"]); + this.id = attributes.id || ""; + this.multiLine = getInteger({ + data: attributes.multiLine, + defaultValue: "", + validate: (x) => x === 0 || x === 1 + }); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.vScrollPolicy = getStringOption(attributes.vScrollPolicy, ["auto", "off", "on"]); + this.border = null; + this.comb = null; + this.extras = null; + this.margin = null; + } + [$toHTML](availableSpace) { + const style = toStyle(this, "border", "font", "margin"); + let html; + const field = this[$getParent]()[$getParent](); + if (this.multiLine === "") { + this.multiLine = field instanceof Draw ? 1 : 0; + } + if (this.multiLine === 1) { + html = { + name: "textarea", + attributes: { + dataId: field[$data]?.[$uid] || field[$uid], + fieldId: field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + } else { + html = { + name: "input", + attributes: { + type: "text", + dataId: field[$data]?.[$uid] || field[$uid], + fieldId: field[$uid], + class: ["xfaTextfield"], + style, + "aria-label": ariaLabel(field), + "aria-required": false + } + }; + } + if (isRequired(field)) { + html.attributes["aria-required"] = true; + html.attributes.required = true; + } + return HTMLResult.success({ + name: "label", + attributes: { + class: ["xfaLabel"] + }, + children: [html] + }); + } + }; + Time2 = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "time"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + [$finalize]() { + const date6 = this[$content].trim(); + this[$content] = date6 ? new Date(date6) : null; + } + [$toHTML](availableSpace) { + return valueToHtml(this[$content] ? this[$content].toString() : ""); + } + }; + TimeStamp = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "timeStamp"); + this.id = attributes.id || ""; + this.server = attributes.server || ""; + this.type = getStringOption(attributes.type, ["optional", "required"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + ToolTip = class extends StringObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "toolTip"); + this.id = attributes.id || ""; + this.rid = attributes.rid || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Traversal = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "traversal", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.traverse = new XFAObjectArray(); + } + }; + Traverse = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "traverse", true); + this.id = attributes.id || ""; + this.operation = getStringOption(attributes.operation, ["next", "back", "down", "first", "left", "right", "up"]); + this.ref = attributes.ref || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.script = null; + } + get name() { + return this.operation; + } + [$isTransparent]() { + return false; + } + }; + Ui = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "ui", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.picture = null; + this.barcode = null; + this.button = null; + this.checkButton = null; + this.choiceList = null; + this.dateTimeEdit = null; + this.defaultUi = null; + this.imageEdit = null; + this.numericEdit = null; + this.passwordEdit = null; + this.signature = null; + this.textEdit = null; + } + [$getExtra]() { + if (this[$extra] === void 0) { + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "extras" || name === "picture") { + continue; + } + const obj2 = this[name]; + if (!(obj2 instanceof XFAObject)) { + continue; + } + this[$extra] = obj2; + return obj2; + } + this[$extra] = null; + } + return this[$extra]; + } + [$toHTML](availableSpace) { + const obj2 = this[$getExtra](); + if (obj2) { + return obj2[$toHTML](availableSpace); + } + return HTMLResult.EMPTY; + } + }; + Validate = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "validate", true); + this.formatTest = getStringOption(attributes.formatTest, ["warning", "disabled", "error"]); + this.id = attributes.id || ""; + this.nullTest = getStringOption(attributes.nullTest, ["disabled", "error", "warning"]); + this.scriptTest = getStringOption(attributes.scriptTest, ["error", "disabled", "warning"]); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.extras = null; + this.message = null; + this.picture = null; + this.script = null; + } + }; + Value = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "value", true); + this.id = attributes.id || ""; + this.override = getInteger({ + data: attributes.override, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.relevant = getRelevant(attributes.relevant); + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.arc = null; + this.boolean = null; + this.date = null; + this.dateTime = null; + this.decimal = null; + this.exData = null; + this.float = null; + this.image = null; + this.integer = null; + this.line = null; + this.rectangle = null; + this.text = null; + this.time = null; + } + [$setValue](value) { + const parent = this[$getParent](); + if (parent instanceof Field) { + if (parent.ui?.imageEdit) { + if (!this.image) { + this.image = new Image2({}); + this[$appendChild](this.image); + } + this.image[$content] = value[$content]; + return; + } + } + const valueName = value[$nodeName]; + if (this[valueName] !== null) { + this[valueName][$content] = value[$content]; + return; + } + for (const name of Object.getOwnPropertyNames(this)) { + const obj2 = this[name]; + if (obj2 instanceof XFAObject) { + this[name] = null; + this[$removeChild](obj2); + } + } + this[value[$nodeName]] = value; + this[$appendChild](value); + } + [$text]() { + if (this.exData) { + if (typeof this.exData[$content] === "string") { + return this.exData[$content].trim(); + } + return this.exData[$content][$text]().trim(); + } + for (const name of Object.getOwnPropertyNames(this)) { + if (name === "image") { + continue; + } + const obj2 = this[name]; + if (obj2 instanceof XFAObject) { + return (obj2[$content] || "").toString().trim(); + } + } + return null; + } + [$toHTML](availableSpace) { + for (const name of Object.getOwnPropertyNames(this)) { + const obj2 = this[name]; + if (!(obj2 instanceof XFAObject)) { + continue; + } + return obj2[$toHTML](availableSpace); + } + return HTMLResult.EMPTY; + } + }; + Variables = class extends XFAObject { + constructor(attributes) { + super(TEMPLATE_NS_ID, "variables", true); + this.id = attributes.id || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + this.boolean = new XFAObjectArray(); + this.date = new XFAObjectArray(); + this.dateTime = new XFAObjectArray(); + this.decimal = new XFAObjectArray(); + this.exData = new XFAObjectArray(); + this.float = new XFAObjectArray(); + this.image = new XFAObjectArray(); + this.integer = new XFAObjectArray(); + this.manifest = new XFAObjectArray(); + this.script = new XFAObjectArray(); + this.text = new XFAObjectArray(); + this.time = new XFAObjectArray(); + } + [$isTransparent]() { + return true; + } + }; + TemplateNamespace = class _TemplateNamespace { + static [$buildXFAObject](name, attributes) { + if (_TemplateNamespace.hasOwnProperty(name)) { + const node2 = _TemplateNamespace[name](attributes); + node2[$setSetAttributes](attributes); + return node2; + } + return void 0; + } + static appearanceFilter(attrs) { + return new AppearanceFilter(attrs); + } + static arc(attrs) { + return new Arc(attrs); + } + static area(attrs) { + return new Area(attrs); + } + static assist(attrs) { + return new Assist(attrs); + } + static barcode(attrs) { + return new Barcode(attrs); + } + static bind(attrs) { + return new Bind(attrs); + } + static bindItems(attrs) { + return new BindItems(attrs); + } + static bookend(attrs) { + return new Bookend(attrs); + } + static boolean(attrs) { + return new BooleanElement(attrs); + } + static border(attrs) { + return new Border(attrs); + } + static break(attrs) { + return new Break(attrs); + } + static breakAfter(attrs) { + return new BreakAfter(attrs); + } + static breakBefore(attrs) { + return new BreakBefore(attrs); + } + static button(attrs) { + return new Button(attrs); + } + static calculate(attrs) { + return new Calculate(attrs); + } + static caption(attrs) { + return new Caption(attrs); + } + static certificate(attrs) { + return new Certificate(attrs); + } + static certificates(attrs) { + return new Certificates(attrs); + } + static checkButton(attrs) { + return new CheckButton(attrs); + } + static choiceList(attrs) { + return new ChoiceList(attrs); + } + static color(attrs) { + return new Color(attrs); + } + static comb(attrs) { + return new Comb(attrs); + } + static connect(attrs) { + return new Connect(attrs); + } + static contentArea(attrs) { + return new ContentArea(attrs); + } + static corner(attrs) { + return new Corner(attrs); + } + static date(attrs) { + return new DateElement(attrs); + } + static dateTime(attrs) { + return new DateTime(attrs); + } + static dateTimeEdit(attrs) { + return new DateTimeEdit(attrs); + } + static decimal(attrs) { + return new Decimal(attrs); + } + static defaultUi(attrs) { + return new DefaultUi(attrs); + } + static desc(attrs) { + return new Desc(attrs); + } + static digestMethod(attrs) { + return new DigestMethod(attrs); + } + static digestMethods(attrs) { + return new DigestMethods(attrs); + } + static draw(attrs) { + return new Draw(attrs); + } + static edge(attrs) { + return new Edge(attrs); + } + static encoding(attrs) { + return new Encoding(attrs); + } + static encodings(attrs) { + return new Encodings(attrs); + } + static encrypt(attrs) { + return new Encrypt(attrs); + } + static encryptData(attrs) { + return new EncryptData(attrs); + } + static encryption(attrs) { + return new Encryption(attrs); + } + static encryptionMethod(attrs) { + return new EncryptionMethod(attrs); + } + static encryptionMethods(attrs) { + return new EncryptionMethods(attrs); + } + static event(attrs) { + return new Event2(attrs); + } + static exData(attrs) { + return new ExData(attrs); + } + static exObject(attrs) { + return new ExObject(attrs); + } + static exclGroup(attrs) { + return new ExclGroup(attrs); + } + static execute(attrs) { + return new Execute(attrs); + } + static extras(attrs) { + return new Extras(attrs); + } + static field(attrs) { + return new Field(attrs); + } + static fill(attrs) { + return new Fill(attrs); + } + static filter(attrs) { + return new Filter(attrs); + } + static float(attrs) { + return new Float(attrs); + } + static font(attrs) { + return new template_Font(attrs); + } + static format(attrs) { + return new Format(attrs); + } + static handler(attrs) { + return new Handler(attrs); + } + static hyphenation(attrs) { + return new Hyphenation(attrs); + } + static image(attrs) { + return new Image2(attrs); + } + static imageEdit(attrs) { + return new ImageEdit(attrs); + } + static integer(attrs) { + return new Integer(attrs); + } + static issuers(attrs) { + return new Issuers(attrs); + } + static items(attrs) { + return new Items(attrs); + } + static keep(attrs) { + return new Keep(attrs); + } + static keyUsage(attrs) { + return new KeyUsage(attrs); + } + static line(attrs) { + return new Line2(attrs); + } + static linear(attrs) { + return new Linear(attrs); + } + static lockDocument(attrs) { + return new LockDocument(attrs); + } + static manifest(attrs) { + return new Manifest(attrs); + } + static margin(attrs) { + return new Margin(attrs); + } + static mdp(attrs) { + return new Mdp(attrs); + } + static medium(attrs) { + return new Medium(attrs); + } + static message(attrs) { + return new Message(attrs); + } + static numericEdit(attrs) { + return new NumericEdit(attrs); + } + static occur(attrs) { + return new Occur(attrs); + } + static oid(attrs) { + return new Oid(attrs); + } + static oids(attrs) { + return new Oids(attrs); + } + static overflow(attrs) { + return new Overflow(attrs); + } + static pageArea(attrs) { + return new PageArea(attrs); + } + static pageSet(attrs) { + return new PageSet(attrs); + } + static para(attrs) { + return new Para(attrs); + } + static passwordEdit(attrs) { + return new PasswordEdit(attrs); + } + static pattern(attrs) { + return new template_Pattern(attrs); + } + static picture(attrs) { + return new Picture(attrs); + } + static proto(attrs) { + return new Proto(attrs); + } + static radial(attrs) { + return new Radial(attrs); + } + static reason(attrs) { + return new Reason(attrs); + } + static reasons(attrs) { + return new Reasons(attrs); + } + static rectangle(attrs) { + return new Rectangle2(attrs); + } + static ref(attrs) { + return new RefElement(attrs); + } + static script(attrs) { + return new Script(attrs); + } + static setProperty(attrs) { + return new SetProperty(attrs); + } + static signData(attrs) { + return new SignData(attrs); + } + static signature(attrs) { + return new Signature(attrs); + } + static signing(attrs) { + return new Signing(attrs); + } + static solid(attrs) { + return new Solid(attrs); + } + static speak(attrs) { + return new Speak(attrs); + } + static stipple(attrs) { + return new Stipple(attrs); + } + static subform(attrs) { + return new Subform(attrs); + } + static subformSet(attrs) { + return new SubformSet(attrs); + } + static subjectDN(attrs) { + return new SubjectDN(attrs); + } + static subjectDNs(attrs) { + return new SubjectDNs(attrs); + } + static submit(attrs) { + return new Submit(attrs); + } + static template(attrs) { + return new Template(attrs); + } + static text(attrs) { + return new Text(attrs); + } + static textEdit(attrs) { + return new TextEdit(attrs); + } + static time(attrs) { + return new Time2(attrs); + } + static timeStamp(attrs) { + return new TimeStamp(attrs); + } + static toolTip(attrs) { + return new ToolTip(attrs); + } + static traversal(attrs) { + return new Traversal(attrs); + } + static traverse(attrs) { + return new Traverse(attrs); + } + static ui(attrs) { + return new Ui(attrs); + } + static validate(attrs) { + return new Validate(attrs); + } + static value(attrs) { + return new Value(attrs); + } + static variables(attrs) { + return new Variables(attrs); + } + }; + bind_NS_DATASETS = NamespaceIds.datasets.id; + Binder = class { + constructor(root2) { + this.root = root2; + this.datasets = root2.datasets; + this.data = root2.datasets?.data || new XmlObject(NamespaceIds.datasets.id, "data"); + this.emptyMerge = this.data[$getChildren]().length === 0; + this.root.form = this.form = root2.template[$clone](); + } + _isConsumeData() { + return !this.emptyMerge && this._mergeMode; + } + _isMatchTemplate() { + return !this._isConsumeData(); + } + bind() { + this._bindElement(this.form, this.data); + return this.form; + } + getData() { + return this.data; + } + _bindValue(formNode, data, picture) { + formNode[$data] = data; + if (formNode[$hasSettableValue]()) { + if (data[$isDataValue]()) { + const value = data[$getDataValue](); + formNode[$setValue](createText(value)); + } else if (formNode instanceof Field && formNode.ui?.choiceList?.open === "multiSelect") { + const value = data[$getChildren]().map((child) => child[$content].trim()).join("\n"); + formNode[$setValue](createText(value)); + } else if (this._isConsumeData()) { + warn2(`XFA - Nodes haven't the same type.`); + } + } else if (!data[$isDataValue]() || this._isMatchTemplate()) { + this._bindElement(formNode, data); + } else { + warn2(`XFA - Nodes haven't the same type.`); + } + } + _findDataByNameToConsume(name, isValue, dataNode, global2) { + if (!name) { + return null; + } + let generator, match; + for (let i = 0; i < 3; i++) { + generator = dataNode[$getRealChildrenByNameIt](name, false, true); + while (true) { + match = generator.next().value; + if (!match) { + break; + } + if (isValue === match[$isDataValue]()) { + return match; + } + } + if (dataNode[$namespaceId] === NamespaceIds.datasets.id && dataNode[$nodeName] === "data") { + break; + } + dataNode = dataNode[$getParent](); + } + if (!global2) { + return null; + } + generator = this.data[$getRealChildrenByNameIt](name, true, false); + match = generator.next().value; + if (match) { + return match; + } + generator = this.data[$getAttributeIt](name, true); + match = generator.next().value; + if (match?.[$isDataValue]()) { + return match; + } + return null; + } + _setProperties(formNode, dataNode) { + if (!formNode.hasOwnProperty("setProperty")) { + return; + } + for (const { + ref, + target, + connection: connection2 + } of formNode.setProperty.children) { + if (connection2) { + continue; + } + if (!ref) { + continue; + } + const nodes = searchNode(this.root, dataNode, ref, false, false); + if (!nodes) { + warn2(`XFA - Invalid reference: ${ref}.`); + continue; + } + const [node2] = nodes; + if (!node2[$isDescendent](this.data)) { + warn2(`XFA - Invalid node: must be a data node.`); + continue; + } + const targetNodes = searchNode(this.root, formNode, target, false, false); + if (!targetNodes) { + warn2(`XFA - Invalid target: ${target}.`); + continue; + } + const [targetNode] = targetNodes; + if (!targetNode[$isDescendent](formNode)) { + warn2(`XFA - Invalid target: must be a property or subproperty.`); + continue; + } + const targetParent = targetNode[$getParent](); + if (targetNode instanceof SetProperty || targetParent instanceof SetProperty) { + warn2(`XFA - Invalid target: cannot be a setProperty or one of its properties.`); + continue; + } + if (targetNode instanceof BindItems || targetParent instanceof BindItems) { + warn2(`XFA - Invalid target: cannot be a bindItems or one of its properties.`); + continue; + } + const content = node2[$text](); + const name = targetNode[$nodeName]; + if (targetNode instanceof XFAAttribute) { + const attrs = /* @__PURE__ */ Object.create(null); + attrs[name] = content; + const obj2 = Reflect.construct(Object.getPrototypeOf(targetParent).constructor, [attrs]); + targetParent[name] = obj2[name]; + continue; + } + if (!targetNode.hasOwnProperty($content)) { + warn2(`XFA - Invalid node to use in setProperty`); + continue; + } + targetNode[$data] = node2; + targetNode[$content] = content; + targetNode[$finalize](); + } + } + _bindItems(formNode, dataNode) { + if (!formNode.hasOwnProperty("items") || !formNode.hasOwnProperty("bindItems") || formNode.bindItems.isEmpty()) { + return; + } + for (const item of formNode.items.children) { + formNode[$removeChild](item); + } + formNode.items.clear(); + const labels = new Items({}); + const values3 = new Items({}); + formNode[$appendChild](labels); + formNode.items.push(labels); + formNode[$appendChild](values3); + formNode.items.push(values3); + for (const { + ref, + labelRef, + valueRef, + connection: connection2 + } of formNode.bindItems.children) { + if (connection2) { + continue; + } + if (!ref) { + continue; + } + const nodes = searchNode(this.root, dataNode, ref, false, false); + if (!nodes) { + warn2(`XFA - Invalid reference: ${ref}.`); + continue; + } + for (const node2 of nodes) { + if (!node2[$isDescendent](this.datasets)) { + warn2(`XFA - Invalid ref (${ref}): must be a datasets child.`); + continue; + } + const labelNodes = searchNode(this.root, node2, labelRef, true, false); + if (!labelNodes) { + warn2(`XFA - Invalid label: ${labelRef}.`); + continue; + } + const [labelNode] = labelNodes; + if (!labelNode[$isDescendent](this.datasets)) { + warn2(`XFA - Invalid label: must be a datasets child.`); + continue; + } + const valueNodes = searchNode(this.root, node2, valueRef, true, false); + if (!valueNodes) { + warn2(`XFA - Invalid value: ${valueRef}.`); + continue; + } + const [valueNode] = valueNodes; + if (!valueNode[$isDescendent](this.datasets)) { + warn2(`XFA - Invalid value: must be a datasets child.`); + continue; + } + const label = createText(labelNode[$text]()); + const value = createText(valueNode[$text]()); + labels[$appendChild](label); + labels.text.push(label); + values3[$appendChild](value); + values3.text.push(value); + } + } + } + _bindOccurrences(formNode, matches, picture) { + let baseClone; + if (matches.length > 1) { + baseClone = formNode[$clone](); + baseClone[$removeChild](baseClone.occur); + baseClone.occur = null; + } + this._bindValue(formNode, matches[0], picture); + this._setProperties(formNode, matches[0]); + this._bindItems(formNode, matches[0]); + if (matches.length === 1) { + return; + } + const parent = formNode[$getParent](); + const name = formNode[$nodeName]; + const pos = parent[$indexOf](formNode); + for (let i = 1, ii = matches.length; i < ii; i++) { + const match = matches[i]; + const clone3 = baseClone[$clone](); + parent[name].push(clone3); + parent[$insertAt](pos + i, clone3); + this._bindValue(clone3, match, picture); + this._setProperties(clone3, match); + this._bindItems(clone3, match); + } + } + _createOccurrences(formNode) { + if (!this.emptyMerge) { + return; + } + const { + occur + } = formNode; + if (!occur || occur.initial <= 1) { + return; + } + const parent = formNode[$getParent](); + const name = formNode[$nodeName]; + if (!(parent[name] instanceof XFAObjectArray)) { + return; + } + let currentNumber; + if (formNode.name) { + currentNumber = parent[name].children.filter((e) => e.name === formNode.name).length; + } else { + currentNumber = parent[name].children.length; + } + const pos = parent[$indexOf](formNode) + 1; + const ii = occur.initial - currentNumber; + if (ii) { + const nodeClone = formNode[$clone](); + nodeClone[$removeChild](nodeClone.occur); + nodeClone.occur = null; + parent[name].push(nodeClone); + parent[$insertAt](pos, nodeClone); + for (let i = 1; i < ii; i++) { + const clone3 = nodeClone[$clone](); + parent[name].push(clone3); + parent[$insertAt](pos + i, clone3); + } + } + } + _getOccurInfo(formNode) { + const { + name, + occur + } = formNode; + if (!occur || !name) { + return [1, 1]; + } + const max2 = occur.max === -1 ? Infinity : occur.max; + return [occur.min, max2]; + } + _setAndBind(formNode, dataNode) { + this._setProperties(formNode, dataNode); + this._bindItems(formNode, dataNode); + this._bindElement(formNode, dataNode); + } + _bindElement(formNode, dataNode) { + const uselessNodes = []; + this._createOccurrences(formNode); + for (const child of formNode[$getChildren]()) { + if (child[$data]) { + continue; + } + if (this._mergeMode === void 0 && child[$nodeName] === "subform") { + this._mergeMode = child.mergeMode === "consumeData"; + const dataChildren = dataNode[$getChildren](); + if (dataChildren.length > 0) { + this._bindOccurrences(child, [dataChildren[0]], null); + } else if (this.emptyMerge) { + const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; + const dataChild = child[$data] = new XmlObject(nsId, child.name || "root"); + dataNode[$appendChild](dataChild); + this._bindElement(child, dataChild); + } + continue; + } + if (!child[$isBindable]()) { + continue; + } + let global2 = false; + let picture = null; + let ref = null; + let match = null; + if (child.bind) { + switch (child.bind.match) { + case "none": + this._setAndBind(child, dataNode); + continue; + case "global": + global2 = true; + break; + case "dataRef": + if (!child.bind.ref) { + warn2(`XFA - ref is empty in node ${child[$nodeName]}.`); + this._setAndBind(child, dataNode); + continue; + } + ref = child.bind.ref; + break; + default: + break; + } + if (child.bind.picture) { + picture = child.bind.picture[$content]; + } + } + const [min2, max2] = this._getOccurInfo(child); + if (ref) { + match = searchNode(this.root, dataNode, ref, true, false); + if (match === null) { + match = createDataNode(this.data, dataNode, ref); + if (!match) { + continue; + } + if (this._isConsumeData()) { + match[$consumed] = true; + } + this._setAndBind(child, match); + continue; + } else { + if (this._isConsumeData()) { + match = match.filter((node2) => !node2[$consumed]); + } + if (match.length > max2) { + match = match.slice(0, max2); + } else if (match.length === 0) { + match = null; + } + if (match && this._isConsumeData()) { + match.forEach((node2) => { + node2[$consumed] = true; + }); + } + } + } else { + if (!child.name) { + this._setAndBind(child, dataNode); + continue; + } + if (this._isConsumeData()) { + const matches = []; + while (matches.length < max2) { + const found = this._findDataByNameToConsume(child.name, child[$hasSettableValue](), dataNode, global2); + if (!found) { + break; + } + found[$consumed] = true; + matches.push(found); + } + match = matches.length > 0 ? matches : null; + } else { + match = dataNode[$getRealChildrenByNameIt](child.name, false, this.emptyMerge).next().value; + if (!match) { + if (min2 === 0) { + uselessNodes.push(child); + continue; + } + const nsId = dataNode[$namespaceId] === bind_NS_DATASETS ? -1 : dataNode[$namespaceId]; + match = child[$data] = new XmlObject(nsId, child.name); + if (this.emptyMerge) { + match[$consumed] = true; + } + dataNode[$appendChild](match); + this._setAndBind(child, match); + continue; + } + if (this.emptyMerge) { + match[$consumed] = true; + } + match = [match]; + } + } + if (match) { + this._bindOccurrences(child, match, picture); + } else if (min2 > 0) { + this._setAndBind(child, dataNode); + } else { + uselessNodes.push(child); + } + } + uselessNodes.forEach((node2) => node2[$getParent]()[$removeChild](node2)); + } + }; + DataHandler = class { + constructor(root2, data) { + this.data = data; + this.dataset = root2.datasets || null; + } + serialize(storage2) { + const stack = [[-1, this.data[$getChildren]()]]; + while (stack.length > 0) { + const last2 = stack.at(-1); + const [i, children] = last2; + if (i + 1 === children.length) { + stack.pop(); + continue; + } + const child = children[++last2[0]]; + const storageEntry = storage2.get(child[$uid]); + if (storageEntry) { + child[$setValue](storageEntry); + } else { + const attributes = child[$getAttributes](); + for (const value of attributes.values()) { + const entry = storage2.get(value[$uid]); + if (entry) { + value[$setValue](entry); + break; + } + } + } + const nodes = child[$getChildren](); + if (nodes.length > 0) { + stack.push([-1, nodes]); + } + } + const buf = [``]; + if (this.dataset) { + for (const child of this.dataset[$getChildren]()) { + if (child[$nodeName] !== "data") { + child[$toString](buf); + } + } + } + this.data[$toString](buf); + buf.push(""); + return buf.join(""); + } + }; + CONFIG_NS_ID = NamespaceIds.config.id; + Acrobat = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "acrobat", true); + this.acrobat7 = null; + this.autoSave = null; + this.common = null; + this.validate = null; + this.validateApprovalSignatures = null; + this.submitUrl = new XFAObjectArray(); + } + }; + Acrobat7 = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "acrobat7", true); + this.dynamicRender = null; + } + }; + ADBE_JSConsole = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ADBE_JSConsole", ["delegate", "Enable", "Disable"]); + } + }; + ADBE_JSDebugger = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ADBE_JSDebugger", ["delegate", "Enable", "Disable"]); + } + }; + AddSilentPrint = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "addSilentPrint"); + } + }; + AddViewerPreferences = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "addViewerPreferences"); + } + }; + AdjustData = class extends Option10 { + constructor(attributes) { + super(CONFIG_NS_ID, "adjustData"); + } + }; + AdobeExtensionLevel = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "adobeExtensionLevel", 0, (n) => n >= 1 && n <= 8); + } + }; + Agent = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "agent", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.common = new XFAObjectArray(); + } + }; + AlwaysEmbed = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "alwaysEmbed"); + } + }; + Amd = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "amd"); + } + }; + config_Area = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "area"); + this.level = getInteger({ + data: attributes.level, + defaultValue: 0, + validate: (n) => n >= 1 && n <= 3 + }); + this.name = getStringOption(attributes.name, ["", "barcode", "coreinit", "deviceDriver", "font", "general", "layout", "merge", "script", "signature", "sourceSet", "templateCache"]); + } + }; + Attributes = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "attributes", ["preserve", "delegate", "ignore"]); + } + }; + AutoSave = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "autoSave", ["disabled", "enabled"]); + } + }; + Base = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "base"); + } + }; + BatchOutput = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "batchOutput"); + this.format = getStringOption(attributes.format, ["none", "concat", "zip", "zipCompress"]); + } + }; + BehaviorOverride = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "behaviorOverride"); + } + [$finalize]() { + this[$content] = new Map(this[$content].trim().split(/\s+/).filter((x) => x.includes(":")).map((x) => x.split(":", 2))); + } + }; + Cache2 = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "cache", true); + this.templateCache = null; + } + }; + Change = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "change"); + } + }; + Common = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "common", true); + this.data = null; + this.locale = null; + this.localeSet = null; + this.messaging = null; + this.suppressBanner = null; + this.template = null; + this.validationMessaging = null; + this.versionControl = null; + this.log = new XFAObjectArray(); + } + }; + Compress = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "compress"); + this.scope = getStringOption(attributes.scope, ["imageOnly", "document"]); + } + }; + CompressLogicalStructure = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "compressLogicalStructure"); + } + }; + CompressObjectStream = class extends Option10 { + constructor(attributes) { + super(CONFIG_NS_ID, "compressObjectStream"); + } + }; + Compression = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "compression", true); + this.compressLogicalStructure = null; + this.compressObjectStream = null; + this.level = null; + this.type = null; + } + }; + Config = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "config", true); + this.acrobat = null; + this.present = null; + this.trace = null; + this.agent = new XFAObjectArray(); + } + }; + Conformance = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "conformance", ["A", "B"]); + } + }; + ContentCopy = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "contentCopy"); + } + }; + Copies = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "copies", 1, (n) => n >= 1); + } + }; + Creator = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "creator"); + } + }; + CurrentPage = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "currentPage", 0, (n) => n >= 0); + } + }; + Data = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "data", true); + this.adjustData = null; + this.attributes = null; + this.incrementalLoad = null; + this.outputXSL = null; + this.range = null; + this.record = null; + this.startNode = null; + this.uri = null; + this.window = null; + this.xsl = null; + this.excludeNS = new XFAObjectArray(); + this.transform = new XFAObjectArray(); + } + }; + Debug = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "debug", true); + this.uri = null; + } + }; + DefaultTypeface = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "defaultTypeface"); + this.writingScript = getStringOption(attributes.writingScript, ["*", "Arabic", "Cyrillic", "EastEuropeanRoman", "Greek", "Hebrew", "Japanese", "Korean", "Roman", "SimplifiedChinese", "Thai", "TraditionalChinese", "Vietnamese"]); + } + }; + Destination = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "destination", ["pdf", "pcl", "ps", "webClient", "zpl"]); + } + }; + DocumentAssembly = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "documentAssembly"); + } + }; + Driver = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "driver", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.fontInfo = null; + this.xdc = null; + } + }; + DuplexOption = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "duplexOption", ["simplex", "duplexFlipLongEdge", "duplexFlipShortEdge"]); + } + }; + DynamicRender = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "dynamicRender", ["forbidden", "required"]); + } + }; + Embed = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "embed"); + } + }; + config_Encrypt = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "encrypt"); + } + }; + config_Encryption = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "encryption", true); + this.encrypt = null; + this.encryptionLevel = null; + this.permissions = null; + } + }; + EncryptionLevel = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "encryptionLevel", ["40bit", "128bit"]); + } + }; + Enforce = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "enforce"); + } + }; + Equate = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "equate"); + this.force = getInteger({ + data: attributes.force, + defaultValue: 1, + validate: (n) => n === 0 + }); + this.from = attributes.from || ""; + this.to = attributes.to || ""; + } + }; + EquateRange = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "equateRange"); + this.from = attributes.from || ""; + this.to = attributes.to || ""; + this._unicodeRange = attributes.unicodeRange || ""; + } + get unicodeRange() { + const ranges = []; + const unicodeRegex = /U\+([0-9a-fA-F]+)/; + const unicodeRange = this._unicodeRange; + for (let range2 of unicodeRange.split(",").map((x) => x.trim()).filter((x) => !!x)) { + range2 = range2.split("-", 2).map((x) => { + const found = x.match(unicodeRegex); + if (!found) { + return 0; + } + return parseInt(found[1], 16); + }); + if (range2.length === 1) { + range2.push(range2[0]); + } + ranges.push(range2); + } + return shadow2(this, "unicodeRange", ranges); + } + }; + Exclude = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "exclude"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/).filter((x) => x && ["calculate", "close", "enter", "exit", "initialize", "ready", "validate"].includes(x)); + } + }; + ExcludeNS = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "excludeNS"); + } + }; + FlipLabel = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "flipLabel", ["usePrinterSetting", "on", "off"]); + } + }; + config_FontInfo = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "fontInfo", true); + this.embed = null; + this.map = null; + this.subsetBelow = null; + this.alwaysEmbed = new XFAObjectArray(); + this.defaultTypeface = new XFAObjectArray(); + this.neverEmbed = new XFAObjectArray(); + } + }; + FormFieldFilling = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "formFieldFilling"); + } + }; + GroupParent = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "groupParent"); + } + }; + IfEmpty = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ifEmpty", ["dataValue", "dataGroup", "ignore", "remove"]); + } + }; + IncludeXDPContent = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "includeXDPContent"); + } + }; + IncrementalLoad = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "incrementalLoad", ["none", "forwardOnly"]); + } + }; + IncrementalMerge = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "incrementalMerge"); + } + }; + Interactive = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "interactive"); + } + }; + Jog = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "jog", ["usePrinterSetting", "none", "pageSet"]); + } + }; + LabelPrinter = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "labelPrinter", true); + this.name = getStringOption(attributes.name, ["zpl", "dpl", "ipl", "tcpl"]); + this.batchOutput = null; + this.flipLabel = null; + this.fontInfo = null; + this.xdc = null; + } + }; + Layout = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "layout", ["paginate", "panel"]); + } + }; + Level = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "level", 0, (n) => n > 0); + } + }; + Linearized = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "linearized"); + } + }; + Locale = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "locale"); + } + }; + LocaleSet = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "localeSet"); + } + }; + Log = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "log", true); + this.mode = null; + this.threshold = null; + this.to = null; + this.uri = null; + } + }; + MapElement = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "map", true); + this.equate = new XFAObjectArray(); + this.equateRange = new XFAObjectArray(); + } + }; + MediumInfo = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "mediumInfo", true); + this.map = null; + } + }; + config_Message = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "message", true); + this.msgId = null; + this.severity = null; + } + }; + Messaging = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "messaging", true); + this.message = new XFAObjectArray(); + } + }; + Mode = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "mode", ["append", "overwrite"]); + } + }; + ModifyAnnots = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "modifyAnnots"); + } + }; + MsgId = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "msgId", 1, (n) => n >= 1); + } + }; + NameAttr = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "nameAttr"); + } + }; + NeverEmbed = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "neverEmbed"); + } + }; + NumberOfCopies = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "numberOfCopies", null, (n) => n >= 2 && n <= 5); + } + }; + OpenAction = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "openAction", true); + this.destination = null; + } + }; + Output = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "output", true); + this.to = null; + this.type = null; + this.uri = null; + } + }; + OutputBin = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "outputBin"); + } + }; + OutputXSL = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "outputXSL", true); + this.uri = null; + } + }; + Overprint = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "overprint", ["none", "both", "draw", "field"]); + } + }; + Packets = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "packets"); + } + [$finalize]() { + if (this[$content] === "*") { + return; + } + this[$content] = this[$content].trim().split(/\s+/).filter((x) => ["config", "datasets", "template", "xfdf", "xslt"].includes(x)); + } + }; + PageOffset = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pageOffset"); + this.x = getInteger({ + data: attributes.x, + defaultValue: "useXDCSetting", + validate: (n) => true + }); + this.y = getInteger({ + data: attributes.y, + defaultValue: "useXDCSetting", + validate: (n) => true + }); + } + }; + PageRange = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pageRange"); + } + [$finalize]() { + const numbers = this[$content].trim().split(/\s+/).map((x) => parseInt(x, 10)); + const ranges = []; + for (let i = 0, ii = numbers.length; i < ii; i += 2) { + ranges.push(numbers.slice(i, i + 2)); + } + this[$content] = ranges; + } + }; + Pagination = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pagination", ["simplex", "duplexShortEdge", "duplexLongEdge"]); + } + }; + PaginationOverride = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "paginationOverride", ["none", "forceDuplex", "forceDuplexLongEdge", "forceDuplexShortEdge", "forceSimplex"]); + } + }; + Part = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "part", 1, (n) => false); + } + }; + Pcl = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pcl", true); + this.name = attributes.name || ""; + this.batchOutput = null; + this.fontInfo = null; + this.jog = null; + this.mediumInfo = null; + this.outputBin = null; + this.pageOffset = null; + this.staple = null; + this.xdc = null; + } + }; + Pdf = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pdf", true); + this.name = attributes.name || ""; + this.adobeExtensionLevel = null; + this.batchOutput = null; + this.compression = null; + this.creator = null; + this.encryption = null; + this.fontInfo = null; + this.interactive = null; + this.linearized = null; + this.openAction = null; + this.pdfa = null; + this.producer = null; + this.renderPolicy = null; + this.scriptModel = null; + this.silentPrint = null; + this.submitFormat = null; + this.tagged = null; + this.version = null; + this.viewerPreferences = null; + this.xdc = null; + } + }; + Pdfa = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "pdfa", true); + this.amd = null; + this.conformance = null; + this.includeXDPContent = null; + this.part = null; + } + }; + Permissions = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "permissions", true); + this.accessibleContent = null; + this.change = null; + this.contentCopy = null; + this.documentAssembly = null; + this.formFieldFilling = null; + this.modifyAnnots = null; + this.plaintextMetadata = null; + this.print = null; + this.printHighQuality = null; + } + }; + PickTrayByPDFSize = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "pickTrayByPDFSize"); + } + }; + config_Picture = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "picture"); + } + }; + PlaintextMetadata = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "plaintextMetadata"); + } + }; + Presence = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "presence", ["preserve", "dissolve", "dissolveStructure", "ignore", "remove"]); + } + }; + Present = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "present", true); + this.behaviorOverride = null; + this.cache = null; + this.common = null; + this.copies = null; + this.destination = null; + this.incrementalMerge = null; + this.layout = null; + this.output = null; + this.overprint = null; + this.pagination = null; + this.paginationOverride = null; + this.script = null; + this.validate = null; + this.xdp = null; + this.driver = new XFAObjectArray(); + this.labelPrinter = new XFAObjectArray(); + this.pcl = new XFAObjectArray(); + this.pdf = new XFAObjectArray(); + this.ps = new XFAObjectArray(); + this.submitUrl = new XFAObjectArray(); + this.webClient = new XFAObjectArray(); + this.zpl = new XFAObjectArray(); + } + }; + Print = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "print"); + } + }; + PrintHighQuality = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "printHighQuality"); + } + }; + PrintScaling = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "printScaling", ["appdefault", "noScaling"]); + } + }; + PrinterName = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "printerName"); + } + }; + Producer = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "producer"); + } + }; + Ps = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "ps", true); + this.name = attributes.name || ""; + this.batchOutput = null; + this.fontInfo = null; + this.jog = null; + this.mediumInfo = null; + this.outputBin = null; + this.staple = null; + this.xdc = null; + } + }; + Range2 = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "range"); + } + [$finalize]() { + this[$content] = this[$content].split(",", 2).map((range2) => range2.split("-").map((x) => parseInt(x.trim(), 10))).filter((range2) => range2.every((x) => !isNaN(x))).map((range2) => { + if (range2.length === 1) { + range2.push(range2[0]); + } + return range2; + }); + } + }; + Record = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "record"); + } + [$finalize]() { + this[$content] = this[$content].trim(); + const n = parseInt(this[$content], 10); + if (!isNaN(n) && n >= 0) { + this[$content] = n; + } + } + }; + Relevant = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "relevant"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/); + } + }; + Rename = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "rename"); + } + [$finalize]() { + this[$content] = this[$content].trim(); + if (this[$content].toLowerCase().startsWith("xml") || new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u").test(this[$content])) { + warn2("XFA - Rename: invalid XFA name"); + } + } + }; + RenderPolicy = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "renderPolicy", ["server", "client"]); + } + }; + RunScripts = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "runScripts", ["both", "client", "none", "server"]); + } + }; + config_Script = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "script", true); + this.currentPage = null; + this.exclude = null; + this.runScripts = null; + } + }; + ScriptModel = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "scriptModel", ["XFA", "none"]); + } + }; + Severity = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "severity", ["ignore", "error", "information", "trace", "warning"]); + } + }; + SilentPrint = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "silentPrint", true); + this.addSilentPrint = null; + this.printerName = null; + } + }; + Staple = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "staple"); + this.mode = getStringOption(attributes.mode, ["usePrinterSetting", "on", "off"]); + } + }; + StartNode = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "startNode"); + } + }; + StartPage = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "startPage", 0, (n) => true); + } + }; + SubmitFormat = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "submitFormat", ["html", "delegate", "fdf", "xml", "pdf"]); + } + }; + SubmitUrl = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "submitUrl"); + } + }; + SubsetBelow = class extends IntegerObject { + constructor(attributes) { + super(CONFIG_NS_ID, "subsetBelow", 100, (n) => n >= 0 && n <= 100); + } + }; + SuppressBanner = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "suppressBanner"); + } + }; + Tagged = class extends Option01 { + constructor(attributes) { + super(CONFIG_NS_ID, "tagged"); + } + }; + config_Template = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "template", true); + this.base = null; + this.relevant = null; + this.startPage = null; + this.uri = null; + this.xsl = null; + } + }; + Threshold = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "threshold", ["trace", "error", "information", "warning"]); + } + }; + To = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "to", ["null", "memory", "stderr", "stdout", "system", "uri"]); + } + }; + TemplateCache = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "templateCache"); + this.maxEntries = getInteger({ + data: attributes.maxEntries, + defaultValue: 5, + validate: (n) => n >= 0 + }); + } + }; + Trace = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "trace", true); + this.area = new XFAObjectArray(); + } + }; + Transform = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "transform", true); + this.groupParent = null; + this.ifEmpty = null; + this.nameAttr = null; + this.picture = null; + this.presence = null; + this.rename = null; + this.whitespace = null; + } + }; + Type = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "type", ["none", "ascii85", "asciiHex", "ccittfax", "flate", "lzw", "runLength", "native", "xdp", "mergedXDP"]); + } + }; + Uri = class extends StringObject { + constructor(attributes) { + super(CONFIG_NS_ID, "uri"); + } + }; + config_Validate = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validate", ["preSubmit", "prePrint", "preExecute", "preSave"]); + } + }; + ValidateApprovalSignatures = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validateApprovalSignatures"); + } + [$finalize]() { + this[$content] = this[$content].trim().split(/\s+/).filter((x) => ["docReady", "postSign"].includes(x)); + } + }; + ValidationMessaging = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "validationMessaging", ["allMessagesIndividually", "allMessagesTogether", "firstMessageOnly", "noMessages"]); + } + }; + Version = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "version", ["1.7", "1.6", "1.5", "1.4", "1.3", "1.2"]); + } + }; + VersionControl = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "VersionControl"); + this.outputBelow = getStringOption(attributes.outputBelow, ["warn", "error", "update"]); + this.sourceAbove = getStringOption(attributes.sourceAbove, ["warn", "error"]); + this.sourceBelow = getStringOption(attributes.sourceBelow, ["update", "maintain"]); + } + }; + ViewerPreferences = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "viewerPreferences", true); + this.ADBE_JSConsole = null; + this.ADBE_JSDebugger = null; + this.addViewerPreferences = null; + this.duplexOption = null; + this.enforce = null; + this.numberOfCopies = null; + this.pageRange = null; + this.pickTrayByPDFSize = null; + this.printScaling = null; + } + }; + WebClient = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "webClient", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.fontInfo = null; + this.xdc = null; + } + }; + Whitespace = class extends OptionObject { + constructor(attributes) { + super(CONFIG_NS_ID, "whitespace", ["preserve", "ltrim", "normalize", "rtrim", "trim"]); + } + }; + Window = class extends ContentObject { + constructor(attributes) { + super(CONFIG_NS_ID, "window"); + } + [$finalize]() { + const pair = this[$content].split(",", 2).map((x) => parseInt(x.trim(), 10)); + if (pair.some((x) => isNaN(x))) { + this[$content] = [0, 0]; + return; + } + if (pair.length === 1) { + pair.push(pair[0]); + } + this[$content] = pair; + } + }; + Xdc = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xdc", true); + this.uri = new XFAObjectArray(); + this.xsl = new XFAObjectArray(); + } + }; + Xdp = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xdp", true); + this.packets = null; + } + }; + Xsl = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "xsl", true); + this.debug = null; + this.uri = null; + } + }; + Zpl = class extends XFAObject { + constructor(attributes) { + super(CONFIG_NS_ID, "zpl", true); + this.name = attributes.name ? attributes.name.trim() : ""; + this.batchOutput = null; + this.flipLabel = null; + this.fontInfo = null; + this.xdc = null; + } + }; + ConfigNamespace = class _ConfigNamespace { + static [$buildXFAObject](name, attributes) { + if (_ConfigNamespace.hasOwnProperty(name)) { + return _ConfigNamespace[name](attributes); + } + return void 0; + } + static acrobat(attrs) { + return new Acrobat(attrs); + } + static acrobat7(attrs) { + return new Acrobat7(attrs); + } + static ADBE_JSConsole(attrs) { + return new ADBE_JSConsole(attrs); + } + static ADBE_JSDebugger(attrs) { + return new ADBE_JSDebugger(attrs); + } + static addSilentPrint(attrs) { + return new AddSilentPrint(attrs); + } + static addViewerPreferences(attrs) { + return new AddViewerPreferences(attrs); + } + static adjustData(attrs) { + return new AdjustData(attrs); + } + static adobeExtensionLevel(attrs) { + return new AdobeExtensionLevel(attrs); + } + static agent(attrs) { + return new Agent(attrs); + } + static alwaysEmbed(attrs) { + return new AlwaysEmbed(attrs); + } + static amd(attrs) { + return new Amd(attrs); + } + static area(attrs) { + return new config_Area(attrs); + } + static attributes(attrs) { + return new Attributes(attrs); + } + static autoSave(attrs) { + return new AutoSave(attrs); + } + static base(attrs) { + return new Base(attrs); + } + static batchOutput(attrs) { + return new BatchOutput(attrs); + } + static behaviorOverride(attrs) { + return new BehaviorOverride(attrs); + } + static cache(attrs) { + return new Cache2(attrs); + } + static change(attrs) { + return new Change(attrs); + } + static common(attrs) { + return new Common(attrs); + } + static compress(attrs) { + return new Compress(attrs); + } + static compressLogicalStructure(attrs) { + return new CompressLogicalStructure(attrs); + } + static compressObjectStream(attrs) { + return new CompressObjectStream(attrs); + } + static compression(attrs) { + return new Compression(attrs); + } + static config(attrs) { + return new Config(attrs); + } + static conformance(attrs) { + return new Conformance(attrs); + } + static contentCopy(attrs) { + return new ContentCopy(attrs); + } + static copies(attrs) { + return new Copies(attrs); + } + static creator(attrs) { + return new Creator(attrs); + } + static currentPage(attrs) { + return new CurrentPage(attrs); + } + static data(attrs) { + return new Data(attrs); + } + static debug(attrs) { + return new Debug(attrs); + } + static defaultTypeface(attrs) { + return new DefaultTypeface(attrs); + } + static destination(attrs) { + return new Destination(attrs); + } + static documentAssembly(attrs) { + return new DocumentAssembly(attrs); + } + static driver(attrs) { + return new Driver(attrs); + } + static duplexOption(attrs) { + return new DuplexOption(attrs); + } + static dynamicRender(attrs) { + return new DynamicRender(attrs); + } + static embed(attrs) { + return new Embed(attrs); + } + static encrypt(attrs) { + return new config_Encrypt(attrs); + } + static encryption(attrs) { + return new config_Encryption(attrs); + } + static encryptionLevel(attrs) { + return new EncryptionLevel(attrs); + } + static enforce(attrs) { + return new Enforce(attrs); + } + static equate(attrs) { + return new Equate(attrs); + } + static equateRange(attrs) { + return new EquateRange(attrs); + } + static exclude(attrs) { + return new Exclude(attrs); + } + static excludeNS(attrs) { + return new ExcludeNS(attrs); + } + static flipLabel(attrs) { + return new FlipLabel(attrs); + } + static fontInfo(attrs) { + return new config_FontInfo(attrs); + } + static formFieldFilling(attrs) { + return new FormFieldFilling(attrs); + } + static groupParent(attrs) { + return new GroupParent(attrs); + } + static ifEmpty(attrs) { + return new IfEmpty(attrs); + } + static includeXDPContent(attrs) { + return new IncludeXDPContent(attrs); + } + static incrementalLoad(attrs) { + return new IncrementalLoad(attrs); + } + static incrementalMerge(attrs) { + return new IncrementalMerge(attrs); + } + static interactive(attrs) { + return new Interactive(attrs); + } + static jog(attrs) { + return new Jog(attrs); + } + static labelPrinter(attrs) { + return new LabelPrinter(attrs); + } + static layout(attrs) { + return new Layout(attrs); + } + static level(attrs) { + return new Level(attrs); + } + static linearized(attrs) { + return new Linearized(attrs); + } + static locale(attrs) { + return new Locale(attrs); + } + static localeSet(attrs) { + return new LocaleSet(attrs); + } + static log(attrs) { + return new Log(attrs); + } + static map(attrs) { + return new MapElement(attrs); + } + static mediumInfo(attrs) { + return new MediumInfo(attrs); + } + static message(attrs) { + return new config_Message(attrs); + } + static messaging(attrs) { + return new Messaging(attrs); + } + static mode(attrs) { + return new Mode(attrs); + } + static modifyAnnots(attrs) { + return new ModifyAnnots(attrs); + } + static msgId(attrs) { + return new MsgId(attrs); + } + static nameAttr(attrs) { + return new NameAttr(attrs); + } + static neverEmbed(attrs) { + return new NeverEmbed(attrs); + } + static numberOfCopies(attrs) { + return new NumberOfCopies(attrs); + } + static openAction(attrs) { + return new OpenAction(attrs); + } + static output(attrs) { + return new Output(attrs); + } + static outputBin(attrs) { + return new OutputBin(attrs); + } + static outputXSL(attrs) { + return new OutputXSL(attrs); + } + static overprint(attrs) { + return new Overprint(attrs); + } + static packets(attrs) { + return new Packets(attrs); + } + static pageOffset(attrs) { + return new PageOffset(attrs); + } + static pageRange(attrs) { + return new PageRange(attrs); + } + static pagination(attrs) { + return new Pagination(attrs); + } + static paginationOverride(attrs) { + return new PaginationOverride(attrs); + } + static part(attrs) { + return new Part(attrs); + } + static pcl(attrs) { + return new Pcl(attrs); + } + static pdf(attrs) { + return new Pdf(attrs); + } + static pdfa(attrs) { + return new Pdfa(attrs); + } + static permissions(attrs) { + return new Permissions(attrs); + } + static pickTrayByPDFSize(attrs) { + return new PickTrayByPDFSize(attrs); + } + static picture(attrs) { + return new config_Picture(attrs); + } + static plaintextMetadata(attrs) { + return new PlaintextMetadata(attrs); + } + static presence(attrs) { + return new Presence(attrs); + } + static present(attrs) { + return new Present(attrs); + } + static print(attrs) { + return new Print(attrs); + } + static printHighQuality(attrs) { + return new PrintHighQuality(attrs); + } + static printScaling(attrs) { + return new PrintScaling(attrs); + } + static printerName(attrs) { + return new PrinterName(attrs); + } + static producer(attrs) { + return new Producer(attrs); + } + static ps(attrs) { + return new Ps(attrs); + } + static range(attrs) { + return new Range2(attrs); + } + static record(attrs) { + return new Record(attrs); + } + static relevant(attrs) { + return new Relevant(attrs); + } + static rename(attrs) { + return new Rename(attrs); + } + static renderPolicy(attrs) { + return new RenderPolicy(attrs); + } + static runScripts(attrs) { + return new RunScripts(attrs); + } + static script(attrs) { + return new config_Script(attrs); + } + static scriptModel(attrs) { + return new ScriptModel(attrs); + } + static severity(attrs) { + return new Severity(attrs); + } + static silentPrint(attrs) { + return new SilentPrint(attrs); + } + static staple(attrs) { + return new Staple(attrs); + } + static startNode(attrs) { + return new StartNode(attrs); + } + static startPage(attrs) { + return new StartPage(attrs); + } + static submitFormat(attrs) { + return new SubmitFormat(attrs); + } + static submitUrl(attrs) { + return new SubmitUrl(attrs); + } + static subsetBelow(attrs) { + return new SubsetBelow(attrs); + } + static suppressBanner(attrs) { + return new SuppressBanner(attrs); + } + static tagged(attrs) { + return new Tagged(attrs); + } + static template(attrs) { + return new config_Template(attrs); + } + static templateCache(attrs) { + return new TemplateCache(attrs); + } + static threshold(attrs) { + return new Threshold(attrs); + } + static to(attrs) { + return new To(attrs); + } + static trace(attrs) { + return new Trace(attrs); + } + static transform(attrs) { + return new Transform(attrs); + } + static type(attrs) { + return new Type(attrs); + } + static uri(attrs) { + return new Uri(attrs); + } + static validate(attrs) { + return new config_Validate(attrs); + } + static validateApprovalSignatures(attrs) { + return new ValidateApprovalSignatures(attrs); + } + static validationMessaging(attrs) { + return new ValidationMessaging(attrs); + } + static version(attrs) { + return new Version(attrs); + } + static versionControl(attrs) { + return new VersionControl(attrs); + } + static viewerPreferences(attrs) { + return new ViewerPreferences(attrs); + } + static webClient(attrs) { + return new WebClient(attrs); + } + static whitespace(attrs) { + return new Whitespace(attrs); + } + static window(attrs) { + return new Window(attrs); + } + static xdc(attrs) { + return new Xdc(attrs); + } + static xdp(attrs) { + return new Xdp(attrs); + } + static xsl(attrs) { + return new Xsl(attrs); + } + static zpl(attrs) { + return new Zpl(attrs); + } + }; + CONNECTION_SET_NS_ID = NamespaceIds.connectionSet.id; + ConnectionSet = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "connectionSet", true); + this.wsdlConnection = new XFAObjectArray(); + this.xmlConnection = new XFAObjectArray(); + this.xsdConnection = new XFAObjectArray(); + } + }; + EffectiveInputPolicy = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "effectiveInputPolicy"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + EffectiveOutputPolicy = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "effectiveOutputPolicy"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + Operation = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "operation"); + this.id = attributes.id || ""; + this.input = attributes.input || ""; + this.name = attributes.name || ""; + this.output = attributes.output || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + RootElement = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "rootElement"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + SoapAction = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "soapAction"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + SoapAddress = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "soapAddress"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + connection_set_Uri = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "uri"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + WsdlAddress = class extends StringObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "wsdlAddress"); + this.id = attributes.id || ""; + this.name = attributes.name || ""; + this.use = attributes.use || ""; + this.usehref = attributes.usehref || ""; + } + }; + WsdlConnection = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "wsdlConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.effectiveInputPolicy = null; + this.effectiveOutputPolicy = null; + this.operation = null; + this.soapAction = null; + this.soapAddress = null; + this.wsdlAddress = null; + } + }; + XmlConnection = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "xmlConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.uri = null; + } + }; + XsdConnection = class extends XFAObject { + constructor(attributes) { + super(CONNECTION_SET_NS_ID, "xsdConnection", true); + this.dataDescription = attributes.dataDescription || ""; + this.name = attributes.name || ""; + this.rootElement = null; + this.uri = null; + } + }; + ConnectionSetNamespace = class _ConnectionSetNamespace { + static [$buildXFAObject](name, attributes) { + if (_ConnectionSetNamespace.hasOwnProperty(name)) { + return _ConnectionSetNamespace[name](attributes); + } + return void 0; + } + static connectionSet(attrs) { + return new ConnectionSet(attrs); + } + static effectiveInputPolicy(attrs) { + return new EffectiveInputPolicy(attrs); + } + static effectiveOutputPolicy(attrs) { + return new EffectiveOutputPolicy(attrs); + } + static operation(attrs) { + return new Operation(attrs); + } + static rootElement(attrs) { + return new RootElement(attrs); + } + static soapAction(attrs) { + return new SoapAction(attrs); + } + static soapAddress(attrs) { + return new SoapAddress(attrs); + } + static uri(attrs) { + return new connection_set_Uri(attrs); + } + static wsdlAddress(attrs) { + return new WsdlAddress(attrs); + } + static wsdlConnection(attrs) { + return new WsdlConnection(attrs); + } + static xmlConnection(attrs) { + return new XmlConnection(attrs); + } + static xsdConnection(attrs) { + return new XsdConnection(attrs); + } + }; + DATASETS_NS_ID = NamespaceIds.datasets.id; + datasets_Data = class extends XmlObject { + constructor(attributes) { + super(DATASETS_NS_ID, "data", attributes); + } + [$isNsAgnostic]() { + return true; + } + }; + Datasets = class extends XFAObject { + constructor(attributes) { + super(DATASETS_NS_ID, "datasets", true); + this.data = null; + this.Signature = null; + } + [$onChild](child) { + const name = child[$nodeName]; + if (name === "data" && child[$namespaceId] === DATASETS_NS_ID || name === "Signature" && child[$namespaceId] === NamespaceIds.signature.id) { + this[name] = child; + } + this[$appendChild](child); + } + }; + DatasetsNamespace = class _DatasetsNamespace { + static [$buildXFAObject](name, attributes) { + if (_DatasetsNamespace.hasOwnProperty(name)) { + return _DatasetsNamespace[name](attributes); + } + return void 0; + } + static datasets(attributes) { + return new Datasets(attributes); + } + static data(attributes) { + return new datasets_Data(attributes); + } + }; + LOCALE_SET_NS_ID = NamespaceIds.localeSet.id; + CalendarSymbols = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "calendarSymbols", true); + this.name = "gregorian"; + this.dayNames = new XFAObjectArray(2); + this.eraNames = null; + this.meridiemNames = null; + this.monthNames = new XFAObjectArray(2); + } + }; + CurrencySymbol = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "currencySymbol"); + this.name = getStringOption(attributes.name, ["symbol", "isoname", "decimal"]); + } + }; + CurrencySymbols = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "currencySymbols", true); + this.currencySymbol = new XFAObjectArray(3); + } + }; + DatePattern = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "datePattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } + }; + DatePatterns = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "datePatterns", true); + this.datePattern = new XFAObjectArray(4); + } + }; + DateTimeSymbols = class extends ContentObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "dateTimeSymbols"); + } + }; + Day = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "day"); + } + }; + DayNames = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "dayNames", true); + this.abbr = getInteger({ + data: attributes.abbr, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.day = new XFAObjectArray(7); + } + }; + Era = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "era"); + } + }; + EraNames = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "eraNames", true); + this.era = new XFAObjectArray(2); + } + }; + locale_set_Locale = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "locale", true); + this.desc = attributes.desc || ""; + this.name = "isoname"; + this.calendarSymbols = null; + this.currencySymbols = null; + this.datePatterns = null; + this.dateTimeSymbols = null; + this.numberPatterns = null; + this.numberSymbols = null; + this.timePatterns = null; + this.typeFaces = null; + } + }; + locale_set_LocaleSet = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "localeSet", true); + this.locale = new XFAObjectArray(); + } + }; + Meridiem = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "meridiem"); + } + }; + MeridiemNames = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "meridiemNames", true); + this.meridiem = new XFAObjectArray(2); + } + }; + Month = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "month"); + } + }; + MonthNames = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "monthNames", true); + this.abbr = getInteger({ + data: attributes.abbr, + defaultValue: 0, + validate: (x) => x === 1 + }); + this.month = new XFAObjectArray(12); + } + }; + NumberPattern = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberPattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } + }; + NumberPatterns = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberPatterns", true); + this.numberPattern = new XFAObjectArray(4); + } + }; + NumberSymbol = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberSymbol"); + this.name = getStringOption(attributes.name, ["decimal", "grouping", "percent", "minus", "zero"]); + } + }; + NumberSymbols = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "numberSymbols", true); + this.numberSymbol = new XFAObjectArray(5); + } + }; + TimePattern = class extends StringObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "timePattern"); + this.name = getStringOption(attributes.name, ["full", "long", "med", "short"]); + } + }; + TimePatterns = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "timePatterns", true); + this.timePattern = new XFAObjectArray(4); + } + }; + TypeFace = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "typeFace", true); + this.name = attributes.name | ""; + } + }; + TypeFaces = class extends XFAObject { + constructor(attributes) { + super(LOCALE_SET_NS_ID, "typeFaces", true); + this.typeFace = new XFAObjectArray(); + } + }; + LocaleSetNamespace = class _LocaleSetNamespace { + static [$buildXFAObject](name, attributes) { + if (_LocaleSetNamespace.hasOwnProperty(name)) { + return _LocaleSetNamespace[name](attributes); + } + return void 0; + } + static calendarSymbols(attrs) { + return new CalendarSymbols(attrs); + } + static currencySymbol(attrs) { + return new CurrencySymbol(attrs); + } + static currencySymbols(attrs) { + return new CurrencySymbols(attrs); + } + static datePattern(attrs) { + return new DatePattern(attrs); + } + static datePatterns(attrs) { + return new DatePatterns(attrs); + } + static dateTimeSymbols(attrs) { + return new DateTimeSymbols(attrs); + } + static day(attrs) { + return new Day(attrs); + } + static dayNames(attrs) { + return new DayNames(attrs); + } + static era(attrs) { + return new Era(attrs); + } + static eraNames(attrs) { + return new EraNames(attrs); + } + static locale(attrs) { + return new locale_set_Locale(attrs); + } + static localeSet(attrs) { + return new locale_set_LocaleSet(attrs); + } + static meridiem(attrs) { + return new Meridiem(attrs); + } + static meridiemNames(attrs) { + return new MeridiemNames(attrs); + } + static month(attrs) { + return new Month(attrs); + } + static monthNames(attrs) { + return new MonthNames(attrs); + } + static numberPattern(attrs) { + return new NumberPattern(attrs); + } + static numberPatterns(attrs) { + return new NumberPatterns(attrs); + } + static numberSymbol(attrs) { + return new NumberSymbol(attrs); + } + static numberSymbols(attrs) { + return new NumberSymbols(attrs); + } + static timePattern(attrs) { + return new TimePattern(attrs); + } + static timePatterns(attrs) { + return new TimePatterns(attrs); + } + static typeFace(attrs) { + return new TypeFace(attrs); + } + static typeFaces(attrs) { + return new TypeFaces(attrs); + } + }; + SIGNATURE_NS_ID = NamespaceIds.signature.id; + signature_Signature = class extends XFAObject { + constructor(attributes) { + super(SIGNATURE_NS_ID, "signature", true); + } + }; + SignatureNamespace = class _SignatureNamespace { + static [$buildXFAObject](name, attributes) { + if (_SignatureNamespace.hasOwnProperty(name)) { + return _SignatureNamespace[name](attributes); + } + return void 0; + } + static signature(attributes) { + return new signature_Signature(attributes); + } + }; + STYLESHEET_NS_ID = NamespaceIds.stylesheet.id; + Stylesheet = class extends XFAObject { + constructor(attributes) { + super(STYLESHEET_NS_ID, "stylesheet", true); + } + }; + StylesheetNamespace = class _StylesheetNamespace { + static [$buildXFAObject](name, attributes) { + if (_StylesheetNamespace.hasOwnProperty(name)) { + return _StylesheetNamespace[name](attributes); + } + return void 0; + } + static stylesheet(attributes) { + return new Stylesheet(attributes); + } + }; + XDP_NS_ID = NamespaceIds.xdp.id; + xdp_Xdp = class extends XFAObject { + constructor(attributes) { + super(XDP_NS_ID, "xdp", true); + this.uuid = attributes.uuid || ""; + this.timeStamp = attributes.timeStamp || ""; + this.config = null; + this.connectionSet = null; + this.datasets = null; + this.localeSet = null; + this.stylesheet = new XFAObjectArray(); + this.template = null; + } + [$onChildCheck](child) { + const ns = NamespaceIds[child[$nodeName]]; + return ns && child[$namespaceId] === ns.id; + } + }; + XdpNamespace = class _XdpNamespace { + static [$buildXFAObject](name, attributes) { + if (_XdpNamespace.hasOwnProperty(name)) { + return _XdpNamespace[name](attributes); + } + return void 0; + } + static xdp(attributes) { + return new xdp_Xdp(attributes); + } + }; + XHTML_NS_ID = NamespaceIds.xhtml.id; + $richText = Symbol(); + VALID_STYLES = /* @__PURE__ */ new Set(["color", "font", "font-family", "font-size", "font-stretch", "font-style", "font-weight", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "letter-spacing", "line-height", "orphans", "page-break-after", "page-break-before", "page-break-inside", "tab-interval", "tab-stop", "text-align", "text-decoration", "text-indent", "vertical-align", "widows", "kerning-mode", "xfa-font-horizontal-scale", "xfa-font-vertical-scale", "xfa-spacerun", "xfa-tab-stops"]); + StyleMapping = /* @__PURE__ */ new Map([["page-break-after", "breakAfter"], ["page-break-before", "breakBefore"], ["page-break-inside", "breakInside"], ["kerning-mode", (value) => value === "none" ? "none" : "normal"], ["xfa-font-horizontal-scale", (value) => `scaleX(${Math.max(0, parseInt(value) / 100).toFixed(2)})`], ["xfa-font-vertical-scale", (value) => `scaleY(${Math.max(0, parseInt(value) / 100).toFixed(2)})`], ["xfa-spacerun", ""], ["xfa-tab-stops", ""], ["font-size", (value, original) => { + value = original.fontSize = Math.abs(getMeasurement(value)); + return measureToString(0.99 * value); + }], ["letter-spacing", (value) => measureToString(getMeasurement(value))], ["line-height", (value) => measureToString(getMeasurement(value))], ["margin", (value) => measureToString(getMeasurement(value))], ["margin-bottom", (value) => measureToString(getMeasurement(value))], ["margin-left", (value) => measureToString(getMeasurement(value))], ["margin-right", (value) => measureToString(getMeasurement(value))], ["margin-top", (value) => measureToString(getMeasurement(value))], ["text-indent", (value) => measureToString(getMeasurement(value))], ["font-family", (value) => value], ["vertical-align", (value) => measureToString(getMeasurement(value))]]); + spacesRegExp = /\s+/g; + crlfRegExp = /[\r\n]+/g; + crlfForRichTextRegExp = /\r\n?/g; + NoWhites = /* @__PURE__ */ new Set(["body", "html"]); + XhtmlObject = class extends XmlObject { + constructor(attributes, name) { + super(XHTML_NS_ID, name); + this[$richText] = false; + this.style = attributes.style || ""; + } + [$clean](builder) { + super[$clean](builder); + this.style = checkStyle(this); + } + [$acceptWhitespace]() { + return !NoWhites.has(this[$nodeName]); + } + [$onText](str, richText = false) { + if (!richText) { + str = str.replaceAll(crlfRegExp, ""); + if (!this.style.includes("xfa-spacerun:yes")) { + str = str.replaceAll(spacesRegExp, " "); + } + } else { + this[$richText] = true; + } + if (str) { + this[$content] += str; + } + } + [$pushGlyphs](measure, mustPop = true) { + const xfaFont = /* @__PURE__ */ Object.create(null); + const margin = { + top: NaN, + bottom: NaN, + left: NaN, + right: NaN + }; + let lineHeight = null; + for (const [key, value] of this.style.split(";").map((s) => s.split(":", 2))) { + switch (key) { + case "font-family": + xfaFont.typeface = stripQuotes(value); + break; + case "font-size": + xfaFont.size = getMeasurement(value); + break; + case "font-weight": + xfaFont.weight = value; + break; + case "font-style": + xfaFont.posture = value; + break; + case "letter-spacing": + xfaFont.letterSpacing = getMeasurement(value); + break; + case "margin": + const values3 = value.split(/ \t/).map((x) => getMeasurement(x)); + switch (values3.length) { + case 1: + margin.top = margin.bottom = margin.left = margin.right = values3[0]; + break; + case 2: + margin.top = margin.bottom = values3[0]; + margin.left = margin.right = values3[1]; + break; + case 3: + margin.top = values3[0]; + margin.bottom = values3[2]; + margin.left = margin.right = values3[1]; + break; + case 4: + margin.top = values3[0]; + margin.left = values3[1]; + margin.bottom = values3[2]; + margin.right = values3[3]; + break; + } + break; + case "margin-top": + margin.top = getMeasurement(value); + break; + case "margin-bottom": + margin.bottom = getMeasurement(value); + break; + case "margin-left": + margin.left = getMeasurement(value); + break; + case "margin-right": + margin.right = getMeasurement(value); + break; + case "line-height": + lineHeight = getMeasurement(value); + break; + } + } + measure.pushData(xfaFont, margin, lineHeight); + if (this[$content]) { + measure.addString(this[$content]); + } else { + for (const child of this[$getChildren]()) { + if (child[$nodeName] === "#text") { + measure.addString(child[$content]); + continue; + } + child[$pushGlyphs](measure); + } + } + if (mustPop) { + measure.popFont(); + } + } + [$toHTML](availableSpace) { + const children = []; + this[$extra] = { + children + }; + this[$childrenToHTML]({}); + if (children.length === 0 && !this[$content]) { + return HTMLResult.EMPTY; + } + let value; + if (this[$richText]) { + value = this[$content] ? this[$content].replaceAll(crlfForRichTextRegExp, "\n") : void 0; + } else { + value = this[$content] || void 0; + } + return HTMLResult.success({ + name: this[$nodeName], + attributes: { + href: this.href, + style: mapStyle(this.style, this, this[$richText]) + }, + children, + value + }); + } + }; + A = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "a"); + this.href = fixURL(attributes.href) || ""; + } + }; + B = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "b"); + } + [$pushGlyphs](measure) { + measure.pushFont({ + weight: "bold" + }); + super[$pushGlyphs](measure); + measure.popFont(); + } + }; + Body = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "body"); + } + [$toHTML](availableSpace) { + const res = super[$toHTML](availableSpace); + const { + html + } = res; + if (!html) { + return HTMLResult.EMPTY; + } + html.name = "div"; + html.attributes.class = ["xfaRich"]; + return res; + } + }; + Br = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "br"); + } + [$text]() { + return "\n"; + } + [$pushGlyphs](measure) { + measure.addString("\n"); + } + [$toHTML](availableSpace) { + return HTMLResult.success({ + name: "br" + }); + } + }; + Html = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "html"); + } + [$toHTML](availableSpace) { + const children = []; + this[$extra] = { + children + }; + this[$childrenToHTML]({}); + if (children.length === 0) { + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: {} + }, + value: this[$content] || "" + }); + } + if (children.length === 1) { + const child = children[0]; + if (child.attributes?.class.includes("xfaRich")) { + return HTMLResult.success(child); + } + } + return HTMLResult.success({ + name: "div", + attributes: { + class: ["xfaRich"], + style: {} + }, + children + }); + } + }; + I = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "i"); + } + [$pushGlyphs](measure) { + measure.pushFont({ + posture: "italic" + }); + super[$pushGlyphs](measure); + measure.popFont(); + } + }; + Li = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "li"); + } + }; + Ol = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "ol"); + } + }; + P = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "p"); + } + [$pushGlyphs](measure) { + super[$pushGlyphs](measure, false); + measure.addString("\n"); + measure.addPara(); + measure.popFont(); + } + [$text]() { + const siblings = this[$getParent]()[$getChildren](); + if (siblings.at(-1) === this) { + return super[$text](); + } + return super[$text]() + "\n"; + } + }; + Span = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "span"); + } + }; + Sub = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "sub"); + } + }; + Sup = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "sup"); + } + }; + Ul = class extends XhtmlObject { + constructor(attributes) { + super(attributes, "ul"); + } + }; + XhtmlNamespace = class _XhtmlNamespace { + static [$buildXFAObject](name, attributes) { + if (_XhtmlNamespace.hasOwnProperty(name)) { + return _XhtmlNamespace[name](attributes); + } + return void 0; + } + static a(attributes) { + return new A(attributes); + } + static b(attributes) { + return new B(attributes); + } + static body(attributes) { + return new Body(attributes); + } + static br(attributes) { + return new Br(attributes); + } + static html(attributes) { + return new Html(attributes); + } + static i(attributes) { + return new I(attributes); + } + static li(attributes) { + return new Li(attributes); + } + static ol(attributes) { + return new Ol(attributes); + } + static p(attributes) { + return new P(attributes); + } + static span(attributes) { + return new Span(attributes); + } + static sub(attributes) { + return new Sub(attributes); + } + static sup(attributes) { + return new Sup(attributes); + } + static ul(attributes) { + return new Ul(attributes); + } + }; + NamespaceSetUp = { + config: ConfigNamespace, + connection: ConnectionSetNamespace, + datasets: DatasetsNamespace, + localeSet: LocaleSetNamespace, + signature: SignatureNamespace, + stylesheet: StylesheetNamespace, + template: TemplateNamespace, + xdp: XdpNamespace, + xhtml: XhtmlNamespace + }; + UnknownNamespace = class { + constructor(nsId) { + this.namespaceId = nsId; + } + [$buildXFAObject](name, attributes) { + return new XmlObject(this.namespaceId, name, attributes); + } + }; + Root = class extends XFAObject { + constructor(ids) { + super(-1, "root", /* @__PURE__ */ Object.create(null)); + this.element = null; + this[$ids] = ids; + } + [$onChild](child) { + this.element = child; + return true; + } + [$finalize]() { + super[$finalize](); + if (this.element.template instanceof Template) { + this[$ids].set($root, this.element); + this.element.template[$resolvePrototypes](this[$ids]); + this.element.template[$ids] = this[$ids]; + } + } + }; + Empty = class extends XFAObject { + constructor() { + super(-1, "", /* @__PURE__ */ Object.create(null)); + } + [$onChild](_3) { + return false; + } + }; + Builder2 = class { + constructor(rootNameSpace = null) { + this._namespaceStack = []; + this._nsAgnosticLevel = 0; + this._namespacePrefixes = /* @__PURE__ */ new Map(); + this._namespaces = /* @__PURE__ */ new Map(); + this._nextNsId = Math.max(...Object.values(NamespaceIds).map(({ + id + }) => id)); + this._currentNamespace = rootNameSpace || new UnknownNamespace(++this._nextNsId); + } + buildRoot(ids) { + return new Root(ids); + } + build({ + nsPrefix, + name, + attributes, + namespace, + prefixes + }) { + const hasNamespaceDef = namespace !== null; + if (hasNamespaceDef) { + this._namespaceStack.push(this._currentNamespace); + this._currentNamespace = this._searchNamespace(namespace); + } + if (prefixes) { + this._addNamespacePrefix(prefixes); + } + if (attributes.hasOwnProperty($nsAttributes)) { + const dataTemplate = NamespaceSetUp.datasets; + const nsAttrs = attributes[$nsAttributes]; + let xfaAttrs = null; + for (const [ns, attrs] of Object.entries(nsAttrs)) { + const nsToUse = this._getNamespaceToUse(ns); + if (nsToUse === dataTemplate) { + xfaAttrs = { + xfa: attrs + }; + break; + } + } + if (xfaAttrs) { + attributes[$nsAttributes] = xfaAttrs; + } else { + delete attributes[$nsAttributes]; + } + } + const namespaceToUse = this._getNamespaceToUse(nsPrefix); + const node2 = namespaceToUse?.[$buildXFAObject](name, attributes) || new Empty(); + if (node2[$isNsAgnostic]()) { + this._nsAgnosticLevel++; + } + if (hasNamespaceDef || prefixes || node2[$isNsAgnostic]()) { + node2[$cleanup] = { + hasNamespace: hasNamespaceDef, + prefixes, + nsAgnostic: node2[$isNsAgnostic]() + }; + } + return node2; + } + isNsAgnostic() { + return this._nsAgnosticLevel > 0; + } + _searchNamespace(nsName) { + let ns = this._namespaces.get(nsName); + if (ns) { + return ns; + } + for (const [name, { + check: check3 + }] of Object.entries(NamespaceIds)) { + if (check3(nsName)) { + ns = NamespaceSetUp[name]; + if (ns) { + this._namespaces.set(nsName, ns); + return ns; + } + break; + } + } + ns = new UnknownNamespace(++this._nextNsId); + this._namespaces.set(nsName, ns); + return ns; + } + _addNamespacePrefix(prefixes) { + for (const { + prefix, + value + } of prefixes) { + const namespace = this._searchNamespace(value); + let prefixStack = this._namespacePrefixes.get(prefix); + if (!prefixStack) { + prefixStack = []; + this._namespacePrefixes.set(prefix, prefixStack); + } + prefixStack.push(namespace); + } + } + _getNamespaceToUse(prefix) { + if (!prefix) { + return this._currentNamespace; + } + const prefixStack = this._namespacePrefixes.get(prefix); + if (prefixStack?.length > 0) { + return prefixStack.at(-1); + } + warn2(`Unknown namespace prefix: ${prefix}.`); + return null; + } + clean(data) { + const { + hasNamespace, + prefixes, + nsAgnostic + } = data; + if (hasNamespace) { + this._currentNamespace = this._namespaceStack.pop(); + } + if (prefixes) { + prefixes.forEach(({ + prefix + }) => { + this._namespacePrefixes.get(prefix).pop(); + }); + } + if (nsAgnostic) { + this._nsAgnosticLevel--; + } + } + }; + XFAParser = class _XFAParser extends XMLParserBase { + constructor(rootNameSpace = null, richText = false) { + super(); + this._builder = new Builder2(rootNameSpace); + this._stack = []; + this._globalData = { + usedTypefaces: /* @__PURE__ */ new Set() + }; + this._ids = /* @__PURE__ */ new Map(); + this._current = this._builder.buildRoot(this._ids); + this._errorCode = XMLParserErrorCode.NoError; + this._whiteRegex = /^\s+$/; + this._nbsps = /\xa0+/g; + this._richText = richText; + } + parse(data) { + this.parseXml(data); + if (this._errorCode !== XMLParserErrorCode.NoError) { + return void 0; + } + this._current[$finalize](); + return this._current.element; + } + onText(text2) { + text2 = text2.replace(this._nbsps, (match) => match.slice(1) + " "); + if (this._richText || this._current[$acceptWhitespace]()) { + this._current[$onText](text2, this._richText); + return; + } + if (this._whiteRegex.test(text2)) { + return; + } + this._current[$onText](text2.trim()); + } + onCdata(text2) { + this._current[$onText](text2); + } + _mkAttributes(attributes, tagName) { + let namespace = null; + let prefixes = null; + const attributeObj = /* @__PURE__ */ Object.create({}); + for (const { + name, + value + } of attributes) { + if (name === "xmlns") { + if (!namespace) { + namespace = value; + } else { + warn2(`XFA - multiple namespace definition in <${tagName}>`); + } + } else if (name.startsWith("xmlns:")) { + const prefix = name.substring("xmlns:".length); + prefixes ??= []; + prefixes.push({ + prefix, + value + }); + } else { + const i = name.indexOf(":"); + if (i === -1) { + attributeObj[name] = value; + } else { + const nsAttrs = attributeObj[$nsAttributes] ??= /* @__PURE__ */ Object.create(null); + const [ns, attrName] = [name.slice(0, i), name.slice(i + 1)]; + const attrs = nsAttrs[ns] ||= /* @__PURE__ */ Object.create(null); + attrs[attrName] = value; + } + } + } + return [namespace, prefixes, attributeObj]; + } + _getNameAndPrefix(name, nsAgnostic) { + const i = name.indexOf(":"); + if (i === -1) { + return [name, null]; + } + return [name.substring(i + 1), nsAgnostic ? "" : name.substring(0, i)]; + } + onBeginElement(tagName, attributes, isEmpty2) { + const [namespace, prefixes, attributesObj] = this._mkAttributes(attributes, tagName); + const [name, nsPrefix] = this._getNameAndPrefix(tagName, this._builder.isNsAgnostic()); + const node2 = this._builder.build({ + nsPrefix, + name, + attributes: attributesObj, + namespace, + prefixes + }); + node2[$globalData] = this._globalData; + if (isEmpty2) { + node2[$finalize](); + if (this._current[$onChild](node2)) { + node2[$setId](this._ids); + } + node2[$clean](this._builder); + return; + } + this._stack.push(this._current); + this._current = node2; + } + onEndElement(name) { + const node2 = this._current; + if (node2[$isCDATAXml]() && typeof node2[$content] === "string") { + const parser = new _XFAParser(); + parser._globalData = this._globalData; + const root2 = parser.parse(node2[$content]); + node2[$content] = null; + node2[$onChild](root2); + } + node2[$finalize](); + this._current = this._stack.pop(); + if (this._current[$onChild](node2)) { + node2[$setId](this._ids); + } + node2[$clean](this._builder); + } + onError(code) { + this._errorCode = code; + } + }; + XFAFactory = class _XFAFactory { + constructor(data) { + try { + this.root = new XFAParser().parse(_XFAFactory._createDocument(data)); + const binder = new Binder(this.root); + this.form = binder.bind(); + this.dataHandler = new DataHandler(this.root, binder.getData()); + this.form[$globalData].template = this.form; + } catch (e) { + warn2(`XFA - an error occurred during parsing and binding: ${e}`); + } + } + isValid() { + return !!(this.root && this.form); + } + _createPagesHelper() { + const iterator = this.form[$toPages](); + return new Promise((resolve2, reject2) => { + const nextIteration = () => { + try { + const value = iterator.next(); + if (value.done) { + resolve2(value.value); + } else { + setTimeout(nextIteration, 0); + } + } catch (e) { + reject2(e); + } + }; + setTimeout(nextIteration, 0); + }); + } + async _createPages() { + try { + this.pages = await this._createPagesHelper(); + this.dims = this.pages.children.map((c) => { + const { + width, + height + } = c.attributes.style; + return [0, 0, parseInt(width), parseInt(height)]; + }); + } catch (e) { + warn2(`XFA - an error occurred during layout: ${e}`); + } + } + getBoundingBox(pageIndex) { + return this.dims[pageIndex]; + } + async getNumPages() { + if (!this.pages) { + await this._createPages(); + } + return this.dims.length; + } + setImages(images) { + this.form[$globalData].images = images; + } + setFonts(fonts) { + this.form[$globalData].fontFinder = new FontFinder(fonts); + const missingFonts = []; + for (let typeface of this.form[$globalData].usedTypefaces) { + typeface = stripQuotes(typeface); + const font = this.form[$globalData].fontFinder.find(typeface); + if (!font) { + missingFonts.push(typeface); + } + } + if (missingFonts.length > 0) { + return missingFonts; + } + return null; + } + appendFonts(fonts, reallyMissingFonts) { + this.form[$globalData].fontFinder.add(fonts, reallyMissingFonts); + } + async getPages() { + if (!this.pages) { + await this._createPages(); + } + const pages = this.pages; + this.pages = null; + return pages; + } + serializeData(storage2) { + return this.dataHandler.serialize(storage2); + } + static _createDocument(data) { + if (!data["/xdp:xdp"]) { + return data["xdp:xdp"]; + } + return Object.values(data).join(""); + } + static getRichTextAsHtml(rc) { + if (!rc || typeof rc !== "string") { + return null; + } + try { + let root2 = new XFAParser(XhtmlNamespace, true).parse(rc); + if (!["body", "xhtml"].includes(root2[$nodeName])) { + const newRoot = XhtmlNamespace.body({}); + newRoot[$appendChild](root2); + root2 = newRoot; + } + const result2 = root2[$toHTML](); + if (!result2.success) { + return null; + } + const { + html + } = result2; + const { + attributes + } = html; + if (attributes) { + if (attributes.class) { + attributes.class = attributes.class.filter((attr) => !attr.startsWith("xfa")); + } + attributes.dir = "auto"; + } + return { + html, + str: root2[$text]() + }; + } catch (e) { + warn2(`XFA - an error occurred during parsing of rich text: ${e}`); + } + return null; + } + }; + AnnotationFactory = class { + static createGlobals(pdfManager) { + return Promise.all([pdfManager.ensureCatalog("acroForm"), pdfManager.ensureDoc("xfaDatasets"), pdfManager.ensureCatalog("structTreeRoot"), pdfManager.ensureCatalog("baseUrl"), pdfManager.ensureCatalog("attachments"), pdfManager.ensureCatalog("globalColorSpaceCache")]).then(([acroForm, xfaDatasets, structTreeRoot, baseUrl, attachments, globalColorSpaceCache]) => ({ + pdfManager, + acroForm: acroForm instanceof Dict ? acroForm : Dict.empty, + xfaDatasets, + structTreeRoot, + baseUrl, + attachments, + globalColorSpaceCache + }), (reason) => { + warn2(`createGlobals: "${reason}".`); + return null; + }); + } + static async create(xref, ref, annotationGlobals, idFactory, collectFields, orphanFields, collectByType, pageRef) { + const pageIndex = collectFields ? await this._getPageIndex(xref, ref, annotationGlobals.pdfManager) : null; + return annotationGlobals.pdfManager.ensure(this, "_create", [xref, ref, annotationGlobals, idFactory, collectFields, orphanFields, collectByType, pageIndex, pageRef]); + } + static _create(xref, ref, annotationGlobals, idFactory, collectFields = false, orphanFields = null, collectByType = null, pageIndex = null, pageRef = null) { + const dict = xref.fetchIfRef(ref); + if (!(dict instanceof Dict)) { + return void 0; + } + let subtype = dict.get("Subtype"); + subtype = subtype instanceof Name2 ? subtype.name : null; + if (collectByType && !collectByType.has(AnnotationType2[subtype.toUpperCase()])) { + return null; + } + const { + acroForm, + pdfManager + } = annotationGlobals; + const id = ref instanceof Ref ? ref.toString() : `annot_${idFactory.createObjId()}`; + const parameters = { + xref, + ref, + dict, + subtype, + id, + annotationGlobals, + collectFields, + orphanFields, + needAppearances: !collectFields && acroForm.get("NeedAppearances") === true, + pageIndex, + evaluatorOptions: pdfManager.evaluatorOptions, + pageRef + }; + switch (subtype) { + case "Link": + return new LinkAnnotation(parameters); + case "Text": + return new TextAnnotation(parameters); + case "Widget": + let fieldType = getInheritableProperty({ + dict, + key: "FT" + }); + fieldType = fieldType instanceof Name2 ? fieldType.name : null; + switch (fieldType) { + case "Tx": + return new TextWidgetAnnotation(parameters); + case "Btn": + return new ButtonWidgetAnnotation(parameters); + case "Ch": + return new ChoiceWidgetAnnotation(parameters); + case "Sig": + return new SignatureWidgetAnnotation(parameters); + } + warn2(`Unimplemented widget field type "${fieldType}", falling back to base field type.`); + return new WidgetAnnotation(parameters); + case "Popup": + return new PopupAnnotation(parameters); + case "FreeText": + return new FreeTextAnnotation(parameters); + case "Line": + return new LineAnnotation(parameters); + case "Square": + return new SquareAnnotation(parameters); + case "Circle": + return new CircleAnnotation(parameters); + case "PolyLine": + return new PolylineAnnotation(parameters); + case "Polygon": + return new PolygonAnnotation(parameters); + case "Caret": + return new CaretAnnotation(parameters); + case "Ink": + return new InkAnnotation(parameters); + case "Highlight": + return new HighlightAnnotation(parameters); + case "Underline": + return new UnderlineAnnotation(parameters); + case "Squiggly": + return new SquigglyAnnotation(parameters); + case "StrikeOut": + return new StrikeOutAnnotation(parameters); + case "Stamp": + return new StampAnnotation(parameters); + case "FileAttachment": + return new FileAttachmentAnnotation(parameters); + default: + if (!collectFields) { + if (!subtype) { + warn2("Annotation is missing the required /Subtype."); + } else { + warn2(`Unimplemented annotation type "${subtype}", falling back to base annotation.`); + } + } + return new Annotation(parameters); + } + } + static async _getPageIndex(xref, ref, pdfManager) { + try { + const annotDict = await xref.fetchIfRefAsync(ref); + if (!(annotDict instanceof Dict)) { + return -1; + } + const pageRef = annotDict.getRaw("P"); + if (pageRef instanceof Ref) { + try { + const pageIndex = await pdfManager.ensureCatalog("getPageIndex", [pageRef]); + return pageIndex; + } catch (ex) { + info2(`_getPageIndex -- not a valid page reference: "${ex}".`); + } + } + if (annotDict.has("Kids")) { + return -1; + } + const numPages = await pdfManager.ensureDoc("numPages"); + for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { + const page = await pdfManager.getPage(pageIndex); + const annotations = await pdfManager.ensure(page, "annotations"); + for (const annotRef of annotations) { + if (annotRef instanceof Ref && isRefsEqual(annotRef, ref)) { + return pageIndex; + } + } + } + } catch (ex) { + warn2(`_getPageIndex: "${ex}".`); + } + return -1; + } + static generateImages(annotations, xref, isOffscreenCanvasSupported) { + if (!isOffscreenCanvasSupported) { + warn2("generateImages: OffscreenCanvas is not supported, cannot save or print some annotations with images."); + return null; + } + let imagePromises; + for (const { + bitmapId, + bitmap + } of annotations) { + if (!bitmap) { + continue; + } + imagePromises ||= /* @__PURE__ */ new Map(); + imagePromises.set(bitmapId, StampAnnotation.createImage(bitmap, xref)); + } + return imagePromises; + } + static async saveNewAnnotations(evaluator, task, annotations, imagePromises, changes) { + const xref = evaluator.xref; + let baseFontRef; + const promises = []; + const { + isOffscreenCanvasSupported + } = evaluator.options; + for (const annotation of annotations) { + if (annotation.deleted) { + continue; + } + switch (annotation.annotationType) { + case AnnotationEditorType2.FREETEXT: + if (!baseFontRef) { + const baseFont = new Dict(xref); + baseFont.setIfName("BaseFont", "Helvetica"); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type1"); + baseFont.setIfName("Encoding", "WinAnsiEncoding"); + baseFontRef = xref.getNewTemporaryRef(); + changes.put(baseFontRef, { + data: baseFont + }); + } + promises.push(FreeTextAnnotation.createNewAnnotation(xref, annotation, changes, { + evaluator, + task, + baseFontRef + })); + break; + case AnnotationEditorType2.HIGHLIGHT: + if (annotation.quadPoints) { + promises.push(HighlightAnnotation.createNewAnnotation(xref, annotation, changes)); + } else { + promises.push(InkAnnotation.createNewAnnotation(xref, annotation, changes)); + } + break; + case AnnotationEditorType2.INK: + promises.push(InkAnnotation.createNewAnnotation(xref, annotation, changes)); + break; + case AnnotationEditorType2.STAMP: + const image = isOffscreenCanvasSupported ? await imagePromises?.get(annotation.bitmapId) : null; + if (image?.imageStream) { + const { + imageStream, + smaskStream + } = image; + if (smaskStream) { + const smaskRef = xref.getNewTemporaryRef(); + changes.put(smaskRef, { + data: smaskStream + }); + imageStream.dict.set("SMask", smaskRef); + } + const imageRef = image.imageRef = xref.getNewTemporaryRef(); + changes.put(imageRef, { + data: imageStream + }); + image.imageStream = image.smaskStream = null; + } + promises.push(StampAnnotation.createNewAnnotation(xref, annotation, changes, { + image + })); + break; + case AnnotationEditorType2.SIGNATURE: + promises.push(StampAnnotation.createNewAnnotation(xref, annotation, changes, {})); + break; + } + } + return { + annotations: (await Promise.all(promises)).flat() + }; + } + static async printNewAnnotations(annotationGlobals, evaluator, task, annotations, imagePromises) { + if (!annotations) { + return null; + } + const { + options, + xref + } = evaluator; + const promises = []; + for (const annotation of annotations) { + if (annotation.deleted) { + continue; + } + switch (annotation.annotationType) { + case AnnotationEditorType2.FREETEXT: + promises.push(FreeTextAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluator, + task, + evaluatorOptions: options + })); + break; + case AnnotationEditorType2.HIGHLIGHT: + if (annotation.quadPoints) { + promises.push(HighlightAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + } else { + promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + } + break; + case AnnotationEditorType2.INK: + promises.push(InkAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + break; + case AnnotationEditorType2.STAMP: + const image = options.isOffscreenCanvasSupported ? await imagePromises?.get(annotation.bitmapId) : null; + if (image?.imageStream) { + const { + imageStream, + smaskStream + } = image; + if (smaskStream) { + imageStream.dict.set("SMask", smaskStream); + } + image.imageRef = new JpegStream(imageStream, imageStream.length); + image.imageStream = image.smaskStream = null; + } + promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + image, + evaluatorOptions: options + })); + break; + case AnnotationEditorType2.SIGNATURE: + promises.push(StampAnnotation.createNewPrintAnnotation(annotationGlobals, xref, annotation, { + evaluatorOptions: options + })); + break; + } + } + return Promise.all(promises); + } + }; + Annotation = class { + constructor(params) { + const { + dict, + xref, + annotationGlobals, + ref, + orphanFields + } = params; + const parentRef = orphanFields?.get(ref); + if (parentRef) { + dict.set("Parent", parentRef); + } + this.setTitle(dict.get("T")); + this.setContents(dict.get("Contents")); + this.setModificationDate(dict.get("M")); + this.setFlags(dict.get("F")); + this.setRectangle(dict.getArray("Rect")); + this.setColor(dict.getArray("C")); + this.setBorderStyle(dict); + this.setAppearance(dict); + this.setOptionalContent(dict); + const MK = dict.get("MK"); + this.setBorderAndBackgroundColors(MK); + this.setRotation(MK, dict); + this.ref = params.ref instanceof Ref ? params.ref : null; + this._streams = []; + if (this.appearance) { + this._streams.push(this.appearance); + } + const isLocked = !!(this.flags & AnnotationFlag.LOCKED); + const isContentLocked = !!(this.flags & AnnotationFlag.LOCKEDCONTENTS); + this.data = { + annotationFlags: this.flags, + borderStyle: this.borderStyle, + color: this.color, + backgroundColor: this.backgroundColor, + borderColor: this.borderColor, + rotation: this.rotation, + contentsObj: this._contents, + hasAppearance: !!this.appearance, + id: params.id, + modificationDate: this.modificationDate, + rect: this.rectangle, + subtype: params.subtype, + hasOwnCanvas: false, + noRotate: !!(this.flags & AnnotationFlag.NOROTATE), + noHTML: isLocked && isContentLocked, + isEditable: false, + structParent: -1 + }; + if (annotationGlobals.structTreeRoot) { + let structParent = dict.get("StructParent"); + this.data.structParent = structParent = Number.isInteger(structParent) && structParent >= 0 ? structParent : -1; + annotationGlobals.structTreeRoot.addAnnotationIdToPage(params.pageRef, structParent); + } + if (params.collectFields) { + const kids = dict.get("Kids"); + if (Array.isArray(kids)) { + const kidIds = []; + for (const kid of kids) { + if (kid instanceof Ref) { + kidIds.push(kid.toString()); + } + } + if (kidIds.length !== 0) { + this.data.kidIds = kidIds; + } + } + this.data.actions = collectActions(xref, dict, AnnotationActionEventType); + this.data.fieldName = this._constructFieldName(dict); + this.data.pageIndex = params.pageIndex; + } + const it = dict.get("IT"); + if (it instanceof Name2) { + this.data.it = it.name; + } + this._isOffscreenCanvasSupported = params.evaluatorOptions.isOffscreenCanvasSupported; + this._fallbackFontDict = null; + this._needAppearances = false; + } + _hasFlag(flags, flag) { + return !!(flags & flag); + } + _buildFlags(noView, noPrint) { + let { + flags + } = this; + if (noView === void 0) { + if (noPrint === void 0) { + return void 0; + } + if (noPrint) { + return flags & ~AnnotationFlag.PRINT; + } + return flags & ~AnnotationFlag.HIDDEN | AnnotationFlag.PRINT; + } + if (noView) { + flags |= AnnotationFlag.PRINT; + if (noPrint) { + return flags & ~AnnotationFlag.NOVIEW | AnnotationFlag.HIDDEN; + } + return flags & ~AnnotationFlag.HIDDEN | AnnotationFlag.NOVIEW; + } + flags &= ~(AnnotationFlag.HIDDEN | AnnotationFlag.NOVIEW); + if (noPrint) { + return flags & ~AnnotationFlag.PRINT; + } + return flags | AnnotationFlag.PRINT; + } + _isViewable(flags) { + return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, AnnotationFlag.NOVIEW); + } + _isPrintable(flags) { + return this._hasFlag(flags, AnnotationFlag.PRINT) && !this._hasFlag(flags, AnnotationFlag.HIDDEN) && !this._hasFlag(flags, AnnotationFlag.INVISIBLE); + } + mustBeViewed(annotationStorage, _renderForms) { + const noView = annotationStorage?.get(this.data.id)?.noView; + if (noView !== void 0) { + return !noView; + } + return this.viewable && !this._hasFlag(this.flags, AnnotationFlag.HIDDEN); + } + mustBePrinted(annotationStorage) { + const noPrint = annotationStorage?.get(this.data.id)?.noPrint; + if (noPrint !== void 0) { + return !noPrint; + } + return this.printable; + } + mustBeViewedWhenEditing(isEditing, modifiedIds = null) { + return isEditing ? !this.data.isEditable : !modifiedIds?.has(this.data.id); + } + get viewable() { + if (this.data.quadPoints === null) { + return false; + } + if (this.flags === 0) { + return true; + } + return this._isViewable(this.flags); + } + get printable() { + if (this.data.quadPoints === null) { + return false; + } + if (this.flags === 0) { + return false; + } + return this._isPrintable(this.flags); + } + _parseStringHelper(data) { + const str = typeof data === "string" ? stringToPDFString(data) : ""; + const dir = str && bidi(str).dir === "rtl" ? "rtl" : "ltr"; + return { + str, + dir + }; + } + setDefaultAppearance(params) { + const { + dict, + annotationGlobals + } = params; + const defaultAppearance = getInheritableProperty({ + dict, + key: "DA" + }) || annotationGlobals.acroForm.get("DA"); + this._defaultAppearance = typeof defaultAppearance === "string" ? defaultAppearance : ""; + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance); + } + setTitle(title) { + this._title = this._parseStringHelper(title); + } + setContents(contents) { + this._contents = this._parseStringHelper(contents); + } + setModificationDate(modificationDate) { + this.modificationDate = typeof modificationDate === "string" ? modificationDate : null; + } + setFlags(flags) { + this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0; + if (this.flags & AnnotationFlag.INVISIBLE && this.constructor.name !== "Annotation") { + this.flags ^= AnnotationFlag.INVISIBLE; + } + } + hasFlag(flag) { + return this._hasFlag(this.flags, flag); + } + setRectangle(rectangle) { + this.rectangle = lookupNormalRect(rectangle, [0, 0, 0, 0]); + } + setColor(color) { + this.color = getRgbColor(color); + } + setLineEndings(lineEndings) { + this.lineEndings = ["None", "None"]; + if (Array.isArray(lineEndings) && lineEndings.length === 2) { + for (let i = 0; i < 2; i++) { + const obj2 = lineEndings[i]; + if (obj2 instanceof Name2) { + switch (obj2.name) { + case "None": + continue; + case "Square": + case "Circle": + case "Diamond": + case "OpenArrow": + case "ClosedArrow": + case "Butt": + case "ROpenArrow": + case "RClosedArrow": + case "Slash": + this.lineEndings[i] = obj2.name; + continue; + } + } + warn2(`Ignoring invalid lineEnding: ${obj2}`); + } + } + } + setRotation(mk, dict) { + this.rotation = 0; + let angle = mk instanceof Dict ? mk.get("R") || 0 : dict.get("Rotate") || 0; + if (Number.isInteger(angle) && angle !== 0) { + angle %= 360; + if (angle < 0) { + angle += 360; + } + if (angle % 90 === 0) { + this.rotation = angle; + } + } + } + setBorderAndBackgroundColors(mk) { + if (mk instanceof Dict) { + this.borderColor = getRgbColor(mk.getArray("BC"), null); + this.backgroundColor = getRgbColor(mk.getArray("BG"), null); + } else { + this.borderColor = this.backgroundColor = null; + } + } + setBorderStyle(borderStyle) { + this.borderStyle = new AnnotationBorderStyle(); + if (!(borderStyle instanceof Dict)) { + return; + } + if (borderStyle.has("BS")) { + const dict = borderStyle.get("BS"); + if (dict instanceof Dict) { + const dictType = dict.get("Type"); + if (!dictType || isName(dictType, "Border")) { + this.borderStyle.setWidth(dict.get("W"), this.rectangle); + this.borderStyle.setStyle(dict.get("S")); + this.borderStyle.setDashArray(dict.getArray("D")); + } + } + } else if (borderStyle.has("Border")) { + const array2 = borderStyle.getArray("Border"); + if (Array.isArray(array2) && array2.length >= 3) { + this.borderStyle.setHorizontalCornerRadius(array2[0]); + this.borderStyle.setVerticalCornerRadius(array2[1]); + this.borderStyle.setWidth(array2[2], this.rectangle); + if (array2.length === 4) { + this.borderStyle.setDashArray(array2[3], true); + } + } + } else { + this.borderStyle.setWidth(0); + } + } + setAppearance(dict) { + this.appearance = null; + const appearanceStates = dict.get("AP"); + if (!(appearanceStates instanceof Dict)) { + return; + } + const normalAppearanceState = appearanceStates.get("N"); + if (normalAppearanceState instanceof BaseStream) { + this.appearance = normalAppearanceState; + return; + } + if (!(normalAppearanceState instanceof Dict)) { + return; + } + const as = dict.get("AS"); + if (!(as instanceof Name2) || !normalAppearanceState.has(as.name)) { + return; + } + const appearance = normalAppearanceState.get(as.name); + if (appearance instanceof BaseStream) { + this.appearance = appearance; + } + } + setOptionalContent(dict) { + this.oc = null; + const oc = dict.get("OC"); + if (oc instanceof Name2) { + warn2("setOptionalContent: Support for /Name-entry is not implemented."); + } else if (oc instanceof Dict) { + this.oc = oc; + } + } + async loadResources(keys2, appearance) { + const resources = await appearance.dict.getAsync("Resources"); + if (resources) { + await ObjectLoader.load(resources, keys2, resources.xref); + } + return resources; + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + const { + hasOwnCanvas, + id, + rect + } = this.data; + let appearance = this.appearance; + const isUsingOwnCanvas = !!(hasOwnCanvas && intent & RenderingIntentFlag2.DISPLAY); + if (isUsingOwnCanvas && (this.width === 0 || this.height === 0)) { + this.data.hasOwnCanvas = false; + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + if (!appearance) { + if (!isUsingOwnCanvas) { + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + appearance = new StringStream(""); + appearance.dict = new Dict(); + } + const appearanceDict = appearance.dict; + const resources = await this.loadResources(RESOURCES_KEYS_OPERATOR_LIST, appearance); + const bbox = lookupRect(appearanceDict.getArray("BBox"), [0, 0, 1, 1]); + const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), IDENTITY_MATRIX); + const transform2 = getTransformMatrix(rect, bbox, matrix); + const opList = new OperatorList(); + let optionalContent; + if (this.oc) { + optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); + } + if (optionalContent !== void 0) { + opList.addOp(OPS2.beginMarkedContentProps, ["OC", optionalContent]); + } + opList.addOp(OPS2.beginAnnotation, [id, rect, transform2, matrix, isUsingOwnCanvas]); + await evaluator.getOperatorList({ + stream: appearance, + task, + resources, + operatorList: opList, + fallbackFontDict: this._fallbackFontDict + }); + opList.addOp(OPS2.endAnnotation, []); + if (optionalContent !== void 0) { + opList.addOp(OPS2.endMarkedContent, []); + } + this.reset(); + return { + opList, + separateForm: false, + separateCanvas: isUsingOwnCanvas + }; + } + async save(evaluator, task, annotationStorage, changes) { + return null; + } + get overlaysTextContent() { + return false; + } + get hasTextContent() { + return false; + } + async extractTextContent(evaluator, task, viewBox) { + if (!this.appearance) { + return; + } + const resources = await this.loadResources(RESOURCES_KEYS_TEXT_CONTENT, this.appearance); + const text2 = []; + const buffer2 = []; + let firstPosition = null; + const sink = { + desiredSize: Math.Infinity, + ready: true, + enqueue(chunk2, size3) { + for (const item of chunk2.items) { + if (item.str === void 0) { + continue; + } + firstPosition ||= item.transform.slice(-2); + buffer2.push(item.str); + if (item.hasEOL) { + text2.push(buffer2.join("").trimEnd()); + buffer2.length = 0; + } + } + } + }; + await evaluator.getTextContent({ + stream: this.appearance, + task, + resources, + includeMarkedContent: true, + keepWhiteSpace: true, + sink, + viewBox + }); + this.reset(); + if (buffer2.length) { + text2.push(buffer2.join("").trimEnd()); + } + if (text2.length > 1 || text2[0]) { + const appearanceDict = this.appearance.dict; + const bbox = lookupRect(appearanceDict.getArray("BBox"), null); + const matrix = lookupMatrix(appearanceDict.getArray("Matrix"), null); + this.data.textPosition = this._transformPoint(firstPosition, bbox, matrix); + this.data.textContent = text2; + } + } + _transformPoint(coords, bbox, matrix) { + const { + rect + } = this.data; + bbox ||= [0, 0, 1, 1]; + matrix ||= [1, 0, 0, 1, 0, 0]; + const transform2 = getTransformMatrix(rect, bbox, matrix); + transform2[4] -= rect[0]; + transform2[5] -= rect[1]; + const p = coords.slice(); + Util2.applyTransform(p, transform2); + Util2.applyTransform(p, matrix); + return p; + } + getFieldObject() { + if (this.data.kidIds) { + return { + id: this.data.id, + actions: this.data.actions, + name: this.data.fieldName, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + type: "", + kidIds: this.data.kidIds, + page: this.data.pageIndex, + rotation: this.rotation + }; + } + return null; + } + reset() { + for (const stream of this._streams) { + stream.reset(); + } + } + _constructFieldName(dict) { + if (!dict.has("T") && !dict.has("Parent")) { + warn2("Unknown field name, falling back to empty field name."); + return ""; + } + if (!dict.has("Parent")) { + return stringToPDFString(dict.get("T")); + } + const fieldName = []; + if (dict.has("T")) { + fieldName.unshift(stringToPDFString(dict.get("T"))); + } + let loopDict = dict; + const visited = new RefSet(); + if (dict.objId) { + visited.put(dict.objId); + } + while (loopDict.has("Parent")) { + loopDict = loopDict.get("Parent"); + if (!(loopDict instanceof Dict) || loopDict.objId && visited.has(loopDict.objId)) { + break; + } + if (loopDict.objId) { + visited.put(loopDict.objId); + } + if (loopDict.has("T")) { + fieldName.unshift(stringToPDFString(loopDict.get("T"))); + } + } + return fieldName.join("."); + } + get width() { + return this.data.rect[2] - this.data.rect[0]; + } + get height() { + return this.data.rect[3] - this.data.rect[1]; + } + }; + AnnotationBorderStyle = class { + constructor() { + this.width = 1; + this.rawWidth = 1; + this.style = AnnotationBorderStyleType2.SOLID; + this.dashArray = [3]; + this.horizontalCornerRadius = 0; + this.verticalCornerRadius = 0; + } + setWidth(width, rect = [0, 0, 0, 0]) { + if (width instanceof Name2) { + this.width = 0; + return; + } + if (typeof width === "number") { + if (width > 0) { + this.rawWidth = width; + const maxWidth = (rect[2] - rect[0]) / 2; + const maxHeight = (rect[3] - rect[1]) / 2; + if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) { + warn2(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`); + width = 1; + } + } + this.width = width; + } + } + setStyle(style) { + if (!(style instanceof Name2)) { + return; + } + switch (style.name) { + case "S": + this.style = AnnotationBorderStyleType2.SOLID; + break; + case "D": + this.style = AnnotationBorderStyleType2.DASHED; + break; + case "B": + this.style = AnnotationBorderStyleType2.BEVELED; + break; + case "I": + this.style = AnnotationBorderStyleType2.INSET; + break; + case "U": + this.style = AnnotationBorderStyleType2.UNDERLINE; + break; + default: + break; + } + } + setDashArray(dashArray, forceStyle = false) { + if (Array.isArray(dashArray)) { + let isValid = true; + let allZeros = true; + for (const element of dashArray) { + const validNumber = +element >= 0; + if (!validNumber) { + isValid = false; + break; + } else if (element > 0) { + allZeros = false; + } + } + if (dashArray.length === 0 || isValid && !allZeros) { + this.dashArray = dashArray; + if (forceStyle) { + this.setStyle(Name2.get("D")); + } + } else { + this.width = 0; + } + } else if (dashArray) { + this.width = 0; + } + } + setHorizontalCornerRadius(radius) { + if (Number.isInteger(radius)) { + this.horizontalCornerRadius = radius; + } + } + setVerticalCornerRadius(radius) { + if (Number.isInteger(radius)) { + this.verticalCornerRadius = radius; + } + } + }; + MarkupAnnotation = class extends Annotation { + constructor(params) { + super(params); + const { + dict + } = params; + if (dict.has("IRT")) { + const rawIRT = dict.getRaw("IRT"); + this.data.inReplyTo = rawIRT instanceof Ref ? rawIRT.toString() : null; + const rt = dict.get("RT"); + this.data.replyType = rt instanceof Name2 ? rt.name : AnnotationReplyType.REPLY; + } + let popupRef = null; + if (this.data.replyType === AnnotationReplyType.GROUP) { + const parent = dict.get("IRT"); + this.setTitle(parent.get("T")); + this.data.titleObj = this._title; + this.setContents(parent.get("Contents")); + this.data.contentsObj = this._contents; + if (!parent.has("CreationDate")) { + this.data.creationDate = null; + } else { + this.setCreationDate(parent.get("CreationDate")); + this.data.creationDate = this.creationDate; + } + if (!parent.has("M")) { + this.data.modificationDate = null; + } else { + this.setModificationDate(parent.get("M")); + this.data.modificationDate = this.modificationDate; + } + popupRef = parent.getRaw("Popup"); + if (!parent.has("C")) { + this.data.color = null; + } else { + this.setColor(parent.getArray("C")); + this.data.color = this.color; + } + } else { + this.data.titleObj = this._title; + this.setCreationDate(dict.get("CreationDate")); + this.data.creationDate = this.creationDate; + popupRef = dict.getRaw("Popup"); + if (!dict.has("C")) { + this.data.color = null; + } + } + this.data.popupRef = popupRef instanceof Ref ? popupRef.toString() : null; + if (dict.has("RC")) { + this.data.richText = XFAFactory.getRichTextAsHtml(dict.get("RC")); + } + } + setCreationDate(creationDate) { + this.creationDate = typeof creationDate === "string" ? creationDate : null; + } + _setDefaultAppearance({ + xref, + extra, + strokeColor, + fillColor, + blendMode, + strokeAlpha, + fillAlpha, + pointsCallback + }) { + const bbox = this.data.rect = [Infinity, Infinity, -Infinity, -Infinity]; + const buffer2 = ["q"]; + if (extra) { + buffer2.push(extra); + } + if (strokeColor) { + buffer2.push(`${strokeColor[0]} ${strokeColor[1]} ${strokeColor[2]} RG`); + } + if (fillColor) { + buffer2.push(`${fillColor[0]} ${fillColor[1]} ${fillColor[2]} rg`); + } + const pointsArray = this.data.quadPoints || Float32Array.from([this.rectangle[0], this.rectangle[3], this.rectangle[2], this.rectangle[3], this.rectangle[0], this.rectangle[1], this.rectangle[2], this.rectangle[1]]); + for (let i = 0, ii = pointsArray.length; i < ii; i += 8) { + const points = pointsCallback(buffer2, pointsArray.subarray(i, i + 8)); + Util2.rectBoundingBox(...points, bbox); + } + buffer2.push("Q"); + const formDict = new Dict(xref); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.setIfName("Subtype", "Form"); + const appearanceStream = new StringStream(buffer2.join(" ")); + appearanceStream.dict = appearanceStreamDict; + formDict.set("Fm0", appearanceStream); + const gsDict = new Dict(xref); + if (blendMode) { + gsDict.setIfName("BM", blendMode); + } + gsDict.setIfNumber("CA", strokeAlpha); + gsDict.setIfNumber("ca", fillAlpha); + const stateDict = new Dict(xref); + stateDict.set("GS0", gsDict); + const resources = new Dict(xref); + resources.set("ExtGState", stateDict); + resources.set("XObject", formDict); + const appearanceDict = new Dict(xref); + appearanceDict.set("Resources", resources); + appearanceDict.set("BBox", bbox); + this.appearance = new StringStream("/GS0 gs /Fm0 Do"); + this.appearance.dict = appearanceDict; + this._streams.push(this.appearance, appearanceStream); + } + static async createNewAnnotation(xref, annotation, changes, params) { + const annotationRef = annotation.ref ||= xref.getNewTemporaryRef(); + const ap = await this.createNewAppearanceStream(annotation, xref, params); + let annotationDict; + if (ap) { + const apRef = xref.getNewTemporaryRef(); + annotationDict = this.createNewDict(annotation, xref, { + apRef + }); + changes.put(apRef, { + data: ap + }); + } else { + annotationDict = this.createNewDict(annotation, xref, {}); + } + if (Number.isInteger(annotation.parentTreeId)) { + annotationDict.set("StructParent", annotation.parentTreeId); + } + changes.put(annotationRef, { + data: annotationDict + }); + const retRef = { + ref: annotationRef + }; + const { + popup + } = annotation; + if (popup) { + if (popup.deleted) { + annotationDict.delete("Popup"); + annotationDict.delete("Contents"); + annotationDict.delete("RC"); + return retRef; + } + const popupRef = popup.ref ||= xref.getNewTemporaryRef(); + popup.parent = annotationRef; + const popupDict = PopupAnnotation.createNewDict(popup, xref); + changes.put(popupRef, { + data: popupDict + }); + annotationDict.setIfDefined("Contents", stringToAsciiOrUTF16BE(popup.contents)); + annotationDict.set("Popup", popupRef); + return [retRef, { + ref: popupRef + }]; + } + return retRef; + } + static async createNewPrintAnnotation(annotationGlobals, xref, annotation, params) { + const ap = await this.createNewAppearanceStream(annotation, xref, params); + const annotationDict = this.createNewDict(annotation, xref, ap ? { + ap + } : {}); + const newAnnotation = new this.prototype.constructor({ + dict: annotationDict, + xref, + annotationGlobals, + evaluatorOptions: params.evaluatorOptions + }); + if (annotation.ref) { + newAnnotation.ref = newAnnotation.refToReplace = annotation.ref; + } + return newAnnotation; + } + }; + WidgetAnnotation = class _WidgetAnnotation extends Annotation { + constructor(params) { + super(params); + const { + dict, + xref, + annotationGlobals + } = params; + const data = this.data; + this._needAppearances = params.needAppearances; + data.annotationType = AnnotationType2.WIDGET; + if (data.fieldName === void 0) { + data.fieldName = this._constructFieldName(dict); + } + if (data.actions === void 0) { + data.actions = collectActions(xref, dict, AnnotationActionEventType); + } + let fieldValue = getInheritableProperty({ + dict, + key: "V", + getArray: true + }); + data.fieldValue = this._decodeFormValue(fieldValue); + const defaultFieldValue = getInheritableProperty({ + dict, + key: "DV", + getArray: true + }); + data.defaultFieldValue = this._decodeFormValue(defaultFieldValue); + if (fieldValue === void 0 && annotationGlobals.xfaDatasets) { + const path2 = this._title.str; + if (path2) { + this._hasValueFromXFA = true; + data.fieldValue = fieldValue = annotationGlobals.xfaDatasets.getValue(path2); + } + } + if (fieldValue === void 0 && data.defaultFieldValue !== null) { + data.fieldValue = data.defaultFieldValue; + } + data.alternativeText = stringToPDFString(dict.get("TU") || ""); + this.setDefaultAppearance(params); + data.hasAppearance ||= this._needAppearances && data.fieldValue !== void 0 && data.fieldValue !== null; + const fieldType = getInheritableProperty({ + dict, + key: "FT" + }); + data.fieldType = fieldType instanceof Name2 ? fieldType.name : null; + const localResources = getInheritableProperty({ + dict, + key: "DR" + }); + const acroFormResources = annotationGlobals.acroForm.get("DR"); + const appearanceResources = this.appearance?.dict.get("Resources"); + this._fieldResources = { + localResources, + acroFormResources, + appearanceResources, + mergedResources: Dict.merge({ + xref, + dictArray: [localResources, appearanceResources, acroFormResources], + mergeSubDicts: true + }) + }; + data.fieldFlags = getInheritableProperty({ + dict, + key: "Ff" + }); + if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) { + data.fieldFlags = 0; + } + data.password = this.hasFieldFlag(AnnotationFieldFlag.PASSWORD); + data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY); + data.required = this.hasFieldFlag(AnnotationFieldFlag.REQUIRED); + data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN) || this._hasFlag(data.annotationFlags, AnnotationFlag.NOVIEW); + } + _decodeFormValue(formValue) { + if (Array.isArray(formValue)) { + return formValue.filter((item) => typeof item === "string").map((item) => stringToPDFString(item)); + } else if (formValue instanceof Name2) { + return stringToPDFString(formValue.name); + } else if (typeof formValue === "string") { + return stringToPDFString(formValue); + } + return null; + } + hasFieldFlag(flag) { + return !!(this.data.fieldFlags & flag); + } + _isViewable(flags) { + return true; + } + mustBeViewed(annotationStorage, renderForms) { + if (renderForms) { + return this.viewable; + } + return super.mustBeViewed(annotationStorage, renderForms) && !this._hasFlag(this.flags, AnnotationFlag.NOVIEW); + } + getRotationMatrix(annotationStorage) { + let rotation = annotationStorage?.get(this.data.id)?.rotation; + if (rotation === void 0) { + rotation = this.rotation; + } + return rotation === 0 ? IDENTITY_MATRIX : getRotationMatrix(rotation, this.width, this.height); + } + getBorderAndBackgroundAppearances(annotationStorage) { + let rotation = annotationStorage?.get(this.data.id)?.rotation; + if (rotation === void 0) { + rotation = this.rotation; + } + if (!this.backgroundColor && !this.borderColor) { + return ""; + } + const rect = rotation === 0 || rotation === 180 ? `0 0 ${this.width} ${this.height} re` : `0 0 ${this.height} ${this.width} re`; + let str = ""; + if (this.backgroundColor) { + str = `${getPdfColor(this.backgroundColor, true)} ${rect} f `; + } + if (this.borderColor) { + const borderWidth = this.borderStyle.width || 1; + str += `${borderWidth} w ${getPdfColor(this.borderColor, false)} ${rect} S `; + } + return str; + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + if (intent & RenderingIntentFlag2.ANNOTATIONS_FORMS && !(this instanceof SignatureWidgetAnnotation) && !this.data.noHTML && !this.data.hasOwnCanvas) { + return { + opList: new OperatorList(), + separateForm: true, + separateCanvas: false + }; + } + if (!this._hasText) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + const content = await this._getAppearance(evaluator, task, intent, annotationStorage); + if (this.appearance && content === null) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + const opList = new OperatorList(); + if (!this._defaultAppearance || content === null) { + return { + opList, + separateForm: false, + separateCanvas: false + }; + } + const isUsingOwnCanvas = !!(this.data.hasOwnCanvas && intent & RenderingIntentFlag2.DISPLAY); + const matrix = [1, 0, 0, 1, 0, 0]; + const bbox = [0, 0, this.width, this.height]; + const transform2 = getTransformMatrix(this.data.rect, bbox, matrix); + let optionalContent; + if (this.oc) { + optionalContent = await evaluator.parseMarkedContentProps(this.oc, null); + } + if (optionalContent !== void 0) { + opList.addOp(OPS2.beginMarkedContentProps, ["OC", optionalContent]); + } + opList.addOp(OPS2.beginAnnotation, [this.data.id, this.data.rect, transform2, this.getRotationMatrix(annotationStorage), isUsingOwnCanvas]); + const stream = new StringStream(content); + await evaluator.getOperatorList({ + stream, + task, + resources: this._fieldResources.mergedResources, + operatorList: opList + }); + opList.addOp(OPS2.endAnnotation, []); + if (optionalContent !== void 0) { + opList.addOp(OPS2.endMarkedContent, []); + } + return { + opList, + separateForm: false, + separateCanvas: isUsingOwnCanvas + }; + } + _getMKDict(rotation) { + const mk = new Dict(null); + if (rotation) { + mk.set("R", rotation); + } + mk.setIfArray("BC", getPdfColorArray(this.borderColor)); + mk.setIfArray("BG", getPdfColorArray(this.backgroundColor)); + return mk.size > 0 ? mk : null; + } + amendSavedDict(annotationStorage, dict) { + } + setValue(dict, value, xref, changes) { + const { + dict: parentDict, + ref: parentRef + } = getParentToUpdate(dict, this.ref, xref); + if (!parentDict) { + dict.set("V", value); + } else if (!changes.has(parentRef)) { + const newParentDict = parentDict.clone(); + newParentDict.set("V", value); + changes.put(parentRef, { + data: newParentDict + }); + return newParentDict; + } + return null; + } + async save(evaluator, task, annotationStorage, changes) { + const storageEntry = annotationStorage?.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let value = storageEntry?.value, rotation = storageEntry?.rotation; + if (value === this.data.fieldValue || value === void 0) { + if (!this._hasValueFromXFA && rotation === void 0 && flags === void 0) { + return; + } + value ||= this.data.fieldValue; + } + if (rotation === void 0 && !this._hasValueFromXFA && Array.isArray(value) && Array.isArray(this.data.fieldValue) && isArrayEqual(value, this.data.fieldValue) && flags === void 0) { + return; + } + if (rotation === void 0) { + rotation = this.rotation; + } + let appearance = null; + if (!this._needAppearances) { + appearance = await this._getAppearance(evaluator, task, RenderingIntentFlag2.SAVE, annotationStorage); + if (appearance === null && flags === void 0) { + return; + } + } else { + } + let needAppearances = false; + if (appearance?.needAppearances) { + needAppearances = true; + appearance = null; + } + const { + xref + } = evaluator; + const originalDict = xref.fetchIfRef(this.ref); + if (!(originalDict instanceof Dict)) { + return; + } + const dict = new Dict(xref); + for (const key of originalDict.getKeys()) { + if (key !== "AP") { + dict.set(key, originalDict.getRaw(key)); + } + } + if (flags !== void 0) { + dict.set("F", flags); + if (appearance === null && !needAppearances) { + const ap = originalDict.getRaw("AP"); + if (ap) { + dict.set("AP", ap); + } + } + } + const xfa = { + path: this.data.fieldName, + value + }; + const newParentDict = this.setValue(dict, Array.isArray(value) ? value.map(stringToAsciiOrUTF16BE) : stringToAsciiOrUTF16BE(value), xref, changes); + this.amendSavedDict(annotationStorage, newParentDict || dict); + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances + }); + if (appearance !== null) { + const newRef = xref.getNewTemporaryRef(); + const AP = new Dict(xref); + dict.set("AP", AP); + AP.set("N", newRef); + const resources = this._getSaveFieldResources(xref); + const appearanceStream = new StringStream(appearance); + const appearanceDict = appearanceStream.dict = new Dict(xref); + appearanceDict.setIfName("Subtype", "Form"); + appearanceDict.set("Resources", resources); + const bbox = rotation % 180 === 0 ? [0, 0, this.width, this.height] : [0, 0, this.height, this.width]; + appearanceDict.set("BBox", bbox); + const rotationMatrix = this.getRotationMatrix(annotationStorage); + if (rotationMatrix !== IDENTITY_MATRIX) { + appearanceDict.set("Matrix", rotationMatrix); + } + changes.put(newRef, { + data: appearanceStream, + xfa: null, + needAppearances: false + }); + } + dict.set("M", `D:${getModificationDate()}`); + } + async _getAppearance(evaluator, task, intent, annotationStorage) { + if (this.data.password) { + return null; + } + const storageEntry = annotationStorage?.get(this.data.id); + let value, rotation; + if (storageEntry) { + value = storageEntry.formattedValue || storageEntry.value; + rotation = storageEntry.rotation; + } + if (rotation === void 0 && value === void 0 && !this._needAppearances) { + if (!this._hasValueFromXFA || this.appearance) { + return null; + } + } + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + if (value === void 0) { + value = this.data.fieldValue; + if (!value) { + return `/Tx BMC q ${colors}Q EMC`; + } + } + if (Array.isArray(value) && value.length === 1) { + value = value[0]; + } + assert3(typeof value === "string", "Expected `value` to be a string."); + value = value.trimEnd(); + if (this.data.combo) { + const option = this.data.options.find(({ + exportValue + }) => value === exportValue); + value = option?.displayValue || value; + } + if (value === "") { + return `/Tx BMC q ${colors}Q EMC`; + } + if (rotation === void 0) { + rotation = this.rotation; + } + let lineCount = -1; + let lines; + if (this.data.multiLine) { + lines = value.split(/\r\n?|\n/).map((line2) => line2.normalize("NFC")); + lineCount = lines.length; + } else { + lines = [value.replace(/\r\n?|\n/, "").normalize("NFC")]; + } + const defaultPadding = 1; + const defaultHPadding = 2; + let { + width: totalWidth, + height: totalHeight + } = this; + if (rotation === 90 || rotation === 270) { + [totalWidth, totalHeight] = [totalHeight, totalWidth]; + } + if (!this._defaultAppearance) { + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); + } + let font = await _WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); + let defaultAppearance, fontSize, lineHeight; + const encodedLines = []; + let encodingError = false; + for (const line2 of lines) { + const encodedString = font.encodeString(line2); + if (encodedString.length > 1) { + encodingError = true; + } + encodedLines.push(encodedString.join("")); + } + if (encodingError && intent & RenderingIntentFlag2.SAVE) { + return { + needAppearances: true + }; + } + if (encodingError && this._isOffscreenCanvasSupported) { + const fontFamily = this.data.comb ? "monospace" : "sans-serif"; + const fakeUnicodeFont = new FakeUnicodeFont(evaluator.xref, fontFamily); + const resources = fakeUnicodeFont.createFontResources(lines.join("")); + const newFont = resources.getRaw("Font"); + if (this._fieldResources.mergedResources.has("Font")) { + const oldFont = this._fieldResources.mergedResources.get("Font"); + for (const key of newFont.getKeys()) { + oldFont.set(key, newFont.getRaw(key)); + } + } else { + this._fieldResources.mergedResources.set("Font", newFont); + } + const fontName = fakeUnicodeFont.fontName.name; + font = await _WidgetAnnotation._getFontData(evaluator, task, { + fontName, + fontSize: 0 + }, resources); + for (let i = 0, ii = encodedLines.length; i < ii; i++) { + encodedLines[i] = stringToUTF16String(lines[i]); + } + const savedDefaultAppearance = Object.assign(/* @__PURE__ */ Object.create(null), this.data.defaultAppearanceData); + this.data.defaultAppearanceData.fontSize = 0; + this.data.defaultAppearanceData.fontName = fontName; + [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); + this.data.defaultAppearanceData = savedDefaultAppearance; + } else { + if (!this._isOffscreenCanvasSupported) { + warn2("_getAppearance: OffscreenCanvas is not supported, annotation may not render correctly."); + } + [defaultAppearance, fontSize, lineHeight] = this._computeFontSize(totalHeight - 2 * defaultPadding, totalWidth - 2 * defaultHPadding, value, font, lineCount); + } + let descent = font.descent; + if (isNaN(descent)) { + descent = BASELINE_FACTOR2 * lineHeight; + } else { + descent = Math.max(BASELINE_FACTOR2 * lineHeight, Math.abs(descent) * fontSize); + } + const defaultVPadding = Math.min(Math.floor((totalHeight - fontSize) / 2), defaultPadding); + const alignment = this.data.textAlignment; + if (this.data.multiLine) { + return this._getMultilineAppearance(defaultAppearance, encodedLines, font, fontSize, totalWidth, totalHeight, alignment, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); + } + if (this.data.comb) { + return this._getCombAppearance(defaultAppearance, font, encodedLines[0], fontSize, totalWidth, totalHeight, defaultHPadding, defaultVPadding, descent, lineHeight, annotationStorage); + } + const bottomPadding = defaultVPadding + descent; + if (alignment === 0 || alignment > 2) { + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(defaultHPadding)} ${numberToString(bottomPadding)} Tm (${escapeString(encodedLines[0])}) Tj ET Q EMC`; + } + const prevInfo = { + shift: 0 + }; + const renderedText = this._renderText(encodedLines[0], font, fontSize, totalWidth, alignment, prevInfo, defaultHPadding, bottomPadding); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText} ET Q EMC`; + } + static async _getFontData(evaluator, task, appearanceData, resources) { + const operatorList = new OperatorList(); + const initialState = { + font: null, + clone() { + return this; + } + }; + const { + fontName, + fontSize + } = appearanceData; + await evaluator.handleSetFont(resources, [fontName && Name2.get(fontName), fontSize], null, operatorList, task, initialState, null); + return initialState.font; + } + _getTextWidth(text2, font) { + return Math.sumPrecise(font.charsToGlyphs(text2).map((g) => g.width)) / 1e3; + } + _computeFontSize(height, width, text2, font, lineCount) { + let { + fontSize + } = this.data.defaultAppearanceData; + let lineHeight = (fontSize || 12) * LINE_FACTOR2, numberOfLines = Math.round(height / lineHeight); + if (!fontSize) { + const roundWithTwoDigits = (x) => Math.floor(x * 100) / 100; + if (lineCount === -1) { + const textWidth = this._getTextWidth(text2, font); + fontSize = roundWithTwoDigits(Math.min(height / LINE_FACTOR2, width / textWidth)); + numberOfLines = 1; + } else { + const lines = text2.split(/\r\n?|\n/); + const cachedLines = []; + for (const line2 of lines) { + const encoded = font.encodeString(line2).join(""); + const glyphs = font.charsToGlyphs(encoded); + const positions = font.getCharPositions(encoded); + cachedLines.push({ + line: encoded, + glyphs, + positions + }); + } + const isTooBig = (fsize) => { + let totalHeight = 0; + for (const cache2 of cachedLines) { + const chunks = this._splitLine(null, font, fsize, width, cache2); + totalHeight += chunks.length * fsize; + if (totalHeight > height) { + return true; + } + } + return false; + }; + numberOfLines = Math.max(numberOfLines, lineCount); + while (true) { + lineHeight = height / numberOfLines; + fontSize = roundWithTwoDigits(lineHeight / LINE_FACTOR2); + if (isTooBig(fontSize)) { + numberOfLines++; + continue; + } + break; + } + } + const { + fontName, + fontColor + } = this.data.defaultAppearanceData; + this._defaultAppearance = createDefaultAppearance({ + fontSize, + fontName, + fontColor + }); + } + return [this._defaultAppearance, fontSize, height / numberOfLines]; + } + _renderText(text2, font, fontSize, totalWidth, alignment, prevInfo, hPadding, vPadding) { + let shift; + if (alignment === 1) { + const width = this._getTextWidth(text2, font) * fontSize; + shift = (totalWidth - width) / 2; + } else if (alignment === 2) { + const width = this._getTextWidth(text2, font) * fontSize; + shift = totalWidth - width - hPadding; + } else { + shift = hPadding; + } + const shiftStr = numberToString(shift - prevInfo.shift); + prevInfo.shift = shift; + vPadding = numberToString(vPadding); + return `${shiftStr} ${vPadding} Td (${escapeString(text2)}) Tj`; + } + _getSaveFieldResources(xref) { + const { + localResources, + appearanceResources, + acroFormResources + } = this._fieldResources; + const fontName = this.data.defaultAppearanceData?.fontName; + if (!fontName) { + return localResources || Dict.empty; + } + for (const resources of [localResources, appearanceResources]) { + if (resources instanceof Dict) { + const localFont = resources.get("Font"); + if (localFont instanceof Dict && localFont.has(fontName)) { + return resources; + } + } + } + if (acroFormResources instanceof Dict) { + const acroFormFont = acroFormResources.get("Font"); + if (acroFormFont instanceof Dict && acroFormFont.has(fontName)) { + const subFontDict = new Dict(xref); + subFontDict.set(fontName, acroFormFont.getRaw(fontName)); + const subResourcesDict = new Dict(xref); + subResourcesDict.set("Font", subFontDict); + return Dict.merge({ + xref, + dictArray: [subResourcesDict, localResources], + mergeSubDicts: true + }); + } + } + return localResources || Dict.empty; + } + getFieldObject() { + return null; + } + }; + TextWidgetAnnotation = class extends WidgetAnnotation { + constructor(params) { + super(params); + const { + dict + } = params; + if (dict.has("PMD")) { + this.flags |= AnnotationFlag.HIDDEN; + this.data.hidden = true; + warn2("Barcodes are not supported"); + } + this.data.hasOwnCanvas = this.data.readOnly && !this.data.noHTML; + this._hasText = true; + if (typeof this.data.fieldValue !== "string") { + this.data.fieldValue = ""; + } + let alignment = getInheritableProperty({ + dict, + key: "Q" + }); + if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) { + alignment = null; + } + this.data.textAlignment = alignment; + let maximumLength = getInheritableProperty({ + dict, + key: "MaxLen" + }); + if (!Number.isInteger(maximumLength) || maximumLength < 0) { + maximumLength = 0; + } + this.data.maxLen = maximumLength; + this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE); + this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) && !this.data.multiLine && !this.data.password && !this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== 0; + this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL); + const { + data: { + actions + } + } = this; + if (!actions) { + return; + } + const AFDateTime = /^AF(Date|Time)_(?:Keystroke|Format)(?:Ex)?\(['"]?([^'"]+)['"]?\);$/; + let canUseHTMLDateTime = false; + if (actions.Format?.length === 1 && actions.Keystroke?.length === 1 && AFDateTime.test(actions.Format[0]) && AFDateTime.test(actions.Keystroke[0]) || actions.Format?.length === 0 && actions.Keystroke?.length === 1 && AFDateTime.test(actions.Keystroke[0]) || actions.Keystroke?.length === 0 && actions.Format?.length === 1 && AFDateTime.test(actions.Format[0])) { + canUseHTMLDateTime = true; + } + const actionsToVisit = []; + if (actions.Format) { + actionsToVisit.push(...actions.Format); + } + if (actions.Keystroke) { + actionsToVisit.push(...actions.Keystroke); + } + if (canUseHTMLDateTime) { + delete actions.Keystroke; + actions.Format = actionsToVisit; + } + for (const formatAction of actionsToVisit) { + const m = formatAction.match(AFDateTime); + if (!m) { + continue; + } + const isDate = m[1] === "Date"; + let format = m[2]; + const num = parseInt(format, 10); + if (!isNaN(num) && Math.floor(Math.log10(num)) + 1 === m[2].length) { + format = (isDate ? DateFormats : TimeFormats)[num] ?? format; + } + this.data.datetimeFormat = format; + if (!canUseHTMLDateTime) { + break; + } + if (isDate) { + if (/HH|MM|ss|h/.test(format)) { + this.data.datetimeType = "datetime-local"; + this.data.timeStep = /ss/.test(format) ? 1 : 60; + } else { + this.data.datetimeType = "date"; + } + break; + } + this.data.datetimeType = "time"; + this.data.timeStep = /ss/.test(format) ? 1 : 60; + break; + } + } + get hasTextContent() { + return !!this.appearance && !this._needAppearances; + } + _getCombAppearance(defaultAppearance, font, text2, fontSize, width, height, hPadding, vPadding, descent, lineHeight, annotationStorage) { + const combWidth = width / this.data.maxLen; + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + const buf = []; + const positions = font.getCharPositions(text2); + for (const [start, end] of positions) { + buf.push(`(${escapeString(text2.substring(start, end))}) Tj`); + } + const renderedComb = buf.join(` ${numberToString(combWidth)} 0 Td `); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 ${numberToString(hPadding)} ${numberToString(vPadding + descent)} Tm ${renderedComb} ET Q EMC`; + } + _getMultilineAppearance(defaultAppearance, lines, font, fontSize, width, height, alignment, hPadding, vPadding, descent, lineHeight, annotationStorage) { + const buf = []; + const totalWidth = width - 2 * hPadding; + const prevInfo = { + shift: 0 + }; + for (let i = 0, ii = lines.length; i < ii; i++) { + const line2 = lines[i]; + const chunks = this._splitLine(line2, font, fontSize, totalWidth); + for (let j = 0, jj = chunks.length; j < jj; j++) { + const chunk2 = chunks[j]; + const vShift = i === 0 && j === 0 ? -vPadding - (lineHeight - descent) : -lineHeight; + buf.push(this._renderText(chunk2, font, fontSize, width, alignment, prevInfo, hPadding, vShift)); + } + } + const colors = this.getBorderAndBackgroundAppearances(annotationStorage); + const renderedText = buf.join("\n"); + return `/Tx BMC q ${colors}BT ` + defaultAppearance + ` 1 0 0 1 0 ${numberToString(height)} Tm ${renderedText} ET Q EMC`; + } + _splitLine(line2, font, fontSize, width, cache2 = {}) { + line2 = cache2.line || line2; + const glyphs = cache2.glyphs || font.charsToGlyphs(line2); + if (glyphs.length <= 1) { + return [line2]; + } + const positions = cache2.positions || font.getCharPositions(line2); + const scale = fontSize / 1e3; + const chunks = []; + let lastSpacePosInStringStart = -1, lastSpacePosInStringEnd = -1, lastSpacePos = -1, startChunk = 0, currentWidth = 0; + for (let i = 0, ii = glyphs.length; i < ii; i++) { + const [start, end] = positions[i]; + const glyph = glyphs[i]; + const glyphWidth = glyph.width * scale; + if (glyph.unicode === " ") { + if (currentWidth + glyphWidth > width) { + chunks.push(line2.substring(startChunk, start)); + startChunk = start; + currentWidth = glyphWidth; + lastSpacePosInStringStart = -1; + lastSpacePos = -1; + } else { + currentWidth += glyphWidth; + lastSpacePosInStringStart = start; + lastSpacePosInStringEnd = end; + lastSpacePos = i; + } + } else if (currentWidth + glyphWidth > width) { + if (lastSpacePosInStringStart !== -1) { + chunks.push(line2.substring(startChunk, lastSpacePosInStringEnd)); + startChunk = lastSpacePosInStringEnd; + i = lastSpacePos + 1; + lastSpacePosInStringStart = -1; + currentWidth = 0; + } else { + chunks.push(line2.substring(startChunk, start)); + startChunk = start; + currentWidth = glyphWidth; + } + } else { + currentWidth += glyphWidth; + } + } + if (startChunk < line2.length) { + chunks.push(line2.substring(startChunk, line2.length)); + } + return chunks; + } + async extractTextContent(evaluator, task, viewBox) { + await super.extractTextContent(evaluator, task, viewBox); + const text2 = this.data.textContent; + if (!text2) { + return; + } + const allText = text2.join("\n"); + if (allText === this.data.fieldValue) { + return; + } + const regex = allText.replaceAll(/([.*+?^${}()|[\]\\])|(\s+)/g, (_m, p1) => p1 ? `\\${p1}` : "\\s+"); + if (new RegExp(`^\\s*${regex}\\s*$`).test(this.data.fieldValue)) { + this.data.textContent = this.data.fieldValue.split("\n"); + } + } + getFieldObject() { + return { + id: this.data.id, + value: this.data.fieldValue, + defaultValue: this.data.defaultFieldValue || "", + multiline: this.data.multiLine, + password: this.data.password, + charLimit: this.data.maxLen, + comb: this.data.comb, + editable: !this.data.readOnly, + hidden: this.data.hidden, + name: this.data.fieldName, + rect: this.data.rect, + actions: this.data.actions, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + datetimeFormat: this.data.datetimeFormat, + hasDatetimeHTML: !!this.data.datetimeType, + type: "text" + }; + } + }; + ButtonWidgetAnnotation = class extends WidgetAnnotation { + constructor(params) { + super(params); + this.checkedAppearance = null; + this.uncheckedAppearance = null; + const isRadio = this.hasFieldFlag(AnnotationFieldFlag.RADIO), isPushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON); + this.data.checkBox = !isRadio && !isPushButton; + this.data.radioButton = isRadio && !isPushButton; + this.data.pushButton = isPushButton; + this.data.isTooltipOnly = false; + if (this.data.checkBox) { + this._processCheckBox(params); + } else if (this.data.radioButton) { + this._processRadioButton(params); + } else if (this.data.pushButton) { + this.data.hasOwnCanvas = true; + this.data.noHTML = false; + this._processPushButton(params); + } else { + warn2("Invalid field flags for button widget annotation"); + } + } + async getOperatorList(evaluator, task, intent, annotationStorage) { + if (this.data.pushButton) { + return super.getOperatorList(evaluator, task, intent, false, annotationStorage); + } + let value = null; + let rotation = null; + if (annotationStorage) { + const storageEntry = annotationStorage.get(this.data.id); + value = storageEntry ? storageEntry.value : null; + rotation = storageEntry ? storageEntry.rotation : null; + } + if (value === null && this.appearance) { + return super.getOperatorList(evaluator, task, intent, annotationStorage); + } + if (value === null || value === void 0) { + value = this.data.checkBox ? this.data.fieldValue === this.data.exportValue : this.data.fieldValue === this.data.buttonValue; + } + const appearance = value ? this.checkedAppearance : this.uncheckedAppearance; + if (appearance) { + const savedAppearance = this.appearance; + const savedMatrix = lookupMatrix(appearance.dict.getArray("Matrix"), IDENTITY_MATRIX); + if (rotation) { + appearance.dict.set("Matrix", this.getRotationMatrix(annotationStorage)); + } + this.appearance = appearance; + const operatorList = super.getOperatorList(evaluator, task, intent, annotationStorage); + this.appearance = savedAppearance; + appearance.dict.set("Matrix", savedMatrix); + return operatorList; + } + return { + opList: new OperatorList(), + separateForm: false, + separateCanvas: false + }; + } + async save(evaluator, task, annotationStorage, changes) { + if (this.data.checkBox) { + this._saveCheckbox(evaluator, task, annotationStorage, changes); + return; + } + if (this.data.radioButton) { + this._saveRadioButton(evaluator, task, annotationStorage, changes); + } + } + async _saveCheckbox(evaluator, task, annotationStorage, changes) { + if (!annotationStorage) { + return; + } + const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let rotation = storageEntry?.rotation, value = storageEntry?.value; + if (rotation === void 0 && flags === void 0) { + if (value === void 0) { + return; + } + const defaultValue = this.data.fieldValue === this.data.exportValue; + if (defaultValue === value) { + return; + } + } + let dict = evaluator.xref.fetchIfRef(this.ref); + if (!(dict instanceof Dict)) { + return; + } + dict = dict.clone(); + if (rotation === void 0) { + rotation = this.rotation; + } + if (value === void 0) { + value = this.data.fieldValue === this.data.exportValue; + } + const xfa = { + path: this.data.fieldName, + value: value ? this.data.exportValue : "" + }; + const name = Name2.get(value ? this.data.exportValue : "Off"); + this.setValue(dict, name, evaluator.xref, changes); + dict.set("AS", name); + dict.set("M", `D:${getModificationDate()}`); + if (flags !== void 0) { + dict.set("F", flags); + } + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances: false + }); + } + async _saveRadioButton(evaluator, task, annotationStorage, changes) { + if (!annotationStorage) { + return; + } + const storageEntry = annotationStorage.get(this.data.id); + const flags = this._buildFlags(storageEntry?.noView, storageEntry?.noPrint); + let rotation = storageEntry?.rotation, value = storageEntry?.value; + if (rotation === void 0 && flags === void 0) { + if (value === void 0) { + return; + } + const defaultValue = this.data.fieldValue === this.data.buttonValue; + if (defaultValue === value) { + return; + } + } + let dict = evaluator.xref.fetchIfRef(this.ref); + if (!(dict instanceof Dict)) { + return; + } + dict = dict.clone(); + if (value === void 0) { + value = this.data.fieldValue === this.data.buttonValue; + } + if (rotation === void 0) { + rotation = this.rotation; + } + const xfa = { + path: this.data.fieldName, + value: value ? this.data.buttonValue : "" + }; + const name = Name2.get(value ? this.data.buttonValue : "Off"); + if (value) { + this.setValue(dict, name, evaluator.xref, changes); + } + dict.set("AS", name); + dict.set("M", `D:${getModificationDate()}`); + if (flags !== void 0) { + dict.set("F", flags); + } + const maybeMK = this._getMKDict(rotation); + if (maybeMK) { + dict.set("MK", maybeMK); + } + changes.put(this.ref, { + data: dict, + xfa, + needAppearances: false + }); + } + _getDefaultCheckedAppearance(params, type) { + const { + width, + height + } = this; + const bbox = [0, 0, width, height]; + const FONT_RATIO = 0.8; + const fontSize = Math.min(width, height) * FONT_RATIO; + let metrics2, char2; + if (type === "check") { + metrics2 = { + width: 0.755 * fontSize, + height: 0.705 * fontSize + }; + char2 = "3"; + } else if (type === "disc") { + metrics2 = { + width: 0.791 * fontSize, + height: 0.705 * fontSize + }; + char2 = "l"; + } else { + unreachable2(`_getDefaultCheckedAppearance - unsupported type: ${type}`); + } + const xShift = numberToString((width - metrics2.width) / 2); + const yShift = numberToString((height - metrics2.height) / 2); + const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char2}) Tj ET Q`; + const appearanceStreamDict = new Dict(params.xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", bbox); + appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(params.xref); + const font = new Dict(params.xref); + font.set("PdfJsZaDb", this.fallbackFontDict); + resources.set("Font", font); + appearanceStreamDict.set("Resources", resources); + this.checkedAppearance = new StringStream(appearance); + this.checkedAppearance.dict = appearanceStreamDict; + this._streams.push(this.checkedAppearance); + } + _processCheckBox(params) { + const customAppearance = params.dict.get("AP"); + if (!(customAppearance instanceof Dict)) { + return; + } + const normalAppearance = customAppearance.get("N"); + if (!(normalAppearance instanceof Dict)) { + return; + } + const asValue = this._decodeFormValue(params.dict.get("AS")); + if (typeof asValue === "string") { + this.data.fieldValue = asValue; + } + const yes = this.data.fieldValue !== null && this.data.fieldValue !== "Off" ? this.data.fieldValue : "Yes"; + const exportValues = this._decodeFormValue(normalAppearance.getKeys()); + if (exportValues.length === 0) { + exportValues.push("Off", yes); + } else if (exportValues.length === 1) { + if (exportValues[0] === "Off") { + exportValues.push(yes); + } else { + exportValues.unshift("Off"); + } + } else if (exportValues.includes(yes)) { + exportValues.length = 0; + exportValues.push("Off", yes); + } else { + const otherYes = exportValues.find((v) => v !== "Off"); + exportValues.length = 0; + exportValues.push("Off", otherYes); + } + if (!exportValues.includes(this.data.fieldValue)) { + this.data.fieldValue = "Off"; + } + this.data.exportValue = exportValues[1]; + const checkedAppearance = normalAppearance.get(this.data.exportValue); + this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; + const uncheckedAppearance = normalAppearance.get("Off"); + this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; + if (this.checkedAppearance) { + this._streams.push(this.checkedAppearance); + } else { + this._getDefaultCheckedAppearance(params, "check"); + } + if (this.uncheckedAppearance) { + this._streams.push(this.uncheckedAppearance); + } + this._fallbackFontDict = this.fallbackFontDict; + if (this.data.defaultFieldValue === null) { + this.data.defaultFieldValue = "Off"; + } + } + _processRadioButton(params) { + this.data.buttonValue = null; + const fieldParent = params.dict.get("Parent"); + if (fieldParent instanceof Dict) { + this.parent = params.dict.getRaw("Parent"); + const fieldParentValue = fieldParent.get("V"); + if (fieldParentValue instanceof Name2) { + this.data.fieldValue = this._decodeFormValue(fieldParentValue); + } + } + const appearanceStates = params.dict.get("AP"); + if (!(appearanceStates instanceof Dict)) { + return; + } + const normalAppearance = appearanceStates.get("N"); + if (!(normalAppearance instanceof Dict)) { + return; + } + for (const key of normalAppearance.getKeys()) { + if (key !== "Off") { + this.data.buttonValue = this._decodeFormValue(key); + break; + } + } + const checkedAppearance = normalAppearance.get(this.data.buttonValue); + this.checkedAppearance = checkedAppearance instanceof BaseStream ? checkedAppearance : null; + const uncheckedAppearance = normalAppearance.get("Off"); + this.uncheckedAppearance = uncheckedAppearance instanceof BaseStream ? uncheckedAppearance : null; + if (this.checkedAppearance) { + this._streams.push(this.checkedAppearance); + } else { + this._getDefaultCheckedAppearance(params, "disc"); + } + if (this.uncheckedAppearance) { + this._streams.push(this.uncheckedAppearance); + } + this._fallbackFontDict = this.fallbackFontDict; + if (this.data.defaultFieldValue === null) { + this.data.defaultFieldValue = "Off"; + } + } + _processPushButton(params) { + const { + dict, + annotationGlobals + } = params; + if (!dict.has("A") && !dict.has("AA") && !this.data.alternativeText) { + warn2("Push buttons without action dictionaries are not supported"); + return; + } + this.data.isTooltipOnly = !dict.has("A") && !dict.has("AA"); + Catalog.parseDestDictionary({ + destDict: dict, + resultObj: this.data, + docBaseUrl: annotationGlobals.baseUrl, + docAttachments: annotationGlobals.attachments + }); + } + getFieldObject() { + let type = "button"; + let exportValues; + if (this.data.checkBox) { + type = "checkbox"; + exportValues = this.data.exportValue; + } else if (this.data.radioButton) { + type = "radiobutton"; + exportValues = this.data.buttonValue; + } + return { + id: this.data.id, + value: this.data.fieldValue || "Off", + defaultValue: this.data.defaultFieldValue, + exportValues, + editable: !this.data.readOnly, + name: this.data.fieldName, + rect: this.data.rect, + hidden: this.data.hidden, + actions: this.data.actions, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + type + }; + } + get fallbackFontDict() { + const dict = new Dict(); + dict.setIfName("BaseFont", "ZapfDingbats"); + dict.setIfName("Type", "FallbackType"); + dict.setIfName("Subtype", "FallbackType"); + dict.setIfName("Encoding", "ZapfDingbatsEncoding"); + return shadow2(this, "fallbackFontDict", dict); + } + }; + ChoiceWidgetAnnotation = class extends WidgetAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.indices = dict.getArray("I"); + this.hasIndices = Array.isArray(this.indices) && this.indices.length > 0; + this.data.options = []; + const options = getInheritableProperty({ + dict, + key: "Opt" + }); + if (Array.isArray(options)) { + for (let i = 0, ii = options.length; i < ii; i++) { + const option = xref.fetchIfRef(options[i]); + const isOptionArray = Array.isArray(option); + this.data.options[i] = { + exportValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[0]) : option), + displayValue: this._decodeFormValue(isOptionArray ? xref.fetchIfRef(option[1]) : option) + }; + } + } + if (!this.hasIndices) { + if (typeof this.data.fieldValue === "string") { + this.data.fieldValue = [this.data.fieldValue]; + } else { + this.data.fieldValue ||= []; + } + } else { + this.data.fieldValue = []; + const ii = this.data.options.length; + for (const i of this.indices) { + if (Number.isInteger(i) && i >= 0 && i < ii) { + this.data.fieldValue.push(this.data.options[i].exportValue); + } + } + } + if (this.data.options.length === 0 && this.data.fieldValue.length > 0) { + this.data.options = this.data.fieldValue.map((value) => ({ + exportValue: value, + displayValue: value + })); + } + this.data.combo = this.hasFieldFlag(AnnotationFieldFlag.COMBO); + this.data.multiSelect = this.hasFieldFlag(AnnotationFieldFlag.MULTISELECT); + this._hasText = true; + } + getFieldObject() { + const type = this.data.combo ? "combobox" : "listbox"; + const value = this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : null; + return { + id: this.data.id, + value, + defaultValue: this.data.defaultFieldValue, + editable: !this.data.readOnly, + name: this.data.fieldName, + rect: this.data.rect, + numItems: this.data.fieldValue.length, + multipleSelection: this.data.multiSelect, + hidden: this.data.hidden, + actions: this.data.actions, + items: this.data.options, + page: this.data.pageIndex, + strokeColor: this.data.borderColor, + fillColor: this.data.backgroundColor, + rotation: this.rotation, + type + }; + } + amendSavedDict(annotationStorage, dict) { + if (!this.hasIndices) { + return; + } + let values3 = annotationStorage?.get(this.data.id)?.value; + if (!Array.isArray(values3)) { + values3 = [values3]; + } + const indices = []; + const { + options + } = this.data; + for (let i = 0, j = 0, ii = options.length; i < ii; i++) { + if (options[i].exportValue === values3[j]) { + indices.push(i); + j += 1; + } + } + dict.set("I", indices); + } + async _getAppearance(evaluator, task, intent, annotationStorage) { + if (this.data.combo) { + return super._getAppearance(evaluator, task, intent, annotationStorage); + } + let exportedValue, rotation; + const storageEntry = annotationStorage?.get(this.data.id); + if (storageEntry) { + rotation = storageEntry.rotation; + exportedValue = storageEntry.value; + } + if (rotation === void 0 && exportedValue === void 0 && !this._needAppearances) { + return null; + } + if (exportedValue === void 0) { + exportedValue = this.data.fieldValue; + } else if (!Array.isArray(exportedValue)) { + exportedValue = [exportedValue]; + } + const defaultPadding = 1; + const defaultHPadding = 2; + let { + width: totalWidth, + height: totalHeight + } = this; + if (rotation === 90 || rotation === 270) { + [totalWidth, totalHeight] = [totalHeight, totalWidth]; + } + const lineCount = this.data.options.length; + const valueIndices = []; + for (let i = 0; i < lineCount; i++) { + const { + exportValue + } = this.data.options[i]; + if (exportedValue.includes(exportValue)) { + valueIndices.push(i); + } + } + if (!this._defaultAppearance) { + this.data.defaultAppearanceData = parseDefaultAppearance(this._defaultAppearance = "/Helvetica 0 Tf 0 g"); + } + const font = await WidgetAnnotation._getFontData(evaluator, task, this.data.defaultAppearanceData, this._fieldResources.mergedResources); + let defaultAppearance; + let { + fontSize + } = this.data.defaultAppearanceData; + if (!fontSize) { + const lineHeight2 = (totalHeight - defaultPadding) / lineCount; + let lineWidth = -1; + let value; + for (const { + displayValue + } of this.data.options) { + const width = this._getTextWidth(displayValue, font); + if (width > lineWidth) { + lineWidth = width; + value = displayValue; + } + } + [defaultAppearance, fontSize] = this._computeFontSize(lineHeight2, totalWidth - 2 * defaultHPadding, value, font, -1); + } else { + defaultAppearance = this._defaultAppearance; + } + const lineHeight = fontSize * LINE_FACTOR2; + const vPadding = (lineHeight - fontSize) / 2; + const numberOfVisibleLines = Math.floor(totalHeight / lineHeight); + let firstIndex = 0; + if (valueIndices.length > 0) { + const minIndex = Math.min(...valueIndices); + const maxIndex = Math.max(...valueIndices); + firstIndex = Math.max(0, maxIndex - numberOfVisibleLines + 1); + if (firstIndex > minIndex) { + firstIndex = minIndex; + } + } + const end = Math.min(firstIndex + numberOfVisibleLines + 1, lineCount); + const buf = ["/Tx BMC q", `1 1 ${totalWidth} ${totalHeight} re W n`]; + if (valueIndices.length) { + buf.push("0.600006 0.756866 0.854904 rg"); + for (const index2 of valueIndices) { + if (firstIndex <= index2 && index2 < end) { + buf.push(`1 ${totalHeight - (index2 - firstIndex + 1) * lineHeight} ${totalWidth} ${lineHeight} re f`); + } + } + } + buf.push("BT", defaultAppearance, `1 0 0 1 0 ${totalHeight} Tm`); + const prevInfo = { + shift: 0 + }; + for (let i = firstIndex; i < end; i++) { + const { + displayValue + } = this.data.options[i]; + const vpadding = i === firstIndex ? vPadding : 0; + buf.push(this._renderText(displayValue, font, fontSize, totalWidth, 0, prevInfo, defaultHPadding, -lineHeight + vpadding)); + } + buf.push("ET Q EMC"); + return buf.join("\n"); + } + }; + SignatureWidgetAnnotation = class extends WidgetAnnotation { + constructor(params) { + super(params); + this.data.fieldValue = null; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = !this.data.hasOwnCanvas; + } + getFieldObject() { + return { + id: this.data.id, + value: null, + page: this.data.pageIndex, + type: "signature" + }; + } + }; + TextAnnotation = class extends MarkupAnnotation { + constructor(params) { + const DEFAULT_ICON_SIZE = 22; + super(params); + this.data.noRotate = true; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const { + dict + } = params; + this.data.annotationType = AnnotationType2.TEXT; + if (this.data.hasAppearance) { + this.data.name = "NoIcon"; + } else { + this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE; + this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE; + this.data.name = dict.has("Name") ? dict.get("Name").name : "Note"; + } + if (dict.has("State")) { + this.data.state = dict.get("State") || null; + this.data.stateModel = dict.get("StateModel") || null; + } else { + this.data.state = null; + this.data.stateModel = null; + } + } + }; + LinkAnnotation = class extends Annotation { + constructor(params) { + super(params); + const { + dict, + annotationGlobals + } = params; + this.data.annotationType = AnnotationType2.LINK; + this.data.noHTML = false; + const quadPoints = getQuadPoints(dict, this.rectangle); + if (quadPoints) { + this.data.quadPoints = quadPoints; + } + this.data.borderColor ||= this.data.color; + Catalog.parseDestDictionary({ + destDict: dict, + resultObj: this.data, + docBaseUrl: annotationGlobals.baseUrl, + docAttachments: annotationGlobals.attachments + }); + } + get overlaysTextContent() { + return true; + } + }; + PopupAnnotation = class extends Annotation { + constructor(params) { + super(params); + const { + dict + } = params; + this.data.annotationType = AnnotationType2.POPUP; + this.data.noHTML = false; + if (this.width === 0 || this.height === 0) { + this.data.rect = null; + } + let parentItem = dict.get("Parent"); + if (!parentItem) { + warn2("Popup annotation has a missing or invalid parent annotation."); + return; + } + this.data.parentRect = lookupNormalRect(parentItem.getArray("Rect"), null); + this.data.creationDate = parentItem.get("CreationDate") || ""; + const rt = parentItem.get("RT"); + if (isName(rt, AnnotationReplyType.GROUP)) { + parentItem = parentItem.get("IRT"); + } + if (!parentItem.has("M")) { + this.data.modificationDate = null; + } else { + this.setModificationDate(parentItem.get("M")); + this.data.modificationDate = this.modificationDate; + } + if (!parentItem.has("C")) { + this.data.color = null; + } else { + this.setColor(parentItem.getArray("C")); + this.data.color = this.color; + } + if (!this.viewable) { + const parentFlags = parentItem.get("F"); + if (this._isViewable(parentFlags)) { + this.setFlags(parentFlags); + } + } + this.setTitle(parentItem.get("T")); + this.data.titleObj = this._title; + this.setContents(parentItem.get("Contents")); + this.data.contentsObj = this._contents; + if (parentItem.has("RC")) { + this.data.richText = XFAFactory.getRichTextAsHtml(parentItem.get("RC")); + } + this.data.open = !!dict.get("Open"); + } + static createNewDict(annotation, xref, _params) { + const { + oldAnnotation, + rect, + parent + } = annotation; + const popup = oldAnnotation || new Dict(xref); + popup.setIfNotExists("Type", Name2.get("Annot")); + popup.setIfNotExists("Subtype", Name2.get("Popup")); + popup.setIfNotExists("Open", false); + popup.setIfArray("Rect", rect); + popup.set("Parent", parent); + return popup; + } + static async createNewAppearanceStream(annotation, xref, params) { + return null; + } + }; + FreeTextAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.hasOwnCanvas = this.data.noRotate; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + const { + annotationGlobals, + evaluatorOptions, + xref + } = params; + this.data.annotationType = AnnotationType2.FREETEXT; + this.setDefaultAppearance(params); + this._hasAppearance = !!this.appearance; + if (this._hasAppearance) { + const { + fontColor, + fontSize + } = parseAppearanceStream(this.appearance, evaluatorOptions, xref, annotationGlobals.globalColorSpaceCache); + this.data.defaultAppearanceData.fontColor = fontColor; + this.data.defaultAppearanceData.fontSize = fontSize || 10; + } else { + this.data.defaultAppearanceData.fontSize ||= 10; + const { + fontColor, + fontSize + } = this.data.defaultAppearanceData; + if (this._contents.str) { + this.data.textContent = this._contents.str.split(/\r\n?|\n/).map((line2) => line2.trimEnd()); + const { + coords, + bbox, + matrix + } = FakeUnicodeFont.getFirstPositionInfo(this.rectangle, this.rotation, fontSize); + this.data.textPosition = this._transformPoint(coords, bbox, matrix); + } + if (this._isOffscreenCanvasSupported) { + const strokeAlpha = params.dict.get("CA"); + const fakeUnicodeFont = new FakeUnicodeFont(xref, "sans-serif"); + this.appearance = fakeUnicodeFont.createAppearance(this._contents.str, this.rectangle, this.rotation, fontSize, fontColor, strokeAlpha); + this._streams.push(this.appearance); + } else { + warn2("FreeTextAnnotation: OffscreenCanvas is not supported, annotation may not render correctly."); + } + } + } + get hasTextContent() { + return this._hasAppearance; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + color, + date: date6, + fontSize, + oldAnnotation, + rect, + rotation, + user, + value + } = annotation; + const freetext = oldAnnotation || new Dict(xref); + freetext.setIfNotExists("Type", Name2.get("Annot")); + freetext.setIfNotExists("Subtype", Name2.get("FreeText")); + freetext.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date6)}`); + if (oldAnnotation) { + freetext.delete("RC"); + } + freetext.setIfArray("Rect", rect); + const da = `/Helv ${fontSize} Tf ${getPdfColor(color, true)}`; + freetext.set("DA", da); + freetext.setIfDefined("Contents", stringToAsciiOrUTF16BE(value)); + freetext.setIfNotExists("F", 4); + freetext.setIfNotExists("Border", [0, 0, 0]); + freetext.setIfNumber("Rotate", rotation); + freetext.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + freetext.set("AP", n); + n.set("N", apRef || ap); + } + return freetext; + } + static async createNewAppearanceStream(annotation, xref, params) { + const { + baseFontRef, + evaluator, + task + } = params; + const { + color, + fontSize, + rect, + rotation, + value + } = annotation; + if (!color) { + return null; + } + const resources = new Dict(xref); + const font = new Dict(xref); + if (baseFontRef) { + font.set("Helv", baseFontRef); + } else { + const baseFont = new Dict(xref); + baseFont.setIfName("BaseFont", "Helvetica"); + baseFont.setIfName("Type", "Font"); + baseFont.setIfName("Subtype", "Type1"); + baseFont.setIfName("Encoding", "WinAnsiEncoding"); + font.set("Helv", baseFont); + } + resources.set("Font", font); + const helv = await WidgetAnnotation._getFontData(evaluator, task, { + fontName: "Helv", + fontSize + }, resources); + const [x1, y1, x2, y2] = rect; + let w = x2 - x1; + let h = y2 - y1; + if (rotation % 180 !== 0) { + [w, h] = [h, w]; + } + const lines = value.split("\n"); + const scale = fontSize / 1e3; + let totalWidth = -Infinity; + const encodedLines = []; + for (let line2 of lines) { + const encoded = helv.encodeString(line2); + if (encoded.length > 1) { + return null; + } + line2 = encoded.join(""); + encodedLines.push(line2); + let lineWidth = 0; + const glyphs = helv.charsToGlyphs(line2); + for (const glyph of glyphs) { + lineWidth += glyph.width * scale; + } + totalWidth = Math.max(totalWidth, lineWidth); + } + let hscale = 1; + if (totalWidth > w) { + hscale = w / totalWidth; + } + let vscale = 1; + const lineHeight = LINE_FACTOR2 * fontSize; + const lineAscent = (LINE_FACTOR2 - LINE_DESCENT_FACTOR2) * fontSize; + const totalHeight = lineHeight * lines.length; + if (totalHeight > h) { + vscale = h / totalHeight; + } + const fscale = Math.min(hscale, vscale); + const newFontSize = fontSize * fscale; + let firstPoint, clipBox, matrix; + switch (rotation) { + case 0: + matrix = [1, 0, 0, 1]; + clipBox = [rect[0], rect[1], w, h]; + firstPoint = [rect[0], rect[3] - lineAscent]; + break; + case 90: + matrix = [0, 1, -1, 0]; + clipBox = [rect[1], -rect[2], w, h]; + firstPoint = [rect[1], -rect[0] - lineAscent]; + break; + case 180: + matrix = [-1, 0, 0, -1]; + clipBox = [-rect[2], -rect[3], w, h]; + firstPoint = [-rect[2], -rect[1] - lineAscent]; + break; + case 270: + matrix = [0, -1, 1, 0]; + clipBox = [-rect[3], rect[0], w, h]; + firstPoint = [-rect[3], rect[2] - lineAscent]; + break; + } + const buffer2 = ["q", `${matrix.join(" ")} 0 0 cm`, `${clipBox.join(" ")} re W n`, `BT`, `${getPdfColor(color, true)}`, `0 Tc /Helv ${numberToString(newFontSize)} Tf`]; + buffer2.push(`${firstPoint.join(" ")} Td (${escapeString(encodedLines[0])}) Tj`); + const vShift = numberToString(lineHeight); + for (let i = 1, ii = encodedLines.length; i < ii; i++) { + const line2 = encodedLines[i]; + buffer2.push(`0 -${vShift} Td (${escapeString(line2)}) Tj`); + } + buffer2.push("ET", "Q"); + const appearance = buffer2.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Resources", resources); + appearanceStreamDict.set("Matrix", [1, 0, 0, 1, -rect[0], -rect[1]]); + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + }; + LineAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.LINE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const lineCoordinates = lookupRect(dict.getArray("L"), [0, 0, 0, 0]); + this.data.lineCoordinates = Util2.normalizeRect(lineCoordinates); + this.setLineEndings(dict.getArray("LE")); + this.data.lineEndings = this.lineEndings; + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; + const bbox = [this.data.lineCoordinates[0] - borderAdjust, this.data.lineCoordinates[1] - borderAdjust, this.data.lineCoordinates[2] + borderAdjust, this.data.lineCoordinates[3] + borderAdjust]; + if (!Util2.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer2, points) => { + buffer2.push(`${lineCoordinates[0]} ${lineCoordinates[1]} m`, `${lineCoordinates[2]} ${lineCoordinates[3]} l`, "S"); + return [points[0] - borderWidth, points[7] - borderWidth, points[2] + borderWidth, points[3] + borderWidth]; + } + }); + } + } + }; + SquareAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.SQUARE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + if (this.borderStyle.width === 0 && !fillColor) { + return; + } + this._setDefaultAppearance({ + xref, + extra: `${this.borderStyle.width} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer2, points) => { + const x = points[4] + this.borderStyle.width / 2; + const y = points[5] + this.borderStyle.width / 2; + const width = points[6] - points[4] - this.borderStyle.width; + const height = points[3] - points[7] - this.borderStyle.width; + buffer2.push(`${x} ${y} ${width} ${height} re`); + if (fillColor) { + buffer2.push("B"); + } else { + buffer2.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } + }; + CircleAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.CIRCLE; + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const interiorColor = getRgbColor(dict.getArray("IC"), null); + const fillColor = getPdfColorArray(interiorColor); + const fillAlpha = fillColor ? strokeAlpha : null; + if (this.borderStyle.width === 0 && !fillColor) { + return; + } + const controlPointsDistance = 4 / 3 * Math.tan(Math.PI / (2 * 4)); + this._setDefaultAppearance({ + xref, + extra: `${this.borderStyle.width} w`, + strokeColor, + fillColor, + strokeAlpha, + fillAlpha, + pointsCallback: (buffer2, points) => { + const x0 = points[0] + this.borderStyle.width / 2; + const y0 = points[1] - this.borderStyle.width / 2; + const x1 = points[6] - this.borderStyle.width / 2; + const y1 = points[7] + this.borderStyle.width / 2; + const xMid = x0 + (x1 - x0) / 2; + const yMid = y0 + (y1 - y0) / 2; + const xOffset = (x1 - x0) / 2 * controlPointsDistance; + const yOffset = (y1 - y0) / 2 * controlPointsDistance; + buffer2.push(`${xMid} ${y1} m`, `${xMid + xOffset} ${y1} ${x1} ${yMid + yOffset} ${x1} ${yMid} c`, `${x1} ${yMid - yOffset} ${xMid + xOffset} ${y0} ${xMid} ${y0} c`, `${xMid - xOffset} ${y0} ${x0} ${yMid - yOffset} ${x0} ${yMid} c`, `${x0} ${yMid + yOffset} ${xMid - xOffset} ${y1} ${xMid} ${y1} c`, "h"); + if (fillColor) { + buffer2.push("B"); + } else { + buffer2.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } + }; + PolylineAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.POLYLINE; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + this.data.vertices = null; + if (!(this instanceof PolygonAnnotation)) { + this.setLineEndings(dict.getArray("LE")); + this.data.lineEndings = this.lineEndings; + } + const rawVertices = dict.getArray("Vertices"); + if (!isNumberArray(rawVertices, null)) { + return; + } + const vertices = this.data.vertices = Float32Array.from(rawVertices); + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + let fillColor = getRgbColor(dict.getArray("IC"), null); + if (fillColor) { + fillColor = getPdfColorArray(fillColor); + } + let operator; + if (fillColor) { + if (this.color) { + operator = fillColor.every((c, i) => c === strokeColor[i]) ? "f" : "B"; + } else { + operator = "f"; + } + } else { + operator = "S"; + } + const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + Util2.rectBoundingBox(vertices[i] - borderAdjust, vertices[i + 1] - borderAdjust, vertices[i] + borderAdjust, vertices[i + 1] + borderAdjust, bbox); + } + if (!Util2.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + strokeAlpha, + fillColor, + fillAlpha: fillColor ? strokeAlpha : null, + pointsCallback: (buffer2, points) => { + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + buffer2.push(`${vertices[i]} ${vertices[i + 1]} ${i === 0 ? "m" : "l"}`); + } + buffer2.push(operator); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } + }; + PolygonAnnotation = class extends PolylineAnnotation { + constructor(params) { + super(params); + this.data.annotationType = AnnotationType2.POLYGON; + } + }; + CaretAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.annotationType = AnnotationType2.CARET; + } + }; + InkAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.INK; + this.data.inkLists = []; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + this.data.opacity = dict.get("CA") || 1; + const rawInkLists = dict.getArray("InkList"); + if (!Array.isArray(rawInkLists)) { + return; + } + for (let i = 0, ii = rawInkLists.length; i < ii; ++i) { + if (!Array.isArray(rawInkLists[i])) { + continue; + } + const inkList = new Float32Array(rawInkLists[i].length); + this.data.inkLists.push(inkList); + for (let j = 0, jj = rawInkLists[i].length; j < jj; j += 2) { + const x = xref.fetchIfRef(rawInkLists[i][j]), y = xref.fetchIfRef(rawInkLists[i][j + 1]); + if (typeof x === "number" && typeof y === "number") { + inkList[j] = x; + inkList[j + 1] = y; + } + } + } + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + const borderWidth = this.borderStyle.width || 1, borderAdjust = 2 * borderWidth; + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + for (const inkList of this.data.inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + Util2.rectBoundingBox(inkList[i] - borderAdjust, inkList[i + 1] - borderAdjust, inkList[i] + borderAdjust, inkList[i + 1] + borderAdjust, bbox); + } + } + if (!Util2.intersect(this.rectangle, bbox)) { + this.rectangle = bbox; + } + this._setDefaultAppearance({ + xref, + extra: `${borderWidth} w`, + strokeColor, + strokeAlpha, + pointsCallback: (buffer2, points) => { + for (const inkList of this.data.inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + buffer2.push(`${inkList[i]} ${inkList[i + 1]} ${i === 0 ? "m" : "l"}`); + } + buffer2.push("S"); + } + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + oldAnnotation, + color, + date: date6, + opacity, + paths, + outlines, + rect, + rotation, + thickness, + user + } = annotation; + const ink = oldAnnotation || new Dict(xref); + ink.setIfNotExists("Type", Name2.get("Annot")); + ink.setIfNotExists("Subtype", Name2.get("Ink")); + ink.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date6)}`); + ink.setIfArray("Rect", rect); + ink.setIfArray("InkList", outlines?.points || paths?.points); + ink.setIfNotExists("F", 4); + ink.setIfNumber("Rotate", rotation); + ink.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (outlines) { + ink.setIfName("IT", "InkHighlight"); + } + if (thickness > 0) { + const bs = new Dict(xref); + ink.set("BS", bs); + bs.set("W", thickness); + } + ink.setIfArray("C", getPdfColorArray(color)); + ink.setIfNumber("CA", opacity); + if (ap || apRef) { + const n = new Dict(xref); + ink.set("AP", n); + n.set("N", apRef || ap); + } + return ink; + } + static async createNewAppearanceStream(annotation, xref, params) { + if (annotation.outlines) { + return this.createNewAppearanceStreamForHighlight(annotation, xref, params); + } + const { + color, + rect, + paths, + thickness, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, false)}`]; + if (opacity !== 1) { + appearanceBuffer.push("/R0 gs"); + } + for (const outline of paths.lines) { + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + if (isNaN(outline[i])) { + appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + if (outline.length === 6) { + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} l`); + } + } + appearanceBuffer.push("S"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + if (opacity !== 1) { + const resources = new Dict(xref); + const extGState = new Dict(xref); + const r0 = new Dict(xref); + r0.set("CA", opacity); + r0.setIfName("Type", "ExtGState"); + extGState.set("R0", r0); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + static async createNewAppearanceStreamForHighlight(annotation, xref, params) { + const { + color, + rect, + outlines: { + outline + }, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; + appearanceBuffer.push(`${numberToString(outline[4])} ${numberToString(outline[5])} m`); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + if (isNaN(outline[i])) { + appearanceBuffer.push(`${numberToString(outline[i + 4])} ${numberToString(outline[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + appearanceBuffer.push("h f"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(xref); + const extGState = new Dict(xref); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + const r0 = new Dict(xref); + extGState.set("R0", r0); + r0.setIfName("BM", "Multiply"); + if (opacity !== 1) { + r0.set("ca", opacity); + r0.setIfName("Type", "ExtGState"); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + }; + HighlightAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.HIGHLIGHT; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + this.data.opacity = dict.get("CA") || 1; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + const resources = this.appearance?.dict.get("Resources"); + if (!this.appearance || !resources?.has("ExtGState")) { + if (this.appearance) { + warn2("HighlightAnnotation - ignoring built-in appearance stream."); + } + const fillColor = getPdfColorArray(this.color, [1, 1, 0]); + const fillAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + fillColor, + blendMode: "Multiply", + fillAlpha, + pointsCallback: (buffer2, points) => { + buffer2.push(`${points[0]} ${points[1]} m`, `${points[2]} ${points[3]} l`, `${points[6]} ${points[7]} l`, `${points[4]} ${points[5]} l`, "f"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + color, + date: date6, + oldAnnotation, + opacity, + rect, + rotation, + user, + quadPoints + } = annotation; + const highlight = oldAnnotation || new Dict(xref); + highlight.setIfNotExists("Type", Name2.get("Annot")); + highlight.setIfNotExists("Subtype", Name2.get("Highlight")); + highlight.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date6)}`); + highlight.setIfArray("Rect", rect); + highlight.setIfNotExists("F", 4); + highlight.setIfNotExists("Border", [0, 0, 0]); + highlight.setIfNumber("Rotate", rotation); + highlight.setIfArray("QuadPoints", quadPoints); + highlight.setIfArray("C", getPdfColorArray(color)); + highlight.setIfNumber("CA", opacity); + highlight.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + highlight.set("AP", n); + n.set("N", apRef || ap); + } + return highlight; + } + static async createNewAppearanceStream(annotation, xref, params) { + const { + color, + rect, + outlines, + opacity + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${getPdfColor(color, true)}`, "/R0 gs"]; + const buffer2 = []; + for (const outline of outlines) { + buffer2.length = 0; + buffer2.push(`${numberToString(outline[0])} ${numberToString(outline[1])} m`); + for (let i = 2, ii = outline.length; i < ii; i += 2) { + buffer2.push(`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`); + } + buffer2.push("h"); + appearanceBuffer.push(buffer2.join("\n")); + } + appearanceBuffer.push("f*"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const resources = new Dict(xref); + const extGState = new Dict(xref); + resources.set("ExtGState", extGState); + appearanceStreamDict.set("Resources", resources); + const r0 = new Dict(xref); + extGState.set("R0", r0); + r0.setIfName("BM", "Multiply"); + if (opacity !== 1) { + r0.set("ca", opacity); + r0.setIfName("Type", "ExtGState"); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + }; + UnderlineAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.UNDERLINE; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 0.571 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer2, points) => { + buffer2.push(`${points[4]} ${points[5] + 1.3} m`, `${points[6]} ${points[7] + 1.3} l`, "S"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } + }; + SquigglyAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.SQUIGGLY; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 1 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer2, points) => { + const dy = (points[1] - points[5]) / 6; + let shift = dy; + let x = points[4]; + const y = points[5]; + const xEnd = points[6]; + buffer2.push(`${x} ${y + shift} m`); + do { + x += 2; + shift = shift === 0 ? dy : 0; + buffer2.push(`${x} ${y + shift} l`); + } while (x < xEnd); + buffer2.push("S"); + return [points[4], y - 2 * dy, xEnd, y + 2 * dy]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } + }; + StrikeOutAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + this.data.annotationType = AnnotationType2.STRIKEOUT; + const quadPoints = this.data.quadPoints = getQuadPoints(dict, null); + if (quadPoints) { + if (!this.appearance) { + const strokeColor = getPdfColorArray(this.color, [0, 0, 0]); + const strokeAlpha = dict.get("CA"); + this._setDefaultAppearance({ + xref, + extra: "[] 0 d 1 w", + strokeColor, + strokeAlpha, + pointsCallback: (buffer2, points) => { + buffer2.push(`${(points[0] + points[4]) / 2} ${(points[1] + points[5]) / 2} m`, `${(points[2] + points[6]) / 2} ${(points[3] + points[7]) / 2} l`, "S"); + return [points[0], points[7], points[2], points[3]]; + } + }); + } + } else { + this.data.popupRef = null; + } + } + get overlaysTextContent() { + return true; + } + }; + StampAnnotation = class extends MarkupAnnotation { + #savedHasOwnCanvas = null; + constructor(params) { + super(params); + this.data.annotationType = AnnotationType2.STAMP; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.isEditable = !this.data.noHTML; + this.data.noHTML = false; + } + mustBeViewedWhenEditing(isEditing, modifiedIds = null) { + if (isEditing) { + if (!this.data.isEditable) { + return true; + } + this.#savedHasOwnCanvas ??= this.data.hasOwnCanvas; + this.data.hasOwnCanvas = true; + return true; + } + if (this.#savedHasOwnCanvas !== null) { + this.data.hasOwnCanvas = this.#savedHasOwnCanvas; + this.#savedHasOwnCanvas = null; + } + return !modifiedIds?.has(this.data.id); + } + static async createImage(bitmap, xref) { + const { + width, + height + } = bitmap; + const canvas = new OffscreenCanvas(width, height); + const ctx = canvas.getContext("2d", { + alpha: true + }); + ctx.drawImage(bitmap, 0, 0); + const data = ctx.getImageData(0, 0, width, height).data; + const buf32 = new Uint32Array(data.buffer); + const hasAlpha = buf32.some(FeatureTest2.isLittleEndian ? (x) => x >>> 24 !== 255 : (x) => (x & 255) !== 255); + if (hasAlpha) { + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, width, height); + ctx.drawImage(bitmap, 0, 0); + } + const jpegBufferPromise = canvas.convertToBlob({ + type: "image/jpeg", + quality: 1 + }).then((blob) => blob.arrayBuffer()); + const xobjectName = Name2.get("XObject"); + const imageName = Name2.get("Image"); + const image = new Dict(xref); + image.set("Type", xobjectName); + image.set("Subtype", imageName); + image.set("BitsPerComponent", 8); + image.setIfName("ColorSpace", "DeviceRGB"); + image.setIfName("Filter", "DCTDecode"); + image.set("BBox", [0, 0, width, height]); + image.set("Width", width); + image.set("Height", height); + let smaskStream = null; + if (hasAlpha) { + const alphaBuffer = new Uint8Array(buf32.length); + if (FeatureTest2.isLittleEndian) { + for (let i = 0, ii = buf32.length; i < ii; i++) { + alphaBuffer[i] = buf32[i] >>> 24; + } + } else { + for (let i = 0, ii = buf32.length; i < ii; i++) { + alphaBuffer[i] = buf32[i] & 255; + } + } + const smask = new Dict(xref); + smask.set("Type", xobjectName); + smask.set("Subtype", imageName); + smask.set("BitsPerComponent", 8); + smask.setIfName("ColorSpace", "DeviceGray"); + smask.set("Width", width); + smask.set("Height", height); + smaskStream = new Stream3(alphaBuffer, 0, 0, smask); + } + const imageStream = new Stream3(await jpegBufferPromise, 0, 0, image); + return { + imageStream, + smaskStream, + width, + height + }; + } + static createNewDict(annotation, xref, { + apRef, + ap + }) { + const { + date: date6, + oldAnnotation, + rect, + rotation, + user + } = annotation; + const stamp = oldAnnotation || new Dict(xref); + stamp.setIfNotExists("Type", Name2.get("Annot")); + stamp.setIfNotExists("Subtype", Name2.get("Stamp")); + stamp.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate(date6)}`); + stamp.setIfArray("Rect", rect); + stamp.setIfNotExists("F", 4); + stamp.setIfNotExists("Border", [0, 0, 0]); + stamp.setIfNumber("Rotate", rotation); + stamp.setIfDefined("T", stringToAsciiOrUTF16BE(user)); + if (apRef || ap) { + const n = new Dict(xref); + stamp.set("AP", n); + n.set("N", apRef || ap); + } + return stamp; + } + static async #createNewAppearanceStreamForDrawing(annotation, xref) { + const { + areContours, + color, + rect, + lines, + thickness + } = annotation; + if (!color) { + return null; + } + const appearanceBuffer = [`${thickness} w 1 J 1 j`, `${getPdfColor(color, areContours)}`]; + for (const line2 of lines) { + appearanceBuffer.push(`${numberToString(line2[4])} ${numberToString(line2[5])} m`); + for (let i = 6, ii = line2.length; i < ii; i += 6) { + if (isNaN(line2[i])) { + appearanceBuffer.push(`${numberToString(line2[i + 4])} ${numberToString(line2[i + 5])} l`); + } else { + const [c1x, c1y, c2x, c2y, x, y] = line2.slice(i, i + 6); + appearanceBuffer.push([c1x, c1y, c2x, c2y, x, y].map(numberToString).join(" ") + " c"); + } + } + if (line2.length === 6) { + appearanceBuffer.push(`${numberToString(line2[4])} ${numberToString(line2[5])} l`); + } + } + appearanceBuffer.push(areContours ? "F" : "S"); + const appearance = appearanceBuffer.join("\n"); + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", rect); + appearanceStreamDict.set("Length", appearance.length); + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + static async createNewAppearanceStream(annotation, xref, params) { + if (annotation.oldAnnotation) { + return null; + } + if (annotation.isSignature) { + return this.#createNewAppearanceStreamForDrawing(annotation, xref); + } + const { + rotation + } = annotation; + const { + imageRef, + width, + height + } = params.image; + const resources = new Dict(xref); + const xobject = new Dict(xref); + resources.set("XObject", xobject); + xobject.set("Im0", imageRef); + const appearance = `q ${width} 0 0 ${height} 0 0 cm /Im0 Do Q`; + const appearanceStreamDict = new Dict(xref); + appearanceStreamDict.set("FormType", 1); + appearanceStreamDict.setIfName("Subtype", "Form"); + appearanceStreamDict.setIfName("Type", "XObject"); + appearanceStreamDict.set("BBox", [0, 0, width, height]); + appearanceStreamDict.set("Resources", resources); + if (rotation) { + const matrix = getRotationMatrix(rotation, width, height); + appearanceStreamDict.set("Matrix", matrix); + } + const ap = new StringStream(appearance); + ap.dict = appearanceStreamDict; + return ap; + } + }; + FileAttachmentAnnotation = class extends MarkupAnnotation { + constructor(params) { + super(params); + const { + dict, + xref + } = params; + const file2 = new FileSpec(dict.get("FS"), xref); + this.data.annotationType = AnnotationType2.FILEATTACHMENT; + this.data.hasOwnCanvas = this.data.noRotate; + this.data.noHTML = false; + this.data.file = file2.serializable; + const name = dict.get("Name"); + this.data.name = name instanceof Name2 ? stringToPDFString(name.name) : "PushPin"; + const fillAlpha = dict.get("ca"); + this.data.fillAlpha = typeof fillAlpha === "number" && fillAlpha >= 0 && fillAlpha <= 1 ? fillAlpha : null; + } + }; + PARAMS = { + get r() { + return shadow2(this, "r", new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21])); + }, + get k() { + return shadow2(this, "k", new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551])); + } + }; + DatasetXMLParser = class extends SimpleXMLParser { + constructor(options) { + super(options); + this.node = null; + } + onEndElement(name) { + const node2 = super.onEndElement(name); + if (node2 && name === "xfa:datasets") { + this.node = node2; + throw new Error("Aborting DatasetXMLParser."); + } + } + }; + DatasetReader = class { + constructor(data) { + if (data.datasets) { + this.node = new SimpleXMLParser({ + hasAttributes: true + }).parseFromString(data.datasets).documentElement; + } else { + const parser = new DatasetXMLParser({ + hasAttributes: true + }); + try { + parser.parseFromString(data["xdp:xdp"]); + } catch { + } + this.node = parser.node; + } + } + getValue(path2) { + if (!this.node || !path2) { + return ""; + } + const node2 = this.node.searchNode(parseXFAPath(path2), 0); + if (!node2) { + return ""; + } + const first2 = node2.firstChild; + if (first2?.nodeName === "value") { + return node2.children.map((child) => decodeString(child.textContent)); + } + return decodeString(node2.textContent); + } + }; + SingleIntersector = class { + #annotation; + #minX = Infinity; + #minY = Infinity; + #maxX = -Infinity; + #maxY = -Infinity; + #quadPoints = null; + #text = []; + #extraChars = []; + #lastIntersectingQuadIndex = -1; + #canTakeExtraChars = false; + constructor(annotation) { + this.#annotation = annotation; + const quadPoints = annotation.data.quadPoints; + if (!quadPoints) { + [this.#minX, this.#minY, this.#maxX, this.#maxY] = annotation.data.rect; + return; + } + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + this.#minX = Math.min(this.#minX, quadPoints[i]); + this.#maxX = Math.max(this.#maxX, quadPoints[i + 2]); + this.#minY = Math.min(this.#minY, quadPoints[i + 5]); + this.#maxY = Math.max(this.#maxY, quadPoints[i + 1]); + } + if (quadPoints.length > 8) { + this.#quadPoints = quadPoints; + } + } + overlaps(other) { + return !(this.#minX >= other.#maxX || this.#maxX <= other.#minX || this.#minY >= other.#maxY || this.#maxY <= other.#minY); + } + #intersects(x, y) { + if (this.#minX >= x || this.#maxX <= x || this.#minY >= y || this.#maxY <= y) { + return false; + } + const quadPoints = this.#quadPoints; + if (!quadPoints) { + return true; + } + if (this.#lastIntersectingQuadIndex >= 0) { + const i = this.#lastIntersectingQuadIndex; + if (!(quadPoints[i] >= x || quadPoints[i + 2] <= x || quadPoints[i + 5] >= y || quadPoints[i + 1] <= y)) { + return true; + } + this.#lastIntersectingQuadIndex = -1; + } + for (let i = 0, ii = quadPoints.length; i < ii; i += 8) { + if (!(quadPoints[i] >= x || quadPoints[i + 2] <= x || quadPoints[i + 5] >= y || quadPoints[i + 1] <= y)) { + this.#lastIntersectingQuadIndex = i; + return true; + } + } + return false; + } + addGlyph(x, y, glyph) { + if (!this.#intersects(x, y)) { + this.disableExtraChars(); + return false; + } + if (this.#extraChars.length > 0) { + this.#text.push(this.#extraChars.join("")); + this.#extraChars.length = 0; + } + this.#text.push(glyph); + this.#canTakeExtraChars = true; + return true; + } + addExtraChar(char2) { + if (this.#canTakeExtraChars) { + this.#extraChars.push(char2); + } + } + disableExtraChars() { + if (!this.#canTakeExtraChars) { + return; + } + this.#canTakeExtraChars = false; + this.#extraChars.length = 0; + } + setText() { + this.#annotation.data.overlaidText = this.#text.join(""); + } + }; + Intersector = class { + #intersectors = /* @__PURE__ */ new Map(); + constructor(annotations) { + for (const annotation of annotations) { + if (!annotation.data.quadPoints && !annotation.data.rect) { + continue; + } + const intersector = new SingleIntersector(annotation); + for (const [otherIntersector, overlapping] of this.#intersectors) { + if (otherIntersector.overlaps(intersector)) { + if (!overlapping) { + this.#intersectors.set(otherIntersector, /* @__PURE__ */ new Set([intersector])); + } else { + overlapping.add(intersector); + } + } + } + this.#intersectors.set(intersector, null); + } + } + addGlyph(transform2, width, height, glyph) { + const x = transform2[4] + width / 2; + const y = transform2[5] + height / 2; + let overlappingIntersectors; + for (const [intersector, overlapping] of this.#intersectors) { + if (overlappingIntersectors) { + if (overlappingIntersectors.has(intersector)) { + intersector.addGlyph(x, y, glyph); + } else { + intersector.disableExtraChars(); + } + continue; + } + if (!intersector.addGlyph(x, y, glyph)) { + continue; + } + overlappingIntersectors = overlapping; + } + } + addExtraChar(char2) { + for (const intersector of this.#intersectors.keys()) { + intersector.addExtraChar(char2); + } + } + setText() { + for (const intersector of this.#intersectors.keys()) { + intersector.setText(); + } + } + }; + Word64 = class { + constructor(highInteger, lowInteger) { + this.high = highInteger | 0; + this.low = lowInteger | 0; + } + and(word) { + this.high &= word.high; + this.low &= word.low; + } + xor(word) { + this.high ^= word.high; + this.low ^= word.low; + } + shiftRight(places) { + if (places >= 32) { + this.low = this.high >>> places - 32 | 0; + this.high = 0; + } else { + this.low = this.low >>> places | this.high << 32 - places; + this.high = this.high >>> places | 0; + } + } + rotateRight(places) { + let low, high; + if (places & 32) { + high = this.low; + low = this.high; + } else { + low = this.low; + high = this.high; + } + places &= 31; + this.low = low >>> places | high << 32 - places; + this.high = high >>> places | low << 32 - places; + } + not() { + this.high = ~this.high; + this.low = ~this.low; + } + add(word) { + const lowAdd = (this.low >>> 0) + (word.low >>> 0); + let highAdd = (this.high >>> 0) + (word.high >>> 0); + if (lowAdd > 4294967295) { + highAdd += 1; + } + this.low = lowAdd | 0; + this.high = highAdd | 0; + } + copyTo(bytes, offset) { + bytes[offset] = this.high >>> 24 & 255; + bytes[offset + 1] = this.high >> 16 & 255; + bytes[offset + 2] = this.high >> 8 & 255; + bytes[offset + 3] = this.high & 255; + bytes[offset + 4] = this.low >>> 24 & 255; + bytes[offset + 5] = this.low >> 16 & 255; + bytes[offset + 6] = this.low >> 8 & 255; + bytes[offset + 7] = this.low & 255; + } + assign(word) { + this.high = word.high; + this.low = word.low; + } + }; + calculate_sha_other_PARAMS = { + get k() { + return shadow2(this, "k", [new Word64(1116352408, 3609767458), new Word64(1899447441, 602891725), new Word64(3049323471, 3964484399), new Word64(3921009573, 2173295548), new Word64(961987163, 4081628472), new Word64(1508970993, 3053834265), new Word64(2453635748, 2937671579), new Word64(2870763221, 3664609560), new Word64(3624381080, 2734883394), new Word64(310598401, 1164996542), new Word64(607225278, 1323610764), new Word64(1426881987, 3590304994), new Word64(1925078388, 4068182383), new Word64(2162078206, 991336113), new Word64(2614888103, 633803317), new Word64(3248222580, 3479774868), new Word64(3835390401, 2666613458), new Word64(4022224774, 944711139), new Word64(264347078, 2341262773), new Word64(604807628, 2007800933), new Word64(770255983, 1495990901), new Word64(1249150122, 1856431235), new Word64(1555081692, 3175218132), new Word64(1996064986, 2198950837), new Word64(2554220882, 3999719339), new Word64(2821834349, 766784016), new Word64(2952996808, 2566594879), new Word64(3210313671, 3203337956), new Word64(3336571891, 1034457026), new Word64(3584528711, 2466948901), new Word64(113926993, 3758326383), new Word64(338241895, 168717936), new Word64(666307205, 1188179964), new Word64(773529912, 1546045734), new Word64(1294757372, 1522805485), new Word64(1396182291, 2643833823), new Word64(1695183700, 2343527390), new Word64(1986661051, 1014477480), new Word64(2177026350, 1206759142), new Word64(2456956037, 344077627), new Word64(2730485921, 1290863460), new Word64(2820302411, 3158454273), new Word64(3259730800, 3505952657), new Word64(3345764771, 106217008), new Word64(3516065817, 3606008344), new Word64(3600352804, 1432725776), new Word64(4094571909, 1467031594), new Word64(275423344, 851169720), new Word64(430227734, 3100823752), new Word64(506948616, 1363258195), new Word64(659060556, 3750685593), new Word64(883997877, 3785050280), new Word64(958139571, 3318307427), new Word64(1322822218, 3812723403), new Word64(1537002063, 2003034995), new Word64(1747873779, 3602036899), new Word64(1955562222, 1575990012), new Word64(2024104815, 1125592928), new Word64(2227730452, 2716904306), new Word64(2361852424, 442776044), new Word64(2428436474, 593698344), new Word64(2756734187, 3733110249), new Word64(3204031479, 2999351573), new Word64(3329325298, 3815920427), new Word64(3391569614, 3928383900), new Word64(3515267271, 566280711), new Word64(3940187606, 3454069534), new Word64(4118630271, 4000239992), new Word64(116418474, 1914138554), new Word64(174292421, 2731055270), new Word64(289380356, 3203993006), new Word64(460393269, 320620315), new Word64(685471733, 587496836), new Word64(852142971, 1086792851), new Word64(1017036298, 365543100), new Word64(1126000580, 2618297676), new Word64(1288033470, 3409855158), new Word64(1501505948, 4234509866), new Word64(1607167915, 987167468), new Word64(1816402316, 1246189591)]); + } + }; + calculate_sha256_PARAMS = { + get k() { + return shadow2(this, "k", [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298]); + } + }; + chunkSize = 512; + DecryptStream = class extends DecodeStream { + constructor(str, maybeLength, decrypt2) { + super(maybeLength); + this.str = str; + this.dict = str.dict; + this.decrypt = decrypt2; + this.nextChunk = null; + this.initialized = false; + } + readBlock() { + let chunk2; + if (this.initialized) { + chunk2 = this.nextChunk; + } else { + chunk2 = this.str.getBytes(chunkSize); + this.initialized = true; + } + if (!chunk2?.length) { + this.eof = true; + return; + } + this.nextChunk = this.str.getBytes(chunkSize); + const hasMoreData = this.nextChunk?.length > 0; + const decrypt2 = this.decrypt; + chunk2 = decrypt2(chunk2, !hasMoreData); + const bufferLength = this.bufferLength, newLength = bufferLength + chunk2.length, buffer2 = this.ensureBuffer(newLength); + buffer2.set(chunk2, bufferLength); + this.bufferLength = newLength; + } + }; + ARCFourCipher = class { + constructor(key) { + this.a = 0; + this.b = 0; + const s = new Uint8Array(256); + const keyLength = key.length; + for (let i = 0; i < 256; ++i) { + s[i] = i; + } + for (let i = 0, j = 0; i < 256; ++i) { + const tmp = s[i]; + j = j + tmp + key[i % keyLength] & 255; + s[i] = s[j]; + s[j] = tmp; + } + this.s = s; + } + encryptBlock(data) { + let a = this.a, b2 = this.b; + const s = this.s; + const n = data.length; + const output2 = new Uint8Array(n); + for (let i = 0; i < n; ++i) { + a = a + 1 & 255; + const tmp = s[a]; + b2 = b2 + tmp & 255; + const tmp2 = s[b2]; + s[a] = tmp2; + s[b2] = tmp; + output2[i] = data[i] ^ s[tmp + tmp2 & 255]; + } + this.a = a; + this.b = b2; + return output2; + } + decryptBlock(data) { + return this.encryptBlock(data); + } + encrypt(data) { + return this.encryptBlock(data); + } + }; + NullCipher = class { + decryptBlock(data) { + return data; + } + encrypt(data) { + return data; + } + }; + AESBaseCipher = class { + _s = new Uint8Array([99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]); + _inv_s = new Uint8Array([82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]); + _mix = new Uint32Array([0, 235474187, 470948374, 303765277, 941896748, 908933415, 607530554, 708780849, 1883793496, 2118214995, 1817866830, 1649639237, 1215061108, 1181045119, 1417561698, 1517767529, 3767586992, 4003061179, 4236429990, 4069246893, 3635733660, 3602770327, 3299278474, 3400528769, 2430122216, 2664543715, 2362090238, 2193862645, 2835123396, 2801107407, 3035535058, 3135740889, 3678124923, 3576870512, 3341394285, 3374361702, 3810496343, 3977675356, 4279080257, 4043610186, 2876494627, 2776292904, 3076639029, 3110650942, 2472011535, 2640243204, 2403728665, 2169303058, 1001089995, 899835584, 666464733, 699432150, 59727847, 226906860, 530400753, 294930682, 1273168787, 1172967064, 1475418501, 1509430414, 1942435775, 2110667444, 1876241833, 1641816226, 2910219766, 2743034109, 2976151520, 3211623147, 2505202138, 2606453969, 2302690252, 2269728455, 3711829422, 3543599269, 3240894392, 3475313331, 3843699074, 3943906441, 4178062228, 4144047775, 1306967366, 1139781709, 1374988112, 1610459739, 1975683434, 2076935265, 1775276924, 1742315127, 1034867998, 866637845, 566021896, 800440835, 92987698, 193195065, 429456164, 395441711, 1984812685, 2017778566, 1784663195, 1683407248, 1315562145, 1080094634, 1383856311, 1551037884, 101039829, 135050206, 437757123, 337553864, 1042385657, 807962610, 573804783, 742039012, 2531067453, 2564033334, 2328828971, 2227573024, 2935566865, 2700099354, 3001755655, 3168937228, 3868552805, 3902563182, 4203181171, 4102977912, 3736164937, 3501741890, 3265478751, 3433712980, 1106041591, 1340463100, 1576976609, 1408749034, 2043211483, 2009195472, 1708848333, 1809054150, 832877231, 1068351396, 766945465, 599762354, 159417987, 126454664, 361929877, 463180190, 2709260871, 2943682380, 3178106961, 3009879386, 2572697195, 2538681184, 2236228733, 2336434550, 3509871135, 3745345300, 3441850377, 3274667266, 3910161971, 3877198648, 4110568485, 4211818798, 2597806476, 2497604743, 2261089178, 2295101073, 2733856160, 2902087851, 3202437046, 2968011453, 3936291284, 3835036895, 4136440770, 4169408201, 3535486456, 3702665459, 3467192302, 3231722213, 2051518780, 1951317047, 1716890410, 1750902305, 1113818384, 1282050075, 1584504582, 1350078989, 168810852, 67556463, 371049330, 404016761, 841739592, 1008918595, 775550814, 540080725, 3969562369, 3801332234, 4035489047, 4269907996, 3569255213, 3669462566, 3366754619, 3332740144, 2631065433, 2463879762, 2160117071, 2395588676, 2767645557, 2868897406, 3102011747, 3069049960, 202008497, 33778362, 270040487, 504459436, 875451293, 975658646, 675039627, 641025152, 2084704233, 1917518562, 1615861247, 1851332852, 1147550661, 1248802510, 1484005843, 1451044056, 933301370, 967311729, 733156972, 632953703, 260388950, 25965917, 328671808, 496906059, 1206477858, 1239443753, 1543208500, 1441952575, 2144161806, 1908694277, 1675577880, 1842759443, 3610369226, 3644379585, 3408119516, 3307916247, 4011190502, 3776767469, 4077384432, 4245618683, 2809771154, 2842737049, 3144396420, 3043140495, 2673705150, 2438237621, 2203032232, 2370213795]); + _mixCol = new Uint8Array(256).map((_3, i) => i < 128 ? i << 1 : i << 1 ^ 27); + constructor() { + this.buffer = new Uint8Array(16); + this.bufferPosition = 0; + } + _expandKey(cipherKey) { + unreachable2("Cannot call `_expandKey` on the base class"); + } + _decrypt(input2, key) { + let t, u, v; + const state = new Uint8Array(16); + state.set(input2); + for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (let i = this._cyclesOfRepetition - 1; i >= 1; --i) { + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (let j = 0; j < 16; ++j) { + state[j] = this._inv_s[state[j]]; + } + for (let j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + for (let j = 0; j < 16; j += 4) { + const s0 = this._mix[state[j]]; + const s1 = this._mix[state[j + 1]]; + const s2 = this._mix[state[j + 2]]; + const s3 = this._mix[state[j + 3]]; + t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8; + state[j] = t >>> 24 & 255; + state[j + 1] = t >> 16 & 255; + state[j + 2] = t >> 8 & 255; + state[j + 3] = t & 255; + } + } + t = state[13]; + state[13] = state[9]; + state[9] = state[5]; + state[5] = state[1]; + state[1] = t; + t = state[14]; + u = state[10]; + state[14] = state[6]; + state[10] = state[2]; + state[6] = t; + state[2] = u; + t = state[15]; + u = state[11]; + v = state[7]; + state[15] = state[3]; + state[11] = t; + state[7] = u; + state[3] = v; + for (let j = 0; j < 16; ++j) { + state[j] = this._inv_s[state[j]]; + state[j] ^= key[j]; + } + return state; + } + _encrypt(input2, key) { + const s = this._s; + let t, u, v; + const state = new Uint8Array(16); + state.set(input2); + for (let j = 0; j < 16; ++j) { + state[j] ^= key[j]; + } + for (let i = 1; i < this._cyclesOfRepetition; i++) { + for (let j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (let j = 0; j < 16; j += 4) { + const s0 = state[j]; + const s1 = state[j + 1]; + const s2 = state[j + 2]; + const s3 = state[j + 3]; + t = s0 ^ s1 ^ s2 ^ s3; + state[j] ^= t ^ this._mixCol[s0 ^ s1]; + state[j + 1] ^= t ^ this._mixCol[s1 ^ s2]; + state[j + 2] ^= t ^ this._mixCol[s2 ^ s3]; + state[j + 3] ^= t ^ this._mixCol[s3 ^ s0]; + } + for (let j = 0, k = i * 16; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + } + for (let j = 0; j < 16; ++j) { + state[j] = s[state[j]]; + } + v = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = v; + v = state[2]; + u = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = v; + state[14] = u; + v = state[3]; + u = state[7]; + t = state[11]; + state[3] = state[15]; + state[7] = v; + state[11] = u; + state[15] = t; + for (let j = 0, k = this._keySize; j < 16; ++j, ++k) { + state[j] ^= key[k]; + } + return state; + } + _decryptBlock2(data, finalize2) { + const sourceLength = data.length; + let buffer2 = this.buffer, bufferLength = this.bufferPosition; + const result2 = []; + let iv = this.iv; + for (let i = 0; i < sourceLength; ++i) { + buffer2[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + const plain = this._decrypt(buffer2, this._key); + for (let j = 0; j < 16; ++j) { + plain[j] ^= iv[j]; + } + iv = buffer2; + result2.push(plain); + buffer2 = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer2; + this.bufferLength = bufferLength; + this.iv = iv; + if (result2.length === 0) { + return new Uint8Array(0); + } + let outputLength = 16 * result2.length; + if (finalize2) { + const lastBlock = result2.at(-1); + let psLen = lastBlock[15]; + if (psLen <= 16) { + for (let i = 15, ii = 16 - psLen; i >= ii; --i) { + if (lastBlock[i] !== psLen) { + psLen = 0; + break; + } + } + outputLength -= psLen; + result2[result2.length - 1] = lastBlock.subarray(0, 16 - psLen); + } + } + const output2 = new Uint8Array(outputLength); + for (let i = 0, j = 0, ii = result2.length; i < ii; ++i, j += 16) { + output2.set(result2[i], j); + } + return output2; + } + decryptBlock(data, finalize2, iv = null) { + const sourceLength = data.length; + const buffer2 = this.buffer; + let bufferLength = this.bufferPosition; + if (iv) { + this.iv = iv; + } else { + for (let i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) { + buffer2[bufferLength] = data[i]; + } + if (bufferLength < 16) { + this.bufferLength = bufferLength; + return new Uint8Array(0); + } + this.iv = buffer2; + data = data.subarray(16); + } + this.buffer = new Uint8Array(16); + this.bufferLength = 0; + this.decryptBlock = this._decryptBlock2; + return this.decryptBlock(data, finalize2); + } + encrypt(data, iv) { + const sourceLength = data.length; + let buffer2 = this.buffer, bufferLength = this.bufferPosition; + const result2 = []; + iv ||= new Uint8Array(16); + for (let i = 0; i < sourceLength; ++i) { + buffer2[bufferLength] = data[i]; + ++bufferLength; + if (bufferLength < 16) { + continue; + } + for (let j = 0; j < 16; ++j) { + buffer2[j] ^= iv[j]; + } + const cipher = this._encrypt(buffer2, this._key); + iv = cipher; + result2.push(cipher); + buffer2 = new Uint8Array(16); + bufferLength = 0; + } + this.buffer = buffer2; + this.bufferLength = bufferLength; + this.iv = iv; + if (result2.length === 0) { + return new Uint8Array(0); + } + const outputLength = 16 * result2.length; + const output2 = new Uint8Array(outputLength); + for (let i = 0, j = 0, ii = result2.length; i < ii; ++i, j += 16) { + output2.set(result2[i], j); + } + return output2; + } + }; + AES128Cipher = class extends AESBaseCipher { + _rcon = new Uint8Array([141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141, 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47, 94, 188, 99, 198, 151, 53, 106, 212, 179, 125, 250, 239, 197, 145, 57, 114, 228, 211, 189, 97, 194, 159, 37, 74, 148, 51, 102, 204, 131, 29, 58, 116, 232, 203, 141]); + constructor(key) { + super(); + this._cyclesOfRepetition = 10; + this._keySize = 160; + this._key = this._expandKey(key); + } + _expandKey(cipherKey) { + const b2 = 176; + const s = this._s; + const rcon = this._rcon; + const result2 = new Uint8Array(b2); + result2.set(cipherKey); + for (let j = 16, i = 1; j < b2; ++i) { + let t1 = result2[j - 3]; + let t2 = result2[j - 2]; + let t3 = result2[j - 1]; + let t4 = result2[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 ^= rcon[i]; + for (let n = 0; n < 4; ++n) { + result2[j] = t1 ^= result2[j - 16]; + j++; + result2[j] = t2 ^= result2[j - 16]; + j++; + result2[j] = t3 ^= result2[j - 16]; + j++; + result2[j] = t4 ^= result2[j - 16]; + j++; + } + } + return result2; + } + }; + AES256Cipher = class extends AESBaseCipher { + constructor(key) { + super(); + this._cyclesOfRepetition = 14; + this._keySize = 224; + this._key = this._expandKey(key); + } + _expandKey(cipherKey) { + const b2 = 240; + const s = this._s; + const result2 = new Uint8Array(b2); + result2.set(cipherKey); + let r = 1; + let t1, t2, t3, t4; + for (let j = 32, i = 1; j < b2; ++i) { + if (j % 32 === 16) { + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + } else if (j % 32 === 0) { + t1 = result2[j - 3]; + t2 = result2[j - 2]; + t3 = result2[j - 1]; + t4 = result2[j - 4]; + t1 = s[t1]; + t2 = s[t2]; + t3 = s[t3]; + t4 = s[t4]; + t1 ^= r; + if ((r <<= 1) >= 256) { + r = (r ^ 27) & 255; + } + } + for (let n = 0; n < 4; ++n) { + result2[j] = t1 ^= result2[j - 32]; + j++; + result2[j] = t2 ^= result2[j - 32]; + j++; + result2[j] = t3 ^= result2[j - 32]; + j++; + result2[j] = t4 ^= result2[j - 32]; + j++; + } + } + return result2; + } + }; + PDFBase = class { + _hash(password, input2, userBytes) { + unreachable2("Abstract method `_hash` called"); + } + checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) { + const hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerValidationSalt, password.length); + hashData.set(userBytes, password.length + ownerValidationSalt.length); + const result2 = this._hash(password, hashData, userBytes); + return isArrayEqual(result2, ownerPassword); + } + checkUserPassword(password, userValidationSalt, userPassword) { + const hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userValidationSalt, password.length); + const result2 = this._hash(password, hashData, []); + return isArrayEqual(result2, userPassword); + } + getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) { + const hashData = new Uint8Array(password.length + 56); + hashData.set(password, 0); + hashData.set(ownerKeySalt, password.length); + hashData.set(userBytes, password.length + ownerKeySalt.length); + const key = this._hash(password, hashData, userBytes); + const cipher = new AES256Cipher(key); + return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16)); + } + getUserKey(password, userKeySalt, userEncryption) { + const hashData = new Uint8Array(password.length + 8); + hashData.set(password, 0); + hashData.set(userKeySalt, password.length); + const key = this._hash(password, hashData, []); + const cipher = new AES256Cipher(key); + return cipher.decryptBlock(userEncryption, false, new Uint8Array(16)); + } + }; + PDF17 = class extends PDFBase { + _hash(password, input2, userBytes) { + return calculateSHA256(input2, 0, input2.length); + } + }; + PDF20 = class extends PDFBase { + _hash(password, input2, userBytes) { + let k = calculateSHA256(input2, 0, input2.length).subarray(0, 32); + let e = [0]; + let i = 0; + while (i < 64 || e.at(-1) > i - 32) { + const combinedLength = password.length + k.length + userBytes.length, combinedArray = new Uint8Array(combinedLength); + let writeOffset = 0; + combinedArray.set(password, writeOffset); + writeOffset += password.length; + combinedArray.set(k, writeOffset); + writeOffset += k.length; + combinedArray.set(userBytes, writeOffset); + const k1 = new Uint8Array(combinedLength * 64); + for (let j = 0, pos = 0; j < 64; j++, pos += combinedLength) { + k1.set(combinedArray, pos); + } + const cipher = new AES128Cipher(k.subarray(0, 16)); + e = cipher.encrypt(k1, k.subarray(16, 32)); + const remainder = Math.sumPrecise(e.slice(0, 16)) % 3; + if (remainder === 0) { + k = calculateSHA256(e, 0, e.length); + } else if (remainder === 1) { + k = calculateSHA384(e, 0, e.length); + } else if (remainder === 2) { + k = calculateSHA512(e, 0, e.length); + } + i++; + } + return k.subarray(0, 32); + } + }; + CipherTransform = class { + constructor(stringCipherConstructor, streamCipherConstructor) { + this.StringCipherConstructor = stringCipherConstructor; + this.StreamCipherConstructor = streamCipherConstructor; + } + createStream(stream, length) { + const cipher = new this.StreamCipherConstructor(); + return new DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize2) { + return cipher.decryptBlock(data, finalize2); + }); + } + decryptString(s) { + const cipher = new this.StringCipherConstructor(); + let data = stringToBytes2(s); + data = cipher.decryptBlock(data, true); + return bytesToString2(data); + } + encryptString(s) { + const cipher = new this.StringCipherConstructor(); + if (cipher instanceof AESBaseCipher) { + const strLen = s.length; + const pad = 16 - strLen % 16; + s += String.fromCharCode(pad).repeat(pad); + const iv = new Uint8Array(16); + crypto.getRandomValues(iv); + let data2 = stringToBytes2(s); + data2 = cipher.encrypt(data2, iv); + const buf = new Uint8Array(16 + data2.length); + buf.set(iv); + buf.set(data2, 16); + return bytesToString2(buf); + } + let data = stringToBytes2(s); + data = cipher.encrypt(data); + return bytesToString2(data); + } + }; + CipherTransformFactory = class _CipherTransformFactory { + static get _defaultPasswordBytes() { + return shadow2(this, "_defaultPasswordBytes", new Uint8Array([40, 191, 78, 94, 78, 117, 138, 65, 100, 0, 78, 86, 255, 250, 1, 8, 46, 46, 0, 182, 208, 104, 62, 128, 47, 12, 169, 254, 100, 83, 105, 122])); + } + #createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) { + if (password) { + const passwordLength = Math.min(127, password.length); + password = password.subarray(0, passwordLength); + } else { + password = []; + } + const pdfAlgorithm = revision === 6 ? new PDF20() : new PDF17(); + if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) { + return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption); + } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) { + return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption); + } + return null; + } + #prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) { + const hashDataSize = 40 + ownerPassword.length + fileId.length; + const hashData = new Uint8Array(hashDataSize); + let i = 0, j, n; + if (password) { + n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + } + j = 0; + while (i < 32) { + hashData[i++] = _CipherTransformFactory._defaultPasswordBytes[j++]; + } + hashData.set(ownerPassword, i); + i += ownerPassword.length; + hashData[i++] = flags & 255; + hashData[i++] = flags >> 8 & 255; + hashData[i++] = flags >> 16 & 255; + hashData[i++] = flags >>> 24 & 255; + hashData.set(fileId, i); + i += fileId.length; + if (revision >= 4 && !encryptMetadata) { + hashData.fill(255, i, i + 4); + i += 4; + } + let hash2 = calculateMD5(hashData, 0, i); + const keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash2 = calculateMD5(hash2, 0, keyLengthInBytes); + } + } + const encryptionKey = hash2.subarray(0, keyLengthInBytes); + let cipher, checkData; + if (revision >= 3) { + i = 0; + hashData.set(_CipherTransformFactory._defaultPasswordBytes, i); + i += 32; + hashData.set(fileId, i); + i += fileId.length; + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i)); + n = encryptionKey.length; + const derivedKey = new Uint8Array(n); + for (j = 1; j <= 19; ++j) { + for (let k = 0; k < n; ++k) { + derivedKey[k] = encryptionKey[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + checkData = cipher.encryptBlock(checkData); + } + } else { + cipher = new ARCFourCipher(encryptionKey); + checkData = cipher.encryptBlock(_CipherTransformFactory._defaultPasswordBytes); + } + return checkData.every((data, k) => userPassword[k] === data) ? encryptionKey : null; + } + #decodeUserPassword(password, ownerPassword, revision, keyLength) { + const hashData = new Uint8Array(32); + let i = 0; + const n = Math.min(32, password.length); + for (; i < n; ++i) { + hashData[i] = password[i]; + } + let j = 0; + while (i < 32) { + hashData[i++] = _CipherTransformFactory._defaultPasswordBytes[j++]; + } + let hash2 = calculateMD5(hashData, 0, i); + const keyLengthInBytes = keyLength >> 3; + if (revision >= 3) { + for (j = 0; j < 50; ++j) { + hash2 = calculateMD5(hash2, 0, hash2.length); + } + } + let cipher, userPassword; + if (revision >= 3) { + userPassword = ownerPassword; + const derivedKey = new Uint8Array(keyLengthInBytes); + for (j = 19; j >= 0; j--) { + for (let k = 0; k < keyLengthInBytes; ++k) { + derivedKey[k] = hash2[k] ^ j; + } + cipher = new ARCFourCipher(derivedKey); + userPassword = cipher.encryptBlock(userPassword); + } + } else { + cipher = new ARCFourCipher(hash2.subarray(0, keyLengthInBytes)); + userPassword = cipher.encryptBlock(ownerPassword); + } + return userPassword; + } + #buildObjectKey(num, gen, encryptionKey, isAes = false) { + const n = encryptionKey.length; + const key = new Uint8Array(n + 9); + key.set(encryptionKey); + let i = n; + key[i++] = num & 255; + key[i++] = num >> 8 & 255; + key[i++] = num >> 16 & 255; + key[i++] = gen & 255; + key[i++] = gen >> 8 & 255; + if (isAes) { + key[i++] = 115; + key[i++] = 65; + key[i++] = 108; + key[i++] = 84; + } + const hash2 = calculateMD5(key, 0, i); + return hash2.subarray(0, Math.min(n + 5, 16)); + } + #buildCipherConstructor(cf, name, num, gen, key) { + if (!(name instanceof Name2)) { + throw new FormatError3("Invalid crypt filter name."); + } + const self2 = this; + const cryptFilter = cf.get(name.name); + const cfm = cryptFilter?.get("CFM"); + if (!cfm || cfm.name === "None") { + return function() { + return new NullCipher(); + }; + } + if (cfm.name === "V2") { + return function() { + return new ARCFourCipher(self2.#buildObjectKey(num, gen, key, false)); + }; + } + if (cfm.name === "AESV2") { + return function() { + return new AES128Cipher(self2.#buildObjectKey(num, gen, key, true)); + }; + } + if (cfm.name === "AESV3") { + return function() { + return new AES256Cipher(key); + }; + } + throw new FormatError3("Unknown crypto method"); + } + constructor(dict, fileId, password) { + const filter2 = dict.get("Filter"); + if (!isName(filter2, "Standard")) { + throw new FormatError3("unknown encryption method"); + } + this.filterName = filter2.name; + this.dict = dict; + const algorithm = dict.get("V"); + if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) { + throw new FormatError3("unsupported encryption algorithm"); + } + this.algorithm = algorithm; + let keyLength = dict.get("Length"); + if (!keyLength) { + if (algorithm <= 3) { + keyLength = 40; + } else { + const cfDict = dict.get("CF"); + const streamCryptoName = dict.get("StmF"); + if (cfDict instanceof Dict && streamCryptoName instanceof Name2) { + cfDict.suppressEncryption = true; + const handlerDict = cfDict.get(streamCryptoName.name); + keyLength = handlerDict?.get("Length") || 128; + if (keyLength < 40) { + keyLength <<= 3; + } + } + } + } + if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) { + throw new FormatError3("invalid key length"); + } + const ownerBytes = stringToBytes2(dict.get("O")), userBytes = stringToBytes2(dict.get("U")); + const ownerPassword = ownerBytes.subarray(0, 32); + const userPassword = userBytes.subarray(0, 32); + const flags = dict.get("P"); + const revision = dict.get("R"); + const encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get("EncryptMetadata") !== false; + this.encryptMetadata = encryptMetadata; + const fileIdBytes = stringToBytes2(fileId); + let passwordBytes; + if (password) { + if (revision === 6) { + try { + password = utf8StringToString(password); + } catch { + warn2("CipherTransformFactory: Unable to convert UTF8 encoded password."); + } + } + passwordBytes = stringToBytes2(password); + } + let encryptionKey; + if (algorithm !== 5) { + encryptionKey = this.#prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } else { + const ownerValidationSalt = ownerBytes.subarray(32, 40); + const ownerKeySalt = ownerBytes.subarray(40, 48); + const uBytes = userBytes.subarray(0, 48); + const userValidationSalt = userBytes.subarray(32, 40); + const userKeySalt = userBytes.subarray(40, 48); + const ownerEncryption = stringToBytes2(dict.get("OE")); + const userEncryption = stringToBytes2(dict.get("UE")); + const perms = stringToBytes2(dict.get("Perms")); + encryptionKey = this.#createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms); + } + if (!encryptionKey) { + if (!password) { + throw new PasswordException3("No password given", PasswordResponses2.NEED_PASSWORD); + } + const decodedPassword = this.#decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength); + encryptionKey = this.#prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata); + } + if (!encryptionKey) { + throw new PasswordException3("Incorrect Password", PasswordResponses2.INCORRECT_PASSWORD); + } + if (algorithm === 4 && encryptionKey.length < 16) { + this.encryptionKey = new Uint8Array(16); + this.encryptionKey.set(encryptionKey); + } else { + this.encryptionKey = encryptionKey; + } + if (algorithm >= 4) { + const cf = dict.get("CF"); + if (cf instanceof Dict) { + cf.suppressEncryption = true; + } + this.cf = cf; + this.stmf = dict.get("StmF") || Name2.get("Identity"); + this.strf = dict.get("StrF") || Name2.get("Identity"); + this.eff = dict.get("EFF") || this.stmf; + } + } + createCipherTransform(num, gen) { + if (this.algorithm === 4 || this.algorithm === 5) { + return new CipherTransform(this.#buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey), this.#buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey)); + } + const key = this.#buildObjectKey(num, gen, this.encryptionKey, false); + const cipherConstructor = function() { + return new ARCFourCipher(key); + }; + return new CipherTransform(cipherConstructor, cipherConstructor); + } + }; + XRef = class { + constructor(stream, pdfManager) { + this.stream = stream; + this.pdfManager = pdfManager; + this.entries = []; + this._xrefStms = /* @__PURE__ */ new Set(); + this._cacheMap = /* @__PURE__ */ new Map(); + this._pendingRefs = new RefSet(); + this._newPersistentRefNum = null; + this._newTemporaryRefNum = null; + this._persistentRefsCache = null; + } + getNewPersistentRef(obj2) { + if (this._newPersistentRefNum === null) { + this._newPersistentRefNum = this.entries.length || 1; + } + const num = this._newPersistentRefNum++; + this._cacheMap.set(num, obj2); + return Ref.get(num, 0); + } + getNewTemporaryRef() { + if (this._newTemporaryRefNum === null) { + this._newTemporaryRefNum = this.entries.length || 1; + if (this._newPersistentRefNum) { + this._persistentRefsCache = /* @__PURE__ */ new Map(); + for (let i = this._newTemporaryRefNum; i < this._newPersistentRefNum; i++) { + this._persistentRefsCache.set(i, this._cacheMap.get(i)); + this._cacheMap.delete(i); + } + } + } + return Ref.get(this._newTemporaryRefNum++, 0); + } + resetNewTemporaryRef() { + this._newTemporaryRefNum = null; + if (this._persistentRefsCache) { + for (const [num, obj2] of this._persistentRefsCache) { + this._cacheMap.set(num, obj2); + } + } + this._persistentRefsCache = null; + } + setStartXRef(startXRef) { + this.startXRefQueue = [startXRef]; + } + parse(recoveryMode = false) { + let trailerDict; + if (!recoveryMode) { + trailerDict = this.readXRef(); + } else { + warn2("Indexing all PDF objects"); + trailerDict = this.indexObjects(); + } + trailerDict.assignXref(this); + this.trailer = trailerDict; + let encrypt; + try { + encrypt = trailerDict.get("Encrypt"); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`XRef.parse - Invalid "Encrypt" reference: "${ex}".`); + } + if (encrypt instanceof Dict) { + const ids = trailerDict.get("ID"); + const fileId = ids?.length ? ids[0] : ""; + encrypt.suppressEncryption = true; + this.encrypt = new CipherTransformFactory(encrypt, fileId, this.pdfManager.password); + } + let root2; + try { + root2 = trailerDict.get("Root"); + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`XRef.parse - Invalid "Root" reference: "${ex}".`); + } + if (root2 instanceof Dict) { + try { + const pages = root2.get("Pages"); + if (pages instanceof Dict) { + this.root = root2; + return; + } + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`XRef.parse - Invalid "Pages" reference: "${ex}".`); + } + } + if (!recoveryMode) { + throw new XRefParseException(); + } + throw new InvalidPDFException3("Invalid Root reference."); + } + processXRefTable(parser) { + if (!("tableState" in this)) { + this.tableState = { + entryNum: 0, + streamPos: parser.lexer.stream.pos, + parserBuf1: parser.buf1, + parserBuf2: parser.buf2 + }; + } + const obj2 = this.readXRefTable(parser); + if (!isCmd(obj2, "trailer")) { + throw new FormatError3("Invalid XRef table: could not find trailer dictionary"); + } + let dict = parser.getObj(); + if (!(dict instanceof Dict) && dict.dict) { + dict = dict.dict; + } + if (!(dict instanceof Dict)) { + throw new FormatError3("Invalid XRef table: could not parse trailer dictionary"); + } + delete this.tableState; + return dict; + } + readXRefTable(parser) { + const stream = parser.lexer.stream; + const tableState = this.tableState; + stream.pos = tableState.streamPos; + parser.buf1 = tableState.parserBuf1; + parser.buf2 = tableState.parserBuf2; + let obj2; + while (true) { + if (!("firstEntryNum" in tableState) || !("entryCount" in tableState)) { + if (isCmd(obj2 = parser.getObj(), "trailer")) { + break; + } + tableState.firstEntryNum = obj2; + tableState.entryCount = parser.getObj(); + } + let first2 = tableState.firstEntryNum; + const count = tableState.entryCount; + if (!Number.isInteger(first2) || !Number.isInteger(count)) { + throw new FormatError3("Invalid XRef table: wrong types in subsection header"); + } + for (let i = tableState.entryNum; i < count; i++) { + tableState.streamPos = stream.pos; + tableState.entryNum = i; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + const entry = {}; + entry.offset = parser.getObj(); + entry.gen = parser.getObj(); + const type = parser.getObj(); + if (type instanceof Cmd) { + switch (type.cmd) { + case "f": + entry.free = true; + break; + case "n": + entry.uncompressed = true; + break; + } + } + if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) { + throw new FormatError3(`Invalid entry in XRef subsection: ${first2}, ${count}`); + } + if (i === 0 && entry.free && first2 === 1) { + first2 = 0; + } + if (!this.entries[i + first2]) { + this.entries[i + first2] = entry; + } + } + tableState.entryNum = 0; + tableState.streamPos = stream.pos; + tableState.parserBuf1 = parser.buf1; + tableState.parserBuf2 = parser.buf2; + delete tableState.firstEntryNum; + delete tableState.entryCount; + } + if (this.entries[0] && !this.entries[0].free) { + throw new FormatError3("Invalid XRef table: unexpected first object"); + } + return obj2; + } + processXRefStream(stream) { + if (!("streamState" in this)) { + const { + dict, + pos + } = stream; + const byteWidths = dict.get("W"); + const range2 = dict.get("Index") || [0, dict.get("Size")]; + this.streamState = { + entryRanges: range2, + byteWidths, + entryNum: 0, + streamPos: pos + }; + } + this.readXRefStream(stream); + delete this.streamState; + return stream.dict; + } + readXRefStream(stream) { + const streamState = this.streamState; + stream.pos = streamState.streamPos; + const [typeFieldWidth, offsetFieldWidth, generationFieldWidth] = streamState.byteWidths; + const entryRanges = streamState.entryRanges; + while (entryRanges.length > 0) { + const [first2, n] = entryRanges; + if (!Number.isInteger(first2) || !Number.isInteger(n)) { + throw new FormatError3(`Invalid XRef range fields: ${first2}, ${n}`); + } + if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) { + throw new FormatError3(`Invalid XRef entry fields length: ${first2}, ${n}`); + } + for (let i = streamState.entryNum; i < n; ++i) { + streamState.entryNum = i; + streamState.streamPos = stream.pos; + let type = 0, offset = 0, generation = 0; + for (let j = 0; j < typeFieldWidth; ++j) { + const typeByte = stream.getByte(); + if (typeByte === -1) { + throw new FormatError3("Invalid XRef byteWidths 'type'."); + } + type = type << 8 | typeByte; + } + if (typeFieldWidth === 0) { + type = 1; + } + for (let j = 0; j < offsetFieldWidth; ++j) { + const offsetByte = stream.getByte(); + if (offsetByte === -1) { + throw new FormatError3("Invalid XRef byteWidths 'offset'."); + } + offset = offset << 8 | offsetByte; + } + for (let j = 0; j < generationFieldWidth; ++j) { + const generationByte = stream.getByte(); + if (generationByte === -1) { + throw new FormatError3("Invalid XRef byteWidths 'generation'."); + } + generation = generation << 8 | generationByte; + } + const entry = {}; + entry.offset = offset; + entry.gen = generation; + switch (type) { + case 0: + entry.free = true; + break; + case 1: + entry.uncompressed = true; + break; + case 2: + break; + default: + throw new FormatError3(`Invalid XRef entry type: ${type}`); + } + if (!this.entries[first2 + i]) { + this.entries[first2 + i] = entry; + } + } + streamState.entryNum = 0; + streamState.streamPos = stream.pos; + entryRanges.splice(0, 2); + } + } + indexObjects() { + const TAB = 9, LF = 10, CR = 13, SPACE = 32; + const PERCENT = 37, LT = 60; + function readToken(data, offset) { + let token = "", ch2 = data[offset]; + while (ch2 !== LF && ch2 !== CR && ch2 !== LT) { + if (++offset >= data.length) { + break; + } + token += String.fromCharCode(ch2); + ch2 = data[offset]; + } + return token; + } + function skipUntil(data, offset, what) { + const length2 = what.length, dataLength = data.length; + let skipped = 0; + while (offset < dataLength) { + let i = 0; + while (i < length2 && data[offset + i] === what[i]) { + ++i; + } + if (i >= length2) { + break; + } + offset++; + skipped++; + } + return skipped; + } + const gEndobjRegExp = /\b(endobj|\d+\s+\d+\s+obj|xref|trailer\s*<<)\b/g; + const gStartxrefRegExp = /\b(startxref|\d+\s+\d+\s+obj)\b/g; + const objRegExp = /^(\d+)\s+(\d+)\s+obj\b/; + const trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]); + const startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]); + const xrefBytes = new Uint8Array([47, 88, 82, 101, 102]); + this.entries.length = 0; + this._cacheMap.clear(); + const stream = this.stream; + stream.pos = 0; + const buffer2 = stream.getBytes(), bufferStr = bytesToString2(buffer2), length = buffer2.length; + let position = stream.start; + const trailers = [], xrefStms = []; + while (position < length) { + let ch2 = buffer2[position]; + if (ch2 === TAB || ch2 === LF || ch2 === CR || ch2 === SPACE) { + ++position; + continue; + } + if (ch2 === PERCENT) { + do { + ++position; + if (position >= length) { + break; + } + ch2 = buffer2[position]; + } while (ch2 !== LF && ch2 !== CR); + continue; + } + const token = readToken(buffer2, position); + let m; + if (token.startsWith("xref") && (token.length === 4 || /\s/.test(token[4]))) { + position += skipUntil(buffer2, position, trailerBytes); + trailers.push(position); + position += skipUntil(buffer2, position, startxrefBytes); + } else if (m = objRegExp.exec(token)) { + const num = m[1] | 0, gen = m[2] | 0; + const startPos = position + token.length; + let contentLength, updateEntries = false; + if (!this.entries[num]) { + updateEntries = true; + } else if (this.entries[num].gen === gen) { + try { + const parser = new Parser({ + lexer: new Lexer(stream.makeSubStream(startPos)) + }); + parser.getObj(); + updateEntries = true; + } catch (ex) { + if (ex instanceof ParserEOFException) { + warn2(`indexObjects -- checking object (${token}): "${ex}".`); + } else { + updateEntries = true; + } + } + } + if (updateEntries) { + this.entries[num] = { + offset: position - stream.start, + gen, + uncompressed: true + }; + } + gEndobjRegExp.lastIndex = startPos; + const match = gEndobjRegExp.exec(bufferStr); + if (match) { + const endPos = gEndobjRegExp.lastIndex + 1; + contentLength = endPos - position; + if (match[1] !== "endobj") { + warn2(`indexObjects: Found "${match[1]}" inside of another "obj", caused by missing "endobj" -- trying to recover.`); + contentLength -= match[1].length + 1; + } + } else { + contentLength = length - position; + } + const content = buffer2.subarray(position, position + contentLength); + const xrefTagOffset = skipUntil(content, 0, xrefBytes); + if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) { + xrefStms.push(position - stream.start); + this._xrefStms.add(position - stream.start); + } + position += contentLength; + } else if (token.startsWith("trailer") && (token.length === 7 || /\s/.test(token[7]))) { + trailers.push(position); + const startPos = position + token.length; + let contentLength; + gStartxrefRegExp.lastIndex = startPos; + const match = gStartxrefRegExp.exec(bufferStr); + if (match) { + const endPos = gStartxrefRegExp.lastIndex + 1; + contentLength = endPos - position; + if (match[1] !== "startxref") { + warn2(`indexObjects: Found "${match[1]}" after "trailer", caused by missing "startxref" -- trying to recover.`); + contentLength -= match[1].length + 1; + } + } else { + contentLength = length - position; + } + position += contentLength; + } else { + position += token.length + 1; + } + } + for (const xrefStm of xrefStms) { + this.startXRefQueue.push(xrefStm); + this.readXRef(true); + } + const trailerDicts = []; + let isEncrypted = false; + for (const trailer of trailers) { + stream.pos = trailer; + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true, + recoveryMode: true + }); + const obj2 = parser.getObj(); + if (!isCmd(obj2, "trailer")) { + continue; + } + const dict = parser.getObj(); + if (!(dict instanceof Dict)) { + continue; + } + trailerDicts.push(dict); + if (dict.has("Encrypt")) { + isEncrypted = true; + } + } + let trailerDict, trailerError; + for (const dict of [...trailerDicts, "genFallback", ...trailerDicts]) { + if (dict === "genFallback") { + if (!trailerError) { + break; + } + this._generationFallback = true; + continue; + } + let validPagesDict = false; + try { + const rootDict = dict.get("Root"); + if (!(rootDict instanceof Dict)) { + continue; + } + const pagesDict = rootDict.get("Pages"); + if (!(pagesDict instanceof Dict)) { + continue; + } + const pagesCount = pagesDict.get("Count"); + if (Number.isInteger(pagesCount)) { + validPagesDict = true; + } + } catch (ex) { + trailerError = ex; + continue; + } + if (validPagesDict && (!isEncrypted || dict.has("Encrypt")) && dict.has("ID")) { + return dict; + } + trailerDict = dict; + } + if (trailerDict) { + return trailerDict; + } + if (this.topDict) { + return this.topDict; + } + if (!trailerDicts.length) { + for (const num in this.entries) { + if (!Object.hasOwn(this.entries, num)) { + continue; + } + const entry = this.entries[num]; + const ref = Ref.get(parseInt(num), entry.gen); + let obj2; + try { + obj2 = this.fetch(ref); + } catch { + continue; + } + if (obj2 instanceof BaseStream) { + obj2 = obj2.dict; + } + if (obj2 instanceof Dict && obj2.has("Root")) { + return obj2; + } + } + } + throw new InvalidPDFException3("Invalid PDF structure."); + } + readXRef(recoveryMode = false) { + const stream = this.stream; + const startXRefParsedCache = /* @__PURE__ */ new Set(); + while (this.startXRefQueue.length) { + try { + const startXRef = this.startXRefQueue[0]; + if (startXRefParsedCache.has(startXRef)) { + warn2("readXRef - skipping XRef table since it was already parsed."); + this.startXRefQueue.shift(); + continue; + } + startXRefParsedCache.add(startXRef); + stream.pos = startXRef + stream.start; + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + let obj2 = parser.getObj(); + let dict; + if (isCmd(obj2, "xref")) { + dict = this.processXRefTable(parser); + if (!this.topDict) { + this.topDict = dict; + } + obj2 = dict.get("XRefStm"); + if (Number.isInteger(obj2) && !this._xrefStms.has(obj2)) { + this._xrefStms.add(obj2); + this.startXRefQueue.push(obj2); + } + } else if (Number.isInteger(obj2)) { + if (!Number.isInteger(parser.getObj()) || !isCmd(parser.getObj(), "obj") || !((obj2 = parser.getObj()) instanceof BaseStream)) { + throw new FormatError3("Invalid XRef stream"); + } + dict = this.processXRefStream(obj2); + if (!this.topDict) { + this.topDict = dict; + } + if (!dict) { + throw new FormatError3("Failed to read XRef stream"); + } + } else { + throw new FormatError3("Invalid XRef stream header"); + } + obj2 = dict.get("Prev"); + if (Number.isInteger(obj2)) { + this.startXRefQueue.push(obj2); + } else if (obj2 instanceof Ref) { + this.startXRefQueue.push(obj2.num); + } + } catch (e) { + if (e instanceof MissingDataException) { + throw e; + } + info2("(while reading XRef): " + e); + } + this.startXRefQueue.shift(); + } + if (this.topDict) { + return this.topDict; + } + if (recoveryMode) { + return void 0; + } + throw new XRefParseException(); + } + getEntry(i) { + const xrefEntry = this.entries[i]; + if (xrefEntry && !xrefEntry.free && xrefEntry.offset) { + return xrefEntry; + } + return null; + } + fetchIfRef(obj2, suppressEncryption = false) { + if (obj2 instanceof Ref) { + return this.fetch(obj2, suppressEncryption); + } + return obj2; + } + fetch(ref, suppressEncryption = false) { + if (!(ref instanceof Ref)) { + throw new Error("ref object is not a reference"); + } + const num = ref.num; + const cacheEntry = this._cacheMap.get(num); + if (cacheEntry !== void 0) { + if (cacheEntry instanceof Dict && !cacheEntry.objId) { + cacheEntry.objId = ref.toString(); + } + return cacheEntry; + } + let xrefEntry = this.getEntry(num); + if (xrefEntry === null) { + return xrefEntry; + } + if (this._pendingRefs.has(ref)) { + this._pendingRefs.remove(ref); + warn2(`Ignoring circular reference: ${ref}.`); + return CIRCULAR_REF; + } + this._pendingRefs.put(ref); + try { + xrefEntry = xrefEntry.uncompressed ? this.fetchUncompressed(ref, xrefEntry, suppressEncryption) : this.fetchCompressed(ref, xrefEntry, suppressEncryption); + this._pendingRefs.remove(ref); + } catch (ex) { + this._pendingRefs.remove(ref); + throw ex; + } + if (xrefEntry instanceof Dict) { + xrefEntry.objId = ref.toString(); + } else if (xrefEntry instanceof BaseStream) { + xrefEntry.dict.objId = ref.toString(); + } + return xrefEntry; + } + fetchUncompressed(ref, xrefEntry, suppressEncryption = false) { + const gen = ref.gen; + let num = ref.num; + if (xrefEntry.gen !== gen) { + const msg = `Inconsistent generation in XRef: ${ref}`; + if (this._generationFallback && xrefEntry.gen < gen) { + warn2(msg); + return this.fetchUncompressed(Ref.get(num, xrefEntry.gen), xrefEntry, suppressEncryption); + } + throw new XRefEntryException(msg); + } + const stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start); + const parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + const obj1 = parser.getObj(); + const obj2 = parser.getObj(); + const obj3 = parser.getObj(); + if (obj1 !== num || obj2 !== gen || !(obj3 instanceof Cmd)) { + throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); + } + if (obj3.cmd !== "obj") { + if (obj3.cmd.startsWith("obj")) { + num = parseInt(obj3.cmd.substring(3), 10); + if (!Number.isNaN(num)) { + return num; + } + } + throw new XRefEntryException(`Bad (uncompressed) XRef entry: ${ref}`); + } + xrefEntry = this.encrypt && !suppressEncryption ? parser.getObj(this.encrypt.createCipherTransform(num, gen)) : parser.getObj(); + if (!(xrefEntry instanceof BaseStream)) { + this._cacheMap.set(num, xrefEntry); + } + return xrefEntry; + } + fetchCompressed(ref, xrefEntry, suppressEncryption = false) { + const tableOffset = xrefEntry.offset; + const stream = this.fetch(Ref.get(tableOffset, 0)); + if (!(stream instanceof BaseStream)) { + throw new FormatError3("bad ObjStm stream"); + } + const first2 = stream.dict.get("First"); + const n = stream.dict.get("N"); + if (!Number.isInteger(first2) || !Number.isInteger(n)) { + throw new FormatError3("invalid first and n parameters for ObjStm stream"); + } + let parser = new Parser({ + lexer: new Lexer(stream), + xref: this, + allowStreams: true + }); + const nums = new Array(n); + const offsets = new Array(n); + for (let i = 0; i < n; ++i) { + const num = parser.getObj(); + if (!Number.isInteger(num)) { + throw new FormatError3(`invalid object number in the ObjStm stream: ${num}`); + } + const offset = parser.getObj(); + if (!Number.isInteger(offset)) { + throw new FormatError3(`invalid object offset in the ObjStm stream: ${offset}`); + } + nums[i] = num; + const entry = this.getEntry(num); + if (entry?.offset === tableOffset && entry.gen !== i) { + entry.gen = i; + } + offsets[i] = offset; + } + const start = (stream.start || 0) + first2; + const entries = new Array(n); + for (let i = 0; i < n; ++i) { + const length = i < n - 1 ? offsets[i + 1] - offsets[i] : void 0; + if (length < 0) { + throw new FormatError3("Invalid offset in the ObjStm stream."); + } + parser = new Parser({ + lexer: new Lexer(stream.makeSubStream(start + offsets[i], length, stream.dict)), + xref: this, + allowStreams: true + }); + const obj2 = parser.getObj(); + entries[i] = obj2; + if (obj2 instanceof BaseStream) { + continue; + } + const num = nums[i], entry = this.entries[num]; + if (entry && entry.offset === tableOffset && entry.gen === i) { + this._cacheMap.set(num, obj2); + } + } + xrefEntry = entries[xrefEntry.gen]; + if (xrefEntry === void 0) { + throw new XRefEntryException(`Bad (compressed) XRef entry: ${ref}`); + } + return xrefEntry; + } + async fetchIfRefAsync(obj2, suppressEncryption) { + if (obj2 instanceof Ref) { + return this.fetchAsync(obj2, suppressEncryption); + } + return obj2; + } + async fetchAsync(ref, suppressEncryption) { + try { + return this.fetch(ref, suppressEncryption); + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + throw ex; + } + await this.pdfManager.requestRange(ex.begin, ex.end); + return this.fetchAsync(ref, suppressEncryption); + } + } + getCatalogObj() { + return this.root; + } + }; + LETTER_SIZE_MEDIABOX = [0, 0, 612, 792]; + Page = class { + #areAnnotationsCached = false; + #resourcesPromise = null; + constructor({ + pdfManager, + xref, + pageIndex, + pageDict, + ref, + globalIdFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + globalColorSpaceCache, + globalImageCache, + systemFontCache, + nonBlendModesSet, + xfaFactory + }) { + this.pdfManager = pdfManager; + this.pageIndex = pageIndex; + this.pageDict = pageDict; + this.xref = xref; + this.ref = ref; + this.fontCache = fontCache; + this.builtInCMapCache = builtInCMapCache; + this.standardFontDataCache = standardFontDataCache; + this.globalColorSpaceCache = globalColorSpaceCache; + this.globalImageCache = globalImageCache; + this.systemFontCache = systemFontCache; + this.nonBlendModesSet = nonBlendModesSet; + this.evaluatorOptions = pdfManager.evaluatorOptions; + this.xfaFactory = xfaFactory; + const idCounters = { + obj: 0 + }; + this._localIdFactory = class extends globalIdFactory { + static createObjId() { + return `p${pageIndex}_${++idCounters.obj}`; + } + static getPageObjId() { + return `p${ref.toString()}`; + } + }; + } + #createPartialEvaluator(handler) { + return new PartialEvaluator({ + xref: this.xref, + handler, + pageIndex: this.pageIndex, + idFactory: this._localIdFactory, + fontCache: this.fontCache, + builtInCMapCache: this.builtInCMapCache, + standardFontDataCache: this.standardFontDataCache, + globalColorSpaceCache: this.globalColorSpaceCache, + globalImageCache: this.globalImageCache, + systemFontCache: this.systemFontCache, + options: this.evaluatorOptions + }); + } + #getInheritableProperty(key, getArray = false) { + const value = getInheritableProperty({ + dict: this.pageDict, + key, + getArray, + stopWhenFound: false + }); + if (!Array.isArray(value)) { + return value; + } + if (value.length === 1 || !(value[0] instanceof Dict)) { + return value[0]; + } + return Dict.merge({ + xref: this.xref, + dictArray: value + }); + } + get content() { + return this.pageDict.getArray("Contents"); + } + get resources() { + const resources = this.#getInheritableProperty("Resources"); + return shadow2(this, "resources", resources instanceof Dict ? resources : Dict.empty); + } + #getBoundingBox(name) { + if (this.xfaData) { + return this.xfaData.bbox; + } + const box = lookupNormalRect(this.#getInheritableProperty(name, true), null); + if (box) { + if (box[2] - box[0] > 0 && box[3] - box[1] > 0) { + return box; + } + warn2(`Empty, or invalid, /${name} entry.`); + } + return null; + } + get mediaBox() { + return shadow2(this, "mediaBox", this.#getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX); + } + get cropBox() { + return shadow2(this, "cropBox", this.#getBoundingBox("CropBox") || this.mediaBox); + } + get userUnit() { + const obj2 = this.pageDict.get("UserUnit"); + return shadow2(this, "userUnit", typeof obj2 === "number" && obj2 > 0 ? obj2 : 1); + } + get view() { + const { + cropBox, + mediaBox + } = this; + if (cropBox !== mediaBox && !isArrayEqual(cropBox, mediaBox)) { + const box = Util2.intersect(cropBox, mediaBox); + if (box && box[2] - box[0] > 0 && box[3] - box[1] > 0) { + return shadow2(this, "view", box); + } + warn2("Empty /CropBox and /MediaBox intersection."); + } + return shadow2(this, "view", mediaBox); + } + get rotate() { + let rotate = this.#getInheritableProperty("Rotate") || 0; + if (rotate % 90 !== 0) { + rotate = 0; + } else if (rotate >= 360) { + rotate %= 360; + } else if (rotate < 0) { + rotate = (rotate % 360 + 360) % 360; + } + return shadow2(this, "rotate", rotate); + } + #onSubStreamError(reason, objId) { + if (this.evaluatorOptions.ignoreErrors) { + warn2(`getContentStream - ignoring sub-stream (${objId}): "${reason}".`); + return; + } + throw reason; + } + async getContentStream() { + const content = await this.pdfManager.ensure(this, "content"); + if (content instanceof BaseStream) { + return content; + } + if (Array.isArray(content)) { + return new StreamsSequenceStream(content, this.#onSubStreamError.bind(this)); + } + return new NullStream(); + } + get xfaData() { + return shadow2(this, "xfaData", this.xfaFactory ? { + bbox: this.xfaFactory.getBoundingBox(this.pageIndex) + } : null); + } + async #replaceIdByRef(annotations, deletedAnnotations, existingAnnotations) { + const promises = []; + for (const annotation of annotations) { + if (annotation.id) { + const ref = Ref.fromString(annotation.id); + if (!ref) { + warn2(`A non-linked annotation cannot be modified: ${annotation.id}`); + continue; + } + if (annotation.deleted) { + deletedAnnotations.put(ref, ref); + if (annotation.popupRef) { + const popupRef = Ref.fromString(annotation.popupRef); + if (popupRef) { + deletedAnnotations.put(popupRef, popupRef); + } + } + continue; + } + if (annotation.popup?.deleted) { + const popupRef = Ref.fromString(annotation.popupRef); + if (popupRef) { + deletedAnnotations.put(popupRef, popupRef); + } + } + existingAnnotations?.put(ref); + annotation.ref = ref; + promises.push(this.xref.fetchAsync(ref).then((obj2) => { + if (obj2 instanceof Dict) { + annotation.oldAnnotation = obj2.clone(); + } + }, () => { + warn2(`Cannot fetch \`oldAnnotation\` for: ${ref}.`); + })); + delete annotation.id; + } + } + await Promise.all(promises); + } + async saveNewAnnotations(handler, task, annotations, imagePromises, changes) { + if (this.xfaFactory) { + throw new Error("XFA: Cannot save new annotations."); + } + const partialEvaluator = this.#createPartialEvaluator(handler); + const deletedAnnotations = new RefSetCache(); + const existingAnnotations = new RefSet(); + await this.#replaceIdByRef(annotations, deletedAnnotations, existingAnnotations); + const pageDict = this.pageDict; + const annotationsArray = this.annotations.filter((a) => !(a instanceof Ref && deletedAnnotations.has(a))); + const newData = await AnnotationFactory.saveNewAnnotations(partialEvaluator, task, annotations, imagePromises, changes); + for (const { + ref + } of newData.annotations) { + if (ref instanceof Ref && !existingAnnotations.has(ref)) { + annotationsArray.push(ref); + } + } + const dict = pageDict.clone(); + dict.set("Annots", annotationsArray); + changes.put(this.ref, { + data: dict + }); + for (const deletedRef of deletedAnnotations) { + changes.put(deletedRef, { + data: null + }); + } + } + async save(handler, task, annotationStorage, changes) { + const partialEvaluator = this.#createPartialEvaluator(handler); + const annotations = await this._parsedAnnotations; + const promises = []; + for (const annotation of annotations) { + promises.push(annotation.save(partialEvaluator, task, annotationStorage, changes).catch(function(reason) { + warn2(`save - ignoring annotation data during "${task.name}" task: "${reason}".`); + return null; + })); + } + return Promise.all(promises); + } + async loadResources(keys2) { + await (this.#resourcesPromise ??= this.pdfManager.ensure(this, "resources")); + await ObjectLoader.load(this.resources, keys2, this.xref); + } + async #getMergedResources(streamDict, keys2) { + const localResources = streamDict?.get("Resources"); + if (!(localResources instanceof Dict && localResources.size)) { + return this.resources; + } + await ObjectLoader.load(localResources, keys2, this.xref); + return Dict.merge({ + xref: this.xref, + dictArray: [localResources, this.resources], + mergeSubDicts: true + }); + } + async getOperatorList({ + handler, + sink, + task, + intent, + cacheKey, + annotationStorage = null, + modifiedIds = null + }) { + const contentStreamPromise = this.getContentStream(); + const resourcesPromise = this.loadResources(RESOURCES_KEYS_OPERATOR_LIST); + const partialEvaluator = this.#createPartialEvaluator(handler); + const newAnnotsByPage = !this.xfaFactory ? getNewAnnotationsMap(annotationStorage) : null; + const newAnnots = newAnnotsByPage?.get(this.pageIndex); + let newAnnotationsPromise = Promise.resolve(null); + let deletedAnnotations = null; + if (newAnnots) { + const annotationGlobalsPromise = this.pdfManager.ensureDoc("annotationGlobals"); + let imagePromises; + const missingBitmaps = /* @__PURE__ */ new Set(); + for (const { + bitmapId, + bitmap + } of newAnnots) { + if (bitmapId && !bitmap && !missingBitmaps.has(bitmapId)) { + missingBitmaps.add(bitmapId); + } + } + const { + isOffscreenCanvasSupported + } = this.evaluatorOptions; + if (missingBitmaps.size > 0) { + const annotationWithBitmaps = newAnnots.slice(); + for (const [key, annotation] of annotationStorage) { + if (!key.startsWith(AnnotationEditorPrefix2)) { + continue; + } + if (annotation.bitmap && missingBitmaps.has(annotation.bitmapId)) { + annotationWithBitmaps.push(annotation); + } + } + imagePromises = AnnotationFactory.generateImages(annotationWithBitmaps, this.xref, isOffscreenCanvasSupported); + } else { + imagePromises = AnnotationFactory.generateImages(newAnnots, this.xref, isOffscreenCanvasSupported); + } + deletedAnnotations = new RefSet(); + newAnnotationsPromise = Promise.all([annotationGlobalsPromise, this.#replaceIdByRef(newAnnots, deletedAnnotations, null)]).then(([annotationGlobals]) => { + if (!annotationGlobals) { + return null; + } + return AnnotationFactory.printNewAnnotations(annotationGlobals, partialEvaluator, task, newAnnots, imagePromises); + }); + } + const pageListPromise = Promise.all([contentStreamPromise, resourcesPromise]).then(async ([contentStream]) => { + const resources = await this.#getMergedResources(contentStream.dict, RESOURCES_KEYS_OPERATOR_LIST); + const opList = new OperatorList(intent, sink); + handler.send("StartRenderPage", { + transparency: partialEvaluator.hasBlendModes(resources, this.nonBlendModesSet), + pageIndex: this.pageIndex, + cacheKey + }); + await partialEvaluator.getOperatorList({ + stream: contentStream, + task, + resources, + operatorList: opList + }); + return opList; + }); + let [pageOpList, annotations, newAnnotations] = await Promise.all([pageListPromise, this._parsedAnnotations, newAnnotationsPromise]); + if (newAnnotations) { + annotations = annotations.filter((a) => !(a.ref && deletedAnnotations.has(a.ref))); + for (let i = 0, ii = newAnnotations.length; i < ii; i++) { + const newAnnotation = newAnnotations[i]; + if (newAnnotation.refToReplace) { + const j = annotations.findIndex((a) => a.ref && isRefsEqual(a.ref, newAnnotation.refToReplace)); + if (j >= 0) { + annotations.splice(j, 1, newAnnotation); + newAnnotations.splice(i--, 1); + ii--; + } + } + } + annotations = annotations.concat(newAnnotations); + } + if (annotations.length === 0 || intent & RenderingIntentFlag2.ANNOTATIONS_DISABLE) { + pageOpList.flush(true); + return { + length: pageOpList.totalLength + }; + } + const renderForms = !!(intent & RenderingIntentFlag2.ANNOTATIONS_FORMS), isEditing = !!(intent & RenderingIntentFlag2.IS_EDITING), intentAny = !!(intent & RenderingIntentFlag2.ANY), intentDisplay = !!(intent & RenderingIntentFlag2.DISPLAY), intentPrint = !!(intent & RenderingIntentFlag2.PRINT); + const opListPromises = []; + for (const annotation of annotations) { + if (intentAny || intentDisplay && annotation.mustBeViewed(annotationStorage, renderForms) && annotation.mustBeViewedWhenEditing(isEditing, modifiedIds) || intentPrint && annotation.mustBePrinted(annotationStorage)) { + opListPromises.push(annotation.getOperatorList(partialEvaluator, task, intent, annotationStorage).catch(function(reason) { + warn2(`getOperatorList - ignoring annotation data during "${task.name}" task: "${reason}".`); + return { + opList: null, + separateForm: false, + separateCanvas: false + }; + })); + } + } + const opLists = await Promise.all(opListPromises); + let form = false, canvas = false; + for (const { + opList, + separateForm, + separateCanvas + } of opLists) { + pageOpList.addOpList(opList); + form ||= separateForm; + canvas ||= separateCanvas; + } + pageOpList.flush(true, { + form, + canvas + }); + return { + length: pageOpList.totalLength + }; + } + async extractTextContent({ + handler, + task, + includeMarkedContent, + disableNormalization, + sink, + intersector = null + }) { + const contentStreamPromise = this.getContentStream(); + const resourcesPromise = this.loadResources(RESOURCES_KEYS_TEXT_CONTENT); + const langPromise = this.pdfManager.ensureCatalog("lang"); + const [contentStream, , lang] = await Promise.all([contentStreamPromise, resourcesPromise, langPromise]); + const resources = await this.#getMergedResources(contentStream.dict, RESOURCES_KEYS_TEXT_CONTENT); + const partialEvaluator = this.#createPartialEvaluator(handler); + return partialEvaluator.getTextContent({ + stream: contentStream, + task, + resources, + includeMarkedContent, + disableNormalization, + sink, + viewBox: this.view, + lang, + intersector + }); + } + async getStructTree() { + const structTreeRoot = await this.pdfManager.ensureCatalog("structTreeRoot"); + if (!structTreeRoot) { + return null; + } + await this._parsedAnnotations; + try { + const structTree = await this.pdfManager.ensure(this, "_parseStructTree", [structTreeRoot]); + const data = await this.pdfManager.ensure(structTree, "serializable"); + return data; + } catch (ex) { + warn2(`getStructTree: "${ex}".`); + return null; + } + } + _parseStructTree(structTreeRoot) { + const tree = new StructTreePage(structTreeRoot, this.pageDict); + tree.parse(this.ref); + return tree; + } + async getAnnotationsData(handler, task, intent) { + const annotations = await this._parsedAnnotations; + if (annotations.length === 0) { + return annotations; + } + const annotationsData = [], textContentPromises = []; + let partialEvaluator; + const intentAny = !!(intent & RenderingIntentFlag2.ANY), intentDisplay = !!(intent & RenderingIntentFlag2.DISPLAY), intentPrint = !!(intent & RenderingIntentFlag2.PRINT); + const highlightedAnnotations = []; + for (const annotation of annotations) { + const isVisible = intentAny || intentDisplay && annotation.viewable; + if (isVisible || intentPrint && annotation.printable) { + annotationsData.push(annotation.data); + } + if (annotation.hasTextContent && isVisible) { + partialEvaluator ??= this.#createPartialEvaluator(handler); + textContentPromises.push(annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]).catch(function(reason) { + warn2(`getAnnotationsData - ignoring textContent during "${task.name}" task: "${reason}".`); + })); + } else if (annotation.overlaysTextContent && isVisible) { + highlightedAnnotations.push(annotation); + } + } + if (highlightedAnnotations.length > 0) { + const intersector = new Intersector(highlightedAnnotations); + textContentPromises.push(this.extractTextContent({ + handler, + task, + includeMarkedContent: false, + disableNormalization: false, + sink: null, + viewBox: this.view, + lang: null, + intersector + }).then(() => { + intersector.setText(); + })); + } + await Promise.all(textContentPromises); + return annotationsData; + } + get annotations() { + const annots = this.#getInheritableProperty("Annots"); + return shadow2(this, "annotations", Array.isArray(annots) ? annots : []); + } + get _parsedAnnotations() { + const promise2 = this.pdfManager.ensure(this, "annotations").then(async (annots) => { + if (annots.length === 0) { + return annots; + } + const [annotationGlobals, fieldObjects] = await Promise.all([this.pdfManager.ensureDoc("annotationGlobals"), this.pdfManager.ensureDoc("fieldObjects")]); + if (!annotationGlobals) { + return []; + } + const orphanFields = fieldObjects?.orphanFields; + const annotationPromises = []; + for (const annotationRef of annots) { + annotationPromises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, orphanFields, null, this.ref).catch(function(reason) { + warn2(`_parsedAnnotations: "${reason}".`); + return null; + })); + } + const sortedAnnotations = []; + let popupAnnotations, widgetAnnotations; + for (const annotation of await Promise.all(annotationPromises)) { + if (!annotation) { + continue; + } + if (annotation instanceof WidgetAnnotation) { + (widgetAnnotations ||= []).push(annotation); + continue; + } + if (annotation instanceof PopupAnnotation) { + (popupAnnotations ||= []).push(annotation); + continue; + } + sortedAnnotations.push(annotation); + } + if (widgetAnnotations) { + sortedAnnotations.push(...widgetAnnotations); + } + if (popupAnnotations) { + sortedAnnotations.push(...popupAnnotations); + } + return sortedAnnotations; + }); + this.#areAnnotationsCached = true; + return shadow2(this, "_parsedAnnotations", promise2); + } + get jsActions() { + const actions = collectActions(this.xref, this.pageDict, PageActionEventType); + return shadow2(this, "jsActions", actions); + } + async collectAnnotationsByType(handler, task, types3, promises, annotationGlobals) { + const { + pageIndex + } = this; + if (this.#areAnnotationsCached) { + const cachedAnnotations = await this._parsedAnnotations; + for (const { + data + } of cachedAnnotations) { + if (!types3 || types3.has(data.annotationType)) { + data.pageIndex = pageIndex; + promises.push(Promise.resolve(data)); + } + } + return; + } + const annots = await this.pdfManager.ensure(this, "annotations"); + for (const annotationRef of annots) { + promises.push(AnnotationFactory.create(this.xref, annotationRef, annotationGlobals, this._localIdFactory, false, null, types3, this.ref).then(async (annotation) => { + if (!annotation) { + return null; + } + annotation.data.pageIndex = pageIndex; + if (annotation.hasTextContent && annotation.viewable) { + const partialEvaluator = this.#createPartialEvaluator(handler); + await annotation.extractTextContent(partialEvaluator, task, [-Infinity, -Infinity, Infinity, Infinity]); + } + return annotation.data; + }).catch(function(reason) { + warn2(`collectAnnotationsByType: "${reason}".`); + return null; + })); + } + } + }; + PDF_HEADER_SIGNATURE = new Uint8Array([37, 80, 68, 70, 45]); + STARTXREF_SIGNATURE = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]); + ENDOBJ_SIGNATURE = new Uint8Array([101, 110, 100, 111, 98, 106]); + PDFDocument = class { + #pagePromises = /* @__PURE__ */ new Map(); + #version = null; + constructor(pdfManager, stream) { + if (stream.length <= 0) { + throw new InvalidPDFException3("The PDF file is empty, i.e. its size is zero bytes."); + } + this.pdfManager = pdfManager; + this.stream = stream; + this.xref = new XRef(stream, pdfManager); + const idCounters = { + font: 0 + }; + this._globalIdFactory = class { + static getDocId() { + return `g_${pdfManager.docId}`; + } + static createFontId() { + return `f${++idCounters.font}`; + } + static createObjId() { + unreachable2("Abstract method `createObjId` called."); + } + static getPageObjId() { + unreachable2("Abstract method `getPageObjId` called."); + } + }; + } + parse(recoveryMode) { + this.xref.parse(recoveryMode); + this.catalog = new Catalog(this.pdfManager, this.xref); + } + get linearization() { + let linearization = null; + try { + linearization = Linearization.create(this.stream); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info2(err); + } + return shadow2(this, "linearization", linearization); + } + get startXRef() { + const stream = this.stream; + let startXRef = 0; + if (this.linearization) { + stream.reset(); + if (find2(stream, ENDOBJ_SIGNATURE)) { + stream.skip(6); + let ch2 = stream.peekByte(); + while (isWhiteSpace(ch2)) { + stream.pos++; + ch2 = stream.peekByte(); + } + startXRef = stream.pos - stream.start; + } + } else { + const step = 1024; + const startXRefLength = STARTXREF_SIGNATURE.length; + let found = false, pos = stream.end; + while (!found && pos > 0) { + pos -= step - startXRefLength; + if (pos < 0) { + pos = 0; + } + stream.pos = pos; + found = find2(stream, STARTXREF_SIGNATURE, step, true); + } + if (found) { + stream.skip(9); + let ch2; + do { + ch2 = stream.getByte(); + } while (isWhiteSpace(ch2)); + let str = ""; + while (ch2 >= 32 && ch2 <= 57) { + str += String.fromCharCode(ch2); + ch2 = stream.getByte(); + } + startXRef = parseInt(str, 10); + if (isNaN(startXRef)) { + startXRef = 0; + } + } + } + return shadow2(this, "startXRef", startXRef); + } + checkHeader() { + const stream = this.stream; + stream.reset(); + if (!find2(stream, PDF_HEADER_SIGNATURE)) { + return; + } + stream.moveStart(); + stream.skip(PDF_HEADER_SIGNATURE.length); + let version4 = "", ch2; + while ((ch2 = stream.getByte()) > 32 && version4.length < 7) { + version4 += String.fromCharCode(ch2); + } + if (PDF_VERSION_REGEXP.test(version4)) { + this.#version = version4; + } else { + warn2(`Invalid PDF header version: ${version4}`); + } + } + parseStartXRef() { + this.xref.setStartXRef(this.startXRef); + } + get numPages() { + let num = 0; + if (this.catalog.hasActualNumPages) { + num = this.catalog.numPages; + } else if (this.xfaFactory) { + num = this.xfaFactory.getNumPages(); + } else if (this.linearization) { + num = this.linearization.numPages; + } else { + num = this.catalog.numPages; + } + return shadow2(this, "numPages", num); + } + #hasOnlyDocumentSignatures(fields, recursionDepth = 0) { + const RECURSION_LIMIT = 10; + if (!Array.isArray(fields)) { + return false; + } + return fields.every((field) => { + field = this.xref.fetchIfRef(field); + if (!(field instanceof Dict)) { + return false; + } + if (field.has("Kids")) { + if (++recursionDepth > RECURSION_LIMIT) { + warn2("#hasOnlyDocumentSignatures: maximum recursion depth reached"); + return false; + } + return this.#hasOnlyDocumentSignatures(field.get("Kids"), recursionDepth); + } + const isSignature = isName(field.get("FT"), "Sig"); + const rectangle = field.get("Rect"); + const isInvisible = Array.isArray(rectangle) && rectangle.every((value) => value === 0); + return isSignature && isInvisible; + }); + } + #collectSignatureCertificates(fields, collectedSignatureCertificates, visited = new RefSet()) { + if (!Array.isArray(fields)) { + return; + } + for (let field of fields) { + if (field instanceof Ref) { + if (visited.has(field)) { + continue; + } + visited.put(field); + } + field = this.xref.fetchIfRef(field); + if (!(field instanceof Dict)) { + continue; + } + if (field.has("Kids")) { + this.#collectSignatureCertificates(field.get("Kids"), collectedSignatureCertificates, visited); + continue; + } + const isSignature = isName(field.get("FT"), "Sig"); + if (!isSignature) { + continue; + } + const value = field.get("V"); + if (!(value instanceof Dict)) { + continue; + } + const subFilter = value.get("SubFilter"); + if (!(subFilter instanceof Name2)) { + continue; + } + collectedSignatureCertificates.add(subFilter.name); + } + } + get _xfaStreams() { + const { + acroForm + } = this.catalog; + if (!acroForm) { + return null; + } + const xfa = acroForm.get("XFA"); + const entries = new Map(["xdp:xdp", "template", "datasets", "config", "connectionSet", "localeSet", "stylesheet", "/xdp:xdp"].map((e) => [e, null])); + if (xfa instanceof BaseStream && !xfa.isEmpty) { + entries.set("xdp:xdp", xfa); + return entries; + } + if (!Array.isArray(xfa) || xfa.length === 0) { + return null; + } + for (let i = 0, ii = xfa.length; i < ii; i += 2) { + let name; + if (i === 0) { + name = "xdp:xdp"; + } else if (i === ii - 2) { + name = "/xdp:xdp"; + } else { + name = xfa[i]; + } + if (!entries.has(name)) { + continue; + } + const data = this.xref.fetchIfRef(xfa[i + 1]); + if (!(data instanceof BaseStream) || data.isEmpty) { + continue; + } + entries.set(name, data); + } + return entries; + } + get xfaDatasets() { + const streams = this._xfaStreams; + if (!streams) { + return shadow2(this, "xfaDatasets", null); + } + for (const key of ["datasets", "xdp:xdp"]) { + const stream = streams.get(key); + if (!stream) { + continue; + } + try { + const str = stringToUTF8String2(stream.getString()); + const data = { + [key]: str + }; + return shadow2(this, "xfaDatasets", new DatasetReader(data)); + } catch { + warn2("XFA - Invalid utf-8 string."); + break; + } + } + return shadow2(this, "xfaDatasets", null); + } + get xfaData() { + const streams = this._xfaStreams; + if (!streams) { + return null; + } + const data = /* @__PURE__ */ Object.create(null); + for (const [key, stream] of streams) { + if (!stream) { + continue; + } + try { + data[key] = stringToUTF8String2(stream.getString()); + } catch { + warn2("XFA - Invalid utf-8 string."); + return null; + } + } + return data; + } + get xfaFactory() { + let data; + if (this.pdfManager.enableXfa && this.catalog.needsRendering && this.formInfo.hasXfa && !this.formInfo.hasAcroForm) { + data = this.xfaData; + } + return shadow2(this, "xfaFactory", data ? new XFAFactory(data) : null); + } + get isPureXfa() { + return this.xfaFactory ? this.xfaFactory.isValid() : false; + } + get htmlForXfa() { + return this.xfaFactory ? this.xfaFactory.getPages() : null; + } + async #loadXfaImages() { + const xfaImages = await this.pdfManager.ensureCatalog("xfaImages"); + if (!xfaImages) { + return; + } + this.xfaFactory.setImages(xfaImages); + } + async #loadXfaFonts(handler, task) { + const acroForm = await this.pdfManager.ensureCatalog("acroForm"); + if (!acroForm) { + return; + } + const resources = await acroForm.getAsync("DR"); + if (!(resources instanceof Dict)) { + return; + } + await ObjectLoader.load(resources, ["Font"], this.xref); + const fontRes = resources.get("Font"); + if (!(fontRes instanceof Dict)) { + return; + } + const options = Object.assign(/* @__PURE__ */ Object.create(null), this.pdfManager.evaluatorOptions, { + useSystemFonts: false + }); + const { + builtInCMapCache, + fontCache, + standardFontDataCache + } = this.catalog; + const partialEvaluator = new PartialEvaluator({ + xref: this.xref, + handler, + pageIndex: -1, + idFactory: this._globalIdFactory, + fontCache, + builtInCMapCache, + standardFontDataCache, + options + }); + const operatorList = new OperatorList(); + const pdfFonts = []; + const initialState = { + get font() { + return pdfFonts.at(-1); + }, + set font(font) { + pdfFonts.push(font); + }, + clone() { + return this; + } + }; + const parseFont = (fontName, fallbackFontDict, cssFontInfo) => partialEvaluator.handleSetFont(resources, [Name2.get(fontName), 1], null, operatorList, task, initialState, fallbackFontDict, cssFontInfo).catch((reason) => { + warn2(`loadXfaFonts: "${reason}".`); + return null; + }); + const promises = []; + for (const [fontName, font] of fontRes) { + const descriptor = font.get("FontDescriptor"); + if (!(descriptor instanceof Dict)) { + continue; + } + let fontFamily = descriptor.get("FontFamily"); + fontFamily = fontFamily.replaceAll(/[ ]+(\d)/g, "$1"); + const fontWeight = descriptor.get("FontWeight"); + const italicAngle = -descriptor.get("ItalicAngle"); + const cssFontInfo = { + fontFamily, + fontWeight, + italicAngle + }; + if (!validateCSSFont(cssFontInfo)) { + continue; + } + promises.push(parseFont(fontName, null, cssFontInfo)); + } + await Promise.all(promises); + const missingFonts = this.xfaFactory.setFonts(pdfFonts); + if (!missingFonts) { + return; + } + options.ignoreErrors = true; + promises.length = 0; + pdfFonts.length = 0; + const reallyMissingFonts = /* @__PURE__ */ new Set(); + for (const missing of missingFonts) { + if (!getXfaFontName(`${missing}-Regular`)) { + reallyMissingFonts.add(missing); + } + } + if (reallyMissingFonts.size) { + missingFonts.push("PdfJS-Fallback"); + } + for (const missing of missingFonts) { + if (reallyMissingFonts.has(missing)) { + continue; + } + for (const fontInfo of [{ + name: "Regular", + fontWeight: 400, + italicAngle: 0 + }, { + name: "Bold", + fontWeight: 700, + italicAngle: 0 + }, { + name: "Italic", + fontWeight: 400, + italicAngle: 12 + }, { + name: "BoldItalic", + fontWeight: 700, + italicAngle: 12 + }]) { + const name = `${missing}-${fontInfo.name}`; + promises.push(parseFont(name, getXfaFontDict(name), { + fontFamily: missing, + fontWeight: fontInfo.fontWeight, + italicAngle: fontInfo.italicAngle + })); + } + } + await Promise.all(promises); + this.xfaFactory.appendFonts(pdfFonts, reallyMissingFonts); + } + loadXfaResources(handler, task) { + return Promise.all([this.#loadXfaFonts(handler, task).catch(() => { + }), this.#loadXfaImages()]); + } + serializeXfaData(annotationStorage) { + return this.xfaFactory ? this.xfaFactory.serializeData(annotationStorage) : null; + } + get version() { + return this.catalog.version || this.#version; + } + get formInfo() { + const formInfo = { + hasFields: false, + hasAcroForm: false, + hasXfa: false, + hasSignatures: false + }; + const { + acroForm + } = this.catalog; + if (!acroForm) { + return shadow2(this, "formInfo", formInfo); + } + try { + const fields = acroForm.get("Fields"); + const hasFields = Array.isArray(fields) && fields.length > 0; + formInfo.hasFields = hasFields; + const xfa = acroForm.get("XFA"); + formInfo.hasXfa = Array.isArray(xfa) && xfa.length > 0 || xfa instanceof BaseStream && !xfa.isEmpty; + const sigFlags = acroForm.get("SigFlags"); + const hasSignatures = !!(sigFlags & 1); + const hasOnlyDocumentSignatures = hasSignatures && this.#hasOnlyDocumentSignatures(fields); + formInfo.hasAcroForm = hasFields && !hasOnlyDocumentSignatures; + formInfo.hasSignatures = hasSignatures; + } catch (ex) { + if (ex instanceof MissingDataException) { + throw ex; + } + warn2(`Cannot fetch form information: "${ex}".`); + } + return shadow2(this, "formInfo", formInfo); + } + get documentInfo() { + const { + catalog, + formInfo, + xref + } = this; + const docInfo = { + PDFFormatVersion: this.version, + Language: catalog.lang, + EncryptFilterName: xref.encrypt?.filterName ?? null, + IsLinearized: !!this.linearization, + IsAcroFormPresent: formInfo.hasAcroForm, + IsXFAPresent: formInfo.hasXfa, + IsCollectionPresent: !!catalog.collection, + IsSignaturesPresent: formInfo.hasSignatures + }; + let infoDict; + try { + infoDict = xref.trailer.get("Info"); + } catch (err) { + if (err instanceof MissingDataException) { + throw err; + } + info2("The document information dictionary is invalid."); + } + if (!(infoDict instanceof Dict)) { + return shadow2(this, "documentInfo", docInfo); + } + for (const [key, value] of infoDict) { + switch (key) { + case "Title": + case "Author": + case "Subject": + case "Keywords": + case "Creator": + case "Producer": + case "CreationDate": + case "ModDate": + if (typeof value === "string") { + docInfo[key] = stringToPDFString(value); + continue; + } + break; + case "Trapped": + if (value instanceof Name2) { + docInfo[key] = value; + continue; + } + break; + default: + let customValue; + switch (typeof value) { + case "string": + customValue = stringToPDFString(value); + break; + case "number": + case "boolean": + customValue = value; + break; + default: + if (value instanceof Name2) { + customValue = value; + } + break; + } + if (customValue === void 0) { + warn2(`Bad value, for custom key "${key}", in Info: ${value}.`); + continue; + } + docInfo.Custom ??= /* @__PURE__ */ Object.create(null); + docInfo.Custom[key] = customValue; + continue; + } + warn2(`Bad value, for key "${key}", in Info: ${value}.`); + } + return shadow2(this, "documentInfo", docInfo); + } + get fingerprints() { + const FINGERPRINT_FIRST_BYTES = 1024; + const EMPTY_FINGERPRINT = "\0".repeat(16); + function validate2(data) { + return typeof data === "string" && data.length === 16 && data !== EMPTY_FINGERPRINT; + } + const id = this.xref.trailer.get("ID"); + let hashOriginal, hashModified; + if (Array.isArray(id) && validate2(id[0])) { + hashOriginal = stringToBytes2(id[0]); + if (id[1] !== id[0] && validate2(id[1])) { + hashModified = stringToBytes2(id[1]); + } + } else { + hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES); + } + return shadow2(this, "fingerprints", [toHexUtil(hashOriginal), hashModified ? toHexUtil(hashModified) : null]); + } + async #getLinearizationPage(pageIndex) { + const { + catalog, + linearization, + xref + } = this; + const ref = Ref.get(linearization.objectNumberFirst, 0); + try { + const obj2 = await xref.fetchAsync(ref); + if (obj2 instanceof Dict) { + let type = obj2.getRaw("Type"); + if (type instanceof Ref) { + type = await xref.fetchAsync(type); + } + if (isName(type, "Page") || !obj2.has("Type") && !obj2.has("Kids") && obj2.has("Contents")) { + if (!catalog.pageKidsCountCache.has(ref)) { + catalog.pageKidsCountCache.put(ref, 1); + } + if (!catalog.pageIndexCache.has(ref)) { + catalog.pageIndexCache.put(ref, 0); + } + return [obj2, ref]; + } + } + throw new FormatError3("The Linearization dictionary doesn't point to a valid Page dictionary."); + } catch (reason) { + warn2(`_getLinearizationPage: "${reason.message}".`); + return catalog.getPageDict(pageIndex); + } + } + getPage(pageIndex) { + const cachedPromise = this.#pagePromises.get(pageIndex); + if (cachedPromise) { + return cachedPromise; + } + const { + catalog, + linearization, + xfaFactory + } = this; + let promise2; + if (xfaFactory) { + promise2 = Promise.resolve([Dict.empty, null]); + } else if (linearization?.pageFirst === pageIndex) { + promise2 = this.#getLinearizationPage(pageIndex); + } else { + promise2 = catalog.getPageDict(pageIndex); + } + promise2 = promise2.then(([pageDict, ref]) => new Page({ + pdfManager: this.pdfManager, + xref: this.xref, + pageIndex, + pageDict, + ref, + globalIdFactory: this._globalIdFactory, + fontCache: catalog.fontCache, + builtInCMapCache: catalog.builtInCMapCache, + standardFontDataCache: catalog.standardFontDataCache, + globalColorSpaceCache: catalog.globalColorSpaceCache, + globalImageCache: catalog.globalImageCache, + systemFontCache: catalog.systemFontCache, + nonBlendModesSet: catalog.nonBlendModesSet, + xfaFactory + })); + this.#pagePromises.set(pageIndex, promise2); + return promise2; + } + async checkFirstPage(recoveryMode = false) { + if (recoveryMode) { + return; + } + try { + await this.getPage(0); + } catch (reason) { + if (reason instanceof XRefEntryException) { + this.#pagePromises.delete(0); + await this.cleanup(); + throw new XRefParseException(); + } + } + } + async checkLastPage(recoveryMode = false) { + const { + catalog, + pdfManager + } = this; + catalog.setActualNumPages(); + let numPages; + try { + await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]); + if (this.xfaFactory) { + return; + } else if (this.linearization) { + numPages = this.linearization.numPages; + } else { + numPages = catalog.numPages; + } + if (!Number.isInteger(numPages)) { + throw new FormatError3("Page count is not an integer."); + } else if (numPages <= 1) { + return; + } + await this.getPage(numPages - 1); + } catch (reason) { + this.#pagePromises.delete(numPages - 1); + await this.cleanup(); + if (reason instanceof XRefEntryException && !recoveryMode) { + throw new XRefParseException(); + } + warn2(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`); + let pagesTree; + try { + pagesTree = await catalog.getAllPageDicts(recoveryMode); + } catch (reasonAll) { + if (reasonAll instanceof XRefEntryException && !recoveryMode) { + throw new XRefParseException(); + } + catalog.setActualNumPages(1); + return; + } + for (const [pageIndex, [pageDict, ref]] of pagesTree) { + let promise2; + if (pageDict instanceof Error) { + promise2 = Promise.reject(pageDict); + promise2.catch(() => { + }); + } else { + promise2 = Promise.resolve(new Page({ + pdfManager, + xref: this.xref, + pageIndex, + pageDict, + ref, + globalIdFactory: this._globalIdFactory, + fontCache: catalog.fontCache, + builtInCMapCache: catalog.builtInCMapCache, + standardFontDataCache: catalog.standardFontDataCache, + globalColorSpaceCache: this.globalColorSpaceCache, + globalImageCache: catalog.globalImageCache, + systemFontCache: catalog.systemFontCache, + nonBlendModesSet: catalog.nonBlendModesSet, + xfaFactory: null + })); + } + this.#pagePromises.set(pageIndex, promise2); + } + catalog.setActualNumPages(pagesTree.size); + } + } + async fontFallback(id, handler) { + const { + catalog, + pdfManager + } = this; + for (const translatedFont of await Promise.all(catalog.fontCache)) { + if (translatedFont.loadedName === id) { + translatedFont.fallback(handler, pdfManager.evaluatorOptions); + return; + } + } + } + async cleanup(manuallyTriggered = false) { + return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches(); + } + async #collectFieldObjects(name, parentRef, fieldRef, promises, annotationGlobals, visitedRefs, orphanFields) { + const { + xref + } = this; + if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) { + return; + } + visitedRefs.put(fieldRef); + const field = await xref.fetchAsync(fieldRef); + if (!(field instanceof Dict)) { + return; + } + let subtype = await field.getAsync("Subtype"); + subtype = subtype instanceof Name2 ? subtype.name : null; + switch (subtype) { + case "Link": + return; + } + if (field.has("T")) { + const partName = stringToPDFString(await field.getAsync("T")); + name = name === "" ? partName : `${name}.${partName}`; + } else { + let obj2 = field; + while (true) { + obj2 = obj2.getRaw("Parent") || parentRef; + if (obj2 instanceof Ref) { + if (visitedRefs.has(obj2)) { + break; + } + obj2 = await xref.fetchAsync(obj2); + } + if (!(obj2 instanceof Dict)) { + break; + } + if (obj2.has("T")) { + const partName = stringToPDFString(await obj2.getAsync("T")); + name = name === "" ? partName : `${name}.${partName}`; + break; + } + } + } + if (parentRef && !field.has("Parent") && isName(field.get("Subtype"), "Widget")) { + orphanFields.put(fieldRef, parentRef); + } + if (!promises.has(name)) { + promises.set(name, []); + } + promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, orphanFields, null, null).then((annotation) => annotation?.getFieldObject()).catch(function(reason) { + warn2(`#collectFieldObjects: "${reason}".`); + return null; + })); + if (!field.has("Kids")) { + return; + } + const kids = await field.getAsync("Kids"); + if (Array.isArray(kids)) { + for (const kid of kids) { + await this.#collectFieldObjects(name, fieldRef, kid, promises, annotationGlobals, visitedRefs, orphanFields); + } + } + } + get fieldObjects() { + const promise2 = this.pdfManager.ensureDoc("formInfo").then(async (formInfo) => { + if (!formInfo.hasFields) { + return null; + } + const annotationGlobals = await this.annotationGlobals; + if (!annotationGlobals) { + return null; + } + const { + acroForm + } = annotationGlobals; + const visitedRefs = new RefSet(); + const allFields = /* @__PURE__ */ Object.create(null); + const fieldPromises = /* @__PURE__ */ new Map(); + const orphanFields = new RefSetCache(); + for (const fieldRef of acroForm.get("Fields")) { + await this.#collectFieldObjects("", null, fieldRef, fieldPromises, annotationGlobals, visitedRefs, orphanFields); + } + const allPromises = []; + for (const [name, promises] of fieldPromises) { + allPromises.push(Promise.all(promises).then((fields) => { + fields = fields.filter((field) => !!field); + if (fields.length > 0) { + allFields[name] = fields; + } + })); + } + await Promise.all(allPromises); + return { + allFields: objectSize(allFields) > 0 ? allFields : null, + orphanFields + }; + }); + return shadow2(this, "fieldObjects", promise2); + } + get hasJSActions() { + const promise2 = this.pdfManager.ensureDoc("_parseHasJSActions"); + return shadow2(this, "hasJSActions", promise2); + } + async _parseHasJSActions() { + const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]); + if (catalogJsActions) { + return true; + } + if (fieldObjects?.allFields) { + return Object.values(fieldObjects.allFields).some((fieldObject) => fieldObject.some((object3) => object3.actions !== null)); + } + return false; + } + get calculationOrderIds() { + const calculationOrder = this.catalog.acroForm?.get("CO"); + if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) { + return shadow2(this, "calculationOrderIds", null); + } + const ids = []; + for (const id of calculationOrder) { + if (id instanceof Ref) { + ids.push(id.toString()); + } + } + return shadow2(this, "calculationOrderIds", ids.length ? ids : null); + } + get annotationGlobals() { + return shadow2(this, "annotationGlobals", AnnotationFactory.createGlobals(this.pdfManager)); + } + }; + BasePdfManager = class { + constructor({ + docBaseUrl, + docId, + enableXfa, + evaluatorOptions, + handler, + password + }) { + this._docBaseUrl = parseDocBaseUrl(docBaseUrl); + this._docId = docId; + this._password = password; + this.enableXfa = enableXfa; + evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest2.isOffscreenCanvasSupported; + evaluatorOptions.isImageDecoderSupported &&= FeatureTest2.isImageDecoderSupported; + this.evaluatorOptions = Object.freeze(evaluatorOptions); + ImageResizer.setOptions(evaluatorOptions); + JpegStream.setOptions(evaluatorOptions); + OperatorList.setOptions(evaluatorOptions); + const options = { + ...evaluatorOptions, + handler + }; + JpxImage.setOptions(options); + IccColorSpace.setOptions(options); + CmykICCBasedCS.setOptions(options); + } + get docId() { + return this._docId; + } + get password() { + return this._password; + } + get docBaseUrl() { + return this._docBaseUrl; + } + ensureDoc(prop, args) { + return this.ensure(this.pdfDocument, prop, args); + } + ensureXRef(prop, args) { + return this.ensure(this.pdfDocument.xref, prop, args); + } + ensureCatalog(prop, args) { + return this.ensure(this.pdfDocument.catalog, prop, args); + } + getPage(pageIndex) { + return this.pdfDocument.getPage(pageIndex); + } + fontFallback(id, handler) { + return this.pdfDocument.fontFallback(id, handler); + } + cleanup(manuallyTriggered = false) { + return this.pdfDocument.cleanup(manuallyTriggered); + } + async ensure(obj2, prop, args) { + unreachable2("Abstract method `ensure` called"); + } + requestRange(begin, end) { + unreachable2("Abstract method `requestRange` called"); + } + requestLoadedStream(noFetch = false) { + unreachable2("Abstract method `requestLoadedStream` called"); + } + sendProgressiveData(chunk2) { + unreachable2("Abstract method `sendProgressiveData` called"); + } + updatePassword(password) { + this._password = password; + } + terminate(reason) { + unreachable2("Abstract method `terminate` called"); + } + }; + LocalPdfManager = class extends BasePdfManager { + constructor(args) { + super(args); + const stream = new Stream3(args.source); + this.pdfDocument = new PDFDocument(this, stream); + this._loadedStreamPromise = Promise.resolve(stream); + } + async ensure(obj2, prop, args) { + const value = obj2[prop]; + if (typeof value === "function") { + return value.apply(obj2, args); + } + return value; + } + requestRange(begin, end) { + return Promise.resolve(); + } + requestLoadedStream(noFetch = false) { + return this._loadedStreamPromise; + } + terminate(reason) { + } + }; + NetworkPdfManager = class extends BasePdfManager { + constructor(args) { + super(args); + this.streamManager = new ChunkedStreamManager(args.source, { + msgHandler: args.handler, + length: args.length, + disableAutoFetch: args.disableAutoFetch, + rangeChunkSize: args.rangeChunkSize + }); + this.pdfDocument = new PDFDocument(this, this.streamManager.getStream()); + } + async ensure(obj2, prop, args) { + try { + const value = obj2[prop]; + if (typeof value === "function") { + return value.apply(obj2, args); + } + return value; + } catch (ex) { + if (!(ex instanceof MissingDataException)) { + throw ex; + } + await this.requestRange(ex.begin, ex.end); + return this.ensure(obj2, prop, args); + } + } + requestRange(begin, end) { + return this.streamManager.requestRange(begin, end); + } + requestLoadedStream(noFetch = false) { + return this.streamManager.requestAllChunks(noFetch); + } + sendProgressiveData(chunk2) { + this.streamManager.onReceiveData({ + chunk: chunk2 + }); + } + terminate(reason) { + this.streamManager.abort(reason); + } + }; + CallbackKind2 = { + DATA: 1, + ERROR: 2 + }; + StreamKind2 = { + CANCEL: 1, + CANCEL_COMPLETE: 2, + CLOSE: 3, + ENQUEUE: 4, + ERROR: 5, + PULL: 6, + PULL_COMPLETE: 7, + START_COMPLETE: 8 + }; + MessageHandler2 = class { + #messageAC = new AbortController(); + constructor(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackId = 1; + this.streamId = 1; + this.streamSinks = /* @__PURE__ */ Object.create(null); + this.streamControllers = /* @__PURE__ */ Object.create(null); + this.callbackCapabilities = /* @__PURE__ */ Object.create(null); + this.actionHandler = /* @__PURE__ */ Object.create(null); + comObj.addEventListener("message", this.#onMessage.bind(this), { + signal: this.#messageAC.signal + }); + } + #onMessage({ + data + }) { + if (data.targetName !== this.sourceName) { + return; + } + if (data.stream) { + this.#processStreamMessage(data); + return; + } + if (data.callback) { + const callbackId = data.callbackId; + const capability = this.callbackCapabilities[callbackId]; + if (!capability) { + throw new Error(`Cannot resolve callback ${callbackId}`); + } + delete this.callbackCapabilities[callbackId]; + if (data.callback === CallbackKind2.DATA) { + capability.resolve(data.data); + } else if (data.callback === CallbackKind2.ERROR) { + capability.reject(wrapReason2(data.reason)); + } else { + throw new Error("Unexpected callback case"); + } + return; + } + const action = this.actionHandler[data.action]; + if (!action) { + throw new Error(`Unknown action from worker: ${data.action}`); + } + if (data.callbackId) { + const sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + Promise.try(action, data.data).then(function(result2) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind2.DATA, + callbackId: data.callbackId, + data: result2 + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind2.ERROR, + callbackId: data.callbackId, + reason: wrapReason2(reason) + }); + }); + return; + } + if (data.streamId) { + this.#createStreamSink(data); + return; + } + action(data.data); + } + on(actionName, handler) { + const ah = this.actionHandler; + if (ah[actionName]) { + throw new Error(`There is already an actionName called "${actionName}"`); + } + ah[actionName] = handler; + } + send(actionName, data, transfers) { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data + }, transfers); + } + sendWithPromise(actionName, data, transfers) { + const callbackId = this.callbackId++; + const capability = Promise.withResolvers(); + this.callbackCapabilities[callbackId] = capability; + try { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + callbackId, + data + }, transfers); + } catch (ex) { + capability.reject(ex); + } + return capability.promise; + } + sendWithStream(actionName, data, queueingStrategy, transfers) { + const streamId = this.streamId++, sourceName = this.sourceName, targetName = this.targetName, comObj = this.comObj; + return new ReadableStream({ + start: (controller) => { + const startCapability = Promise.withResolvers(); + this.streamControllers[streamId] = { + controller, + startCall: startCapability, + pullCall: null, + cancelCall: null, + isClosed: false + }; + comObj.postMessage({ + sourceName, + targetName, + action: actionName, + streamId, + data, + desiredSize: controller.desiredSize + }, transfers); + return startCapability.promise; + }, + pull: (controller) => { + const pullCapability = Promise.withResolvers(); + this.streamControllers[streamId].pullCall = pullCapability; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.PULL, + streamId, + desiredSize: controller.desiredSize + }); + return pullCapability.promise; + }, + cancel: (reason) => { + assert3(reason instanceof Error, "cancel must have a valid reason"); + const cancelCapability = Promise.withResolvers(); + this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.CANCEL, + streamId, + reason: wrapReason2(reason) + }); + return cancelCapability.promise; + } + }, queueingStrategy); + } + #createStreamSink(data) { + const streamId = data.streamId, sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + const self2 = this, action = this.actionHandler[data.action]; + const streamSink = { + enqueue(chunk2, size3 = 1, transfers) { + if (this.isCancelled) { + return; + } + const lastDesiredSize = this.desiredSize; + this.desiredSize -= size3; + if (lastDesiredSize > 0 && this.desiredSize <= 0) { + this.sinkCapability = Promise.withResolvers(); + this.ready = this.sinkCapability.promise; + } + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.ENQUEUE, + streamId, + chunk: chunk2 + }, transfers); + }, + close() { + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.CLOSE, + streamId + }); + delete self2.streamSinks[streamId]; + }, + error(reason) { + assert3(reason instanceof Error, "error must have a valid reason"); + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.ERROR, + streamId, + reason: wrapReason2(reason) + }); + }, + sinkCapability: Promise.withResolvers(), + onPull: null, + onCancel: null, + isCancelled: false, + desiredSize: data.desiredSize, + ready: null + }; + streamSink.sinkCapability.resolve(); + streamSink.ready = streamSink.sinkCapability.promise; + this.streamSinks[streamId] = streamSink; + Promise.try(action, data.data, streamSink).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.START_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.START_COMPLETE, + streamId, + reason: wrapReason2(reason) + }); + }); + } + #processStreamMessage(data) { + const streamId = data.streamId, sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + const streamController = this.streamControllers[streamId], streamSink = this.streamSinks[streamId]; + switch (data.stream) { + case StreamKind2.START_COMPLETE: + if (data.success) { + streamController.startCall.resolve(); + } else { + streamController.startCall.reject(wrapReason2(data.reason)); + } + break; + case StreamKind2.PULL_COMPLETE: + if (data.success) { + streamController.pullCall.resolve(); + } else { + streamController.pullCall.reject(wrapReason2(data.reason)); + } + break; + case StreamKind2.PULL: + if (!streamSink) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.PULL_COMPLETE, + streamId, + success: true + }); + break; + } + if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { + streamSink.sinkCapability.resolve(); + } + streamSink.desiredSize = data.desiredSize; + Promise.try(streamSink.onPull || onFn2).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.PULL_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.PULL_COMPLETE, + streamId, + reason: wrapReason2(reason) + }); + }); + break; + case StreamKind2.ENQUEUE: + assert3(streamController, "enqueue should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.controller.enqueue(data.chunk); + break; + case StreamKind2.CLOSE: + assert3(streamController, "close should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.isClosed = true; + streamController.controller.close(); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind2.ERROR: + assert3(streamController, "error should have stream controller"); + streamController.controller.error(wrapReason2(data.reason)); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind2.CANCEL_COMPLETE: + if (data.success) { + streamController.cancelCall.resolve(); + } else { + streamController.cancelCall.reject(wrapReason2(data.reason)); + } + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind2.CANCEL: + if (!streamSink) { + break; + } + const dataReason = wrapReason2(data.reason); + Promise.try(streamSink.onCancel || onFn2, dataReason).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.CANCEL_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind2.CANCEL_COMPLETE, + streamId, + reason: wrapReason2(reason) + }); + }); + streamSink.sinkCapability.reject(dataReason); + streamSink.isCancelled = true; + delete this.streamSinks[streamId]; + break; + default: + throw new Error("Unexpected stream case"); + } + } + async #deleteStreamController(streamController, streamId) { + await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]); + delete this.streamControllers[streamId]; + } + destroy() { + this.#messageAC?.abort(); + this.#messageAC = null; + } + }; + PDFWorkerStream = class { + constructor(msgHandler) { + this._msgHandler = msgHandler; + this._contentLength = null; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + getFullReader() { + assert3(!this._fullRequestReader, "PDFWorkerStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler); + return this._fullRequestReader; + } + getRangeReader(begin, end) { + const reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler); + this._rangeRequestReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } + }; + PDFWorkerStreamReader = class { + constructor(msgHandler) { + this._msgHandler = msgHandler; + this.onProgress = null; + this._contentLength = null; + this._isRangeSupported = false; + this._isStreamingSupported = false; + const readableStream = this._msgHandler.sendWithStream("GetReader"); + this._reader = readableStream.getReader(); + this._headersReady = this._msgHandler.sendWithPromise("ReaderHeadersReady").then((data) => { + this._isStreamingSupported = data.isStreamingSupported; + this._isRangeSupported = data.isRangeSupported; + this._contentLength = data.contentLength; + }); + } + get headersReady() { + return this._headersReady; + } + get contentLength() { + return this._contentLength; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + get isRangeSupported() { + return this._isRangeSupported; + } + async read() { + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value: void 0, + done: true + }; + } + return { + value: value.buffer, + done: false + }; + } + cancel(reason) { + this._reader.cancel(reason); + } + }; + PDFWorkerStreamRangeReader = class { + constructor(begin, end, msgHandler) { + this._msgHandler = msgHandler; + this.onProgress = null; + const readableStream = this._msgHandler.sendWithStream("GetRangeReader", { + begin, + end + }); + this._reader = readableStream.getReader(); + } + get isStreamingSupported() { + return false; + } + async read() { + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value: void 0, + done: true + }; + } + return { + value: value.buffer, + done: false + }; + } + cancel(reason) { + this._reader.cancel(reason); + } + }; + WorkerTask = class { + constructor(name) { + this.name = name; + this.terminated = false; + this._capability = Promise.withResolvers(); + } + get finished() { + return this._capability.promise; + } + finish() { + this._capability.resolve(); + } + terminate() { + this.terminated = true; + } + ensureNotTerminated() { + if (this.terminated) { + throw new Error("Worker task was terminated"); + } + } + }; + WorkerMessageHandler = class { + static { + if (typeof window === "undefined" && !isNodeJS2 && typeof self !== "undefined" && typeof self.postMessage === "function" && "onmessage" in self) { + this.initializeFromPort(self); + } + } + static setup(handler, port) { + let testMessageProcessed = false; + handler.on("test", (data) => { + if (testMessageProcessed) { + return; + } + testMessageProcessed = true; + handler.send("test", data instanceof Uint8Array); + }); + handler.on("configure", (data) => { + setVerbosityLevel2(data.verbosity); + }); + handler.on("GetDocRequest", (data) => this.createDocumentHandler(data, port)); + } + static createDocumentHandler(docParams, port) { + let pdfManager; + let terminated = false; + let cancelXHRs = null; + const WorkerTasks = /* @__PURE__ */ new Set(); + const verbosity3 = getVerbosityLevel2(); + const { + docId, + apiVersion + } = docParams; + const workerVersion = "5.4.296"; + if (apiVersion !== workerVersion) { + throw new Error(`The API version "${apiVersion}" does not match the Worker version "${workerVersion}".`); + } + const buildMsg = (type, prop) => `The \`${type}.prototype\` contains unexpected enumerable property "${prop}", thus breaking e.g. \`for...in\` iteration of ${type}s.`; + for (const prop in {}) { + throw new Error(buildMsg("Object", prop)); + } + for (const prop in []) { + throw new Error(buildMsg("Array", prop)); + } + const workerHandlerName = docId + "_worker"; + let handler = new MessageHandler2(workerHandlerName, docId, port); + function ensureNotTerminated() { + if (terminated) { + throw new Error("Worker was terminated"); + } + } + function startWorkerTask(task) { + WorkerTasks.add(task); + } + function finishWorkerTask(task) { + task.finish(); + WorkerTasks.delete(task); + } + async function loadDocument(recoveryMode) { + await pdfManager.ensureDoc("checkHeader"); + await pdfManager.ensureDoc("parseStartXRef"); + await pdfManager.ensureDoc("parse", [recoveryMode]); + await pdfManager.ensureDoc("checkFirstPage", [recoveryMode]); + await pdfManager.ensureDoc("checkLastPage", [recoveryMode]); + const isPureXfa = await pdfManager.ensureDoc("isPureXfa"); + if (isPureXfa) { + const task = new WorkerTask("loadXfaResources"); + startWorkerTask(task); + await pdfManager.ensureDoc("loadXfaResources", [handler, task]); + finishWorkerTask(task); + } + const [numPages, fingerprints] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("fingerprints")]); + const htmlForXfa = isPureXfa ? await pdfManager.ensureDoc("htmlForXfa") : null; + return { + numPages, + fingerprints, + htmlForXfa + }; + } + async function getPdfManager({ + data, + password, + disableAutoFetch, + rangeChunkSize, + length, + docBaseUrl, + enableXfa, + evaluatorOptions + }) { + const pdfManagerArgs = { + source: null, + disableAutoFetch, + docBaseUrl, + docId, + enableXfa, + evaluatorOptions, + handler, + length, + password, + rangeChunkSize + }; + if (data) { + pdfManagerArgs.source = data; + return new LocalPdfManager(pdfManagerArgs); + } + const pdfStream = new PDFWorkerStream(handler), fullRequest = pdfStream.getFullReader(); + const pdfManagerCapability = Promise.withResolvers(); + let newPdfManager, cachedChunks = [], loaded = 0; + fullRequest.headersReady.then(function() { + if (!fullRequest.isRangeSupported) { + return; + } + pdfManagerArgs.source = pdfStream; + pdfManagerArgs.length = fullRequest.contentLength; + pdfManagerArgs.disableAutoFetch ||= fullRequest.isStreamingSupported; + newPdfManager = new NetworkPdfManager(pdfManagerArgs); + for (const chunk2 of cachedChunks) { + newPdfManager.sendProgressiveData(chunk2); + } + cachedChunks = []; + pdfManagerCapability.resolve(newPdfManager); + cancelXHRs = null; + }).catch(function(reason) { + pdfManagerCapability.reject(reason); + cancelXHRs = null; + }); + new Promise(function(resolve2, reject2) { + const readChunk = function({ + value, + done + }) { + try { + ensureNotTerminated(); + if (done) { + if (!newPdfManager) { + const pdfFile = arrayBuffersToBytes(cachedChunks); + cachedChunks = []; + if (length && pdfFile.length !== length) { + warn2("reported HTTP length is different from actual"); + } + pdfManagerArgs.source = pdfFile; + newPdfManager = new LocalPdfManager(pdfManagerArgs); + pdfManagerCapability.resolve(newPdfManager); + } + cancelXHRs = null; + return; + } + loaded += value.byteLength; + if (!fullRequest.isStreamingSupported) { + handler.send("DocProgress", { + loaded, + total: Math.max(loaded, fullRequest.contentLength || 0) + }); + } + if (newPdfManager) { + newPdfManager.sendProgressiveData(value); + } else { + cachedChunks.push(value); + } + fullRequest.read().then(readChunk, reject2); + } catch (e) { + reject2(e); + } + }; + fullRequest.read().then(readChunk, reject2); + }).catch(function(e) { + pdfManagerCapability.reject(e); + cancelXHRs = null; + }); + cancelXHRs = (reason) => { + pdfStream.cancelAllRequests(reason); + }; + return pdfManagerCapability.promise; + } + function setupDoc(data) { + function onSuccess(doc) { + ensureNotTerminated(); + handler.send("GetDoc", { + pdfInfo: doc + }); + } + function onFailure(ex) { + ensureNotTerminated(); + if (ex instanceof PasswordException3) { + const task = new WorkerTask(`PasswordException: response ${ex.code}`); + startWorkerTask(task); + handler.sendWithPromise("PasswordRequest", ex).then(function({ + password + }) { + finishWorkerTask(task); + pdfManager.updatePassword(password); + pdfManagerReady(); + }).catch(function() { + finishWorkerTask(task); + handler.send("DocException", ex); + }); + } else { + handler.send("DocException", wrapReason2(ex)); + } + } + function pdfManagerReady() { + ensureNotTerminated(); + loadDocument(false).then(onSuccess, function(reason) { + ensureNotTerminated(); + if (!(reason instanceof XRefParseException)) { + onFailure(reason); + return; + } + pdfManager.requestLoadedStream().then(function() { + ensureNotTerminated(); + loadDocument(true).then(onSuccess, onFailure); + }); + }); + } + ensureNotTerminated(); + getPdfManager(data).then(function(newPdfManager) { + if (terminated) { + newPdfManager.terminate(new AbortException3("Worker was terminated.")); + throw new Error("Worker was terminated"); + } + pdfManager = newPdfManager; + pdfManager.requestLoadedStream(true).then((stream) => { + handler.send("DataLoaded", { + length: stream.bytes.byteLength + }); + }); + }).then(pdfManagerReady, onFailure); + } + handler.on("GetPage", function(data) { + return pdfManager.getPage(data.pageIndex).then(function(page) { + return Promise.all([pdfManager.ensure(page, "rotate"), pdfManager.ensure(page, "ref"), pdfManager.ensure(page, "userUnit"), pdfManager.ensure(page, "view")]).then(function([rotate, ref, userUnit, view]) { + return { + rotate, + ref, + refStr: ref?.toString() ?? null, + userUnit, + view + }; + }); + }); + }); + handler.on("GetPageIndex", function(data) { + const pageRef = Ref.get(data.num, data.gen); + return pdfManager.ensureCatalog("getPageIndex", [pageRef]); + }); + handler.on("GetDestinations", function(data) { + return pdfManager.ensureCatalog("destinations"); + }); + handler.on("GetDestination", function(data) { + return pdfManager.ensureCatalog("getDestination", [data.id]); + }); + handler.on("GetPageLabels", function(data) { + return pdfManager.ensureCatalog("pageLabels"); + }); + handler.on("GetPageLayout", function(data) { + return pdfManager.ensureCatalog("pageLayout"); + }); + handler.on("GetPageMode", function(data) { + return pdfManager.ensureCatalog("pageMode"); + }); + handler.on("GetViewerPreferences", function(data) { + return pdfManager.ensureCatalog("viewerPreferences"); + }); + handler.on("GetOpenAction", function(data) { + return pdfManager.ensureCatalog("openAction"); + }); + handler.on("GetAttachments", function(data) { + return pdfManager.ensureCatalog("attachments"); + }); + handler.on("GetDocJSActions", function(data) { + return pdfManager.ensureCatalog("jsActions"); + }); + handler.on("GetPageJSActions", function({ + pageIndex + }) { + return pdfManager.getPage(pageIndex).then((page) => pdfManager.ensure(page, "jsActions")); + }); + handler.on("GetAnnotationsByType", async function({ + types: types3, + pageIndexesToSkip + }) { + const [numPages, annotationGlobals] = await Promise.all([pdfManager.ensureDoc("numPages"), pdfManager.ensureDoc("annotationGlobals")]); + if (!annotationGlobals) { + return null; + } + const pagePromises = []; + const annotationPromises = []; + let task = null; + try { + for (let i = 0, ii = numPages; i < ii; i++) { + if (pageIndexesToSkip?.has(i)) { + continue; + } + if (!task) { + task = new WorkerTask("GetAnnotationsByType"); + startWorkerTask(task); + } + pagePromises.push(pdfManager.getPage(i).then(async (page) => { + if (!page) { + return []; + } + return page.collectAnnotationsByType(handler, task, types3, annotationPromises, annotationGlobals) || []; + })); + } + await Promise.all(pagePromises); + const annotations = await Promise.all(annotationPromises); + return annotations.filter((a) => !!a); + } finally { + if (task) { + finishWorkerTask(task); + } + } + }); + handler.on("GetOutline", function(data) { + return pdfManager.ensureCatalog("documentOutline"); + }); + handler.on("GetOptionalContentConfig", function(data) { + return pdfManager.ensureCatalog("optionalContentConfig"); + }); + handler.on("GetPermissions", function(data) { + return pdfManager.ensureCatalog("permissions"); + }); + handler.on("GetMetadata", function(data) { + return Promise.all([pdfManager.ensureDoc("documentInfo"), pdfManager.ensureCatalog("metadata")]); + }); + handler.on("GetMarkInfo", function(data) { + return pdfManager.ensureCatalog("markInfo"); + }); + handler.on("GetData", function(data) { + return pdfManager.requestLoadedStream().then((stream) => stream.bytes); + }); + handler.on("GetAnnotations", function({ + pageIndex, + intent + }) { + return pdfManager.getPage(pageIndex).then(function(page) { + const task = new WorkerTask(`GetAnnotations: page ${pageIndex}`); + startWorkerTask(task); + return page.getAnnotationsData(handler, task, intent).then((data) => { + finishWorkerTask(task); + return data; + }, (reason) => { + finishWorkerTask(task); + throw reason; + }); + }); + }); + handler.on("GetFieldObjects", function(data) { + return pdfManager.ensureDoc("fieldObjects").then((fieldObjects) => fieldObjects?.allFields || null); + }); + handler.on("HasJSActions", function(data) { + return pdfManager.ensureDoc("hasJSActions"); + }); + handler.on("GetCalculationOrderIds", function(data) { + return pdfManager.ensureDoc("calculationOrderIds"); + }); + handler.on("SaveDocument", async function({ + isPureXfa, + numPages, + annotationStorage, + filename + }) { + const globalPromises = [pdfManager.requestLoadedStream(), pdfManager.ensureCatalog("acroForm"), pdfManager.ensureCatalog("acroFormRef"), pdfManager.ensureDoc("startXRef"), pdfManager.ensureDoc("xref"), pdfManager.ensureCatalog("structTreeRoot")]; + const changes = new RefSetCache(); + const promises = []; + const newAnnotationsByPage = !isPureXfa ? getNewAnnotationsMap(annotationStorage) : null; + const [stream, acroForm, acroFormRef, startXRef, xref, _structTreeRoot] = await Promise.all(globalPromises); + const catalogRef = xref.trailer.getRaw("Root") || null; + let structTreeRoot; + if (newAnnotationsByPage) { + if (!_structTreeRoot) { + if (await StructTreeRoot.canCreateStructureTree({ + catalogRef, + pdfManager, + newAnnotationsByPage + })) { + structTreeRoot = null; + } + } else if (await _structTreeRoot.canUpdateStructTree({ + pdfManager, + newAnnotationsByPage + })) { + structTreeRoot = _structTreeRoot; + } + const imagePromises = AnnotationFactory.generateImages(annotationStorage.values(), xref, pdfManager.evaluatorOptions.isOffscreenCanvasSupported); + const newAnnotationPromises = structTreeRoot === void 0 ? promises : []; + for (const [pageIndex, annotations] of newAnnotationsByPage) { + newAnnotationPromises.push(pdfManager.getPage(pageIndex).then((page) => { + const task = new WorkerTask(`Save (editor): page ${pageIndex}`); + startWorkerTask(task); + return page.saveNewAnnotations(handler, task, annotations, imagePromises, changes).finally(function() { + finishWorkerTask(task); + }); + })); + } + if (structTreeRoot === null) { + promises.push(Promise.all(newAnnotationPromises).then(async () => { + await StructTreeRoot.createStructureTree({ + newAnnotationsByPage, + xref, + catalogRef, + pdfManager, + changes + }); + })); + } else if (structTreeRoot) { + promises.push(Promise.all(newAnnotationPromises).then(async () => { + await structTreeRoot.updateStructureTree({ + newAnnotationsByPage, + pdfManager, + changes + }); + })); + } + } + if (isPureXfa) { + promises.push(pdfManager.ensureDoc("serializeXfaData", [annotationStorage])); + } else { + for (let pageIndex = 0; pageIndex < numPages; pageIndex++) { + promises.push(pdfManager.getPage(pageIndex).then(function(page) { + const task = new WorkerTask(`Save: page ${pageIndex}`); + startWorkerTask(task); + return page.save(handler, task, annotationStorage, changes).finally(function() { + finishWorkerTask(task); + }); + })); + } + } + const refs = await Promise.all(promises); + let xfaData = null; + if (isPureXfa) { + xfaData = refs[0]; + if (!xfaData) { + return stream.bytes; + } + } else if (changes.size === 0) { + return stream.bytes; + } + const needAppearances = acroFormRef && acroForm instanceof Dict && changes.values().some((ref) => ref.needAppearances); + const xfa = acroForm instanceof Dict && acroForm.get("XFA") || null; + let xfaDatasetsRef = null; + let hasXfaDatasetsEntry = false; + if (Array.isArray(xfa)) { + for (let i = 0, ii = xfa.length; i < ii; i += 2) { + if (xfa[i] === "datasets") { + xfaDatasetsRef = xfa[i + 1]; + hasXfaDatasetsEntry = true; + } + } + if (xfaDatasetsRef === null) { + xfaDatasetsRef = xref.getNewTemporaryRef(); + } + } else if (xfa) { + warn2("Unsupported XFA type."); + } + let newXrefInfo = /* @__PURE__ */ Object.create(null); + if (xref.trailer) { + const infoMap = /* @__PURE__ */ new Map(); + const xrefInfo = xref.trailer.get("Info") || null; + if (xrefInfo instanceof Dict) { + for (const [key, value] of xrefInfo) { + if (typeof value === "string") { + infoMap.set(key, stringToPDFString(value)); + } + } + } + newXrefInfo = { + rootRef: catalogRef, + encryptRef: xref.trailer.getRaw("Encrypt") || null, + newRef: xref.getNewTemporaryRef(), + infoRef: xref.trailer.getRaw("Info") || null, + infoMap, + fileIds: xref.trailer.get("ID") || null, + startXRef, + filename + }; + } + return incrementalUpdate({ + originalData: stream.bytes, + xrefInfo: newXrefInfo, + changes, + xref, + hasXfa: !!xfa, + xfaDatasetsRef, + hasXfaDatasetsEntry, + needAppearances, + acroFormRef, + acroForm, + xfaData, + useXrefStream: isDict(xref.topDict, "XRef") + }).finally(() => { + xref.resetNewTemporaryRef(); + }); + }); + handler.on("GetOperatorList", function(data, sink) { + const pageIndex = data.pageIndex; + pdfManager.getPage(pageIndex).then(function(page) { + const task = new WorkerTask(`GetOperatorList: page ${pageIndex}`); + startWorkerTask(task); + const start = verbosity3 >= VerbosityLevel2.INFOS ? Date.now() : 0; + page.getOperatorList({ + handler, + sink, + task, + intent: data.intent, + cacheKey: data.cacheKey, + annotationStorage: data.annotationStorage, + modifiedIds: data.modifiedIds + }).then(function(operatorListInfo) { + finishWorkerTask(task); + if (start) { + info2(`page=${pageIndex + 1} - getOperatorList: time=${Date.now() - start}ms, len=${operatorListInfo.length}`); + } + sink.close(); + }, function(reason) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + sink.error(reason); + }); + }); + }); + handler.on("GetTextContent", function(data, sink) { + const { + pageIndex, + includeMarkedContent, + disableNormalization + } = data; + pdfManager.getPage(pageIndex).then(function(page) { + const task = new WorkerTask("GetTextContent: page " + pageIndex); + startWorkerTask(task); + const start = verbosity3 >= VerbosityLevel2.INFOS ? Date.now() : 0; + page.extractTextContent({ + handler, + task, + sink, + includeMarkedContent, + disableNormalization + }).then(function() { + finishWorkerTask(task); + if (start) { + info2(`page=${pageIndex + 1} - getTextContent: time=${Date.now() - start}ms`); + } + sink.close(); + }, function(reason) { + finishWorkerTask(task); + if (task.terminated) { + return; + } + sink.error(reason); + }); + }); + }); + handler.on("GetStructTree", function(data) { + return pdfManager.getPage(data.pageIndex).then((page) => pdfManager.ensure(page, "getStructTree")); + }); + handler.on("FontFallback", function(data) { + return pdfManager.fontFallback(data.id, handler); + }); + handler.on("Cleanup", function(data) { + return pdfManager.cleanup(true); + }); + handler.on("Terminate", function(data) { + terminated = true; + const waitOn = []; + if (pdfManager) { + pdfManager.terminate(new AbortException3("Worker was terminated.")); + const cleanupPromise = pdfManager.cleanup(); + waitOn.push(cleanupPromise); + pdfManager = null; + } else { + clearGlobalCaches(); + } + cancelXHRs?.(new AbortException3("Worker was terminated.")); + for (const task of WorkerTasks) { + waitOn.push(task.finished); + task.terminate(); + } + return Promise.all(waitOn).then(function() { + handler.destroy(); + handler = null; + }); + }); + handler.on("Ready", function(data) { + setupDoc(docParams); + docParams = null; + }); + return workerHandlerName; + } + static initializeFromPort(port) { + const handler = new MessageHandler2("worker", "main", port); + this.setup(handler, port); + handler.send("ready", null); + } + }; + globalThis.pdfjsWorker = { + WorkerMessageHandler + }; + } +}); + // packages/auth-kit/src/actor.ts function buildActor(claims, permissions = {}) { return { @@ -87954,8 +150106,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -87983,6 +150165,33 @@ function decodeCursor(cursor) { return null; } } +var PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +function isPostgresTimestamp(text2) { + const match = PG_TIMESTAMP.exec(text2); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number); + const date6 = new Date(Date.UTC(year, month - 1, day)); + const realDate = year >= 1e3 && date6.getUTCFullYear() === year && date6.getUTCMonth() === month - 1 && date6.getUTCDate() === day; + const offsetHours = match[7] === void 0 ? 0 : Number(match[7]); + const offsetMinutes = match[8] === void 0 ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseTimeCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== "string" || typeof id !== "string" || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -87991,39 +150200,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -88057,12 +150288,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -88383,16 +150618,16 @@ var isCryptoKey = (key) => { }; var isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject"; var isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key); -function message(msg, actual, ...types2) { - if (types2.length > 2) { - const last2 = types2.pop(); - msg += `one of type ${types2.join(", ")}, or ${last2}.`; - } else types2.length === 2 ? msg += `one of type ${types2[0]} or ${types2[1]}.` : msg += `of type ${types2[0]}.`; +function message(msg, actual, ...types3) { + if (types3.length > 2) { + const last2 = types3.pop(); + msg += `one of type ${types3.join(", ")}, or ${last2}.`; + } else types3.length === 2 ? msg += `one of type ${types3[0]} or ${types3[1]}.` : msg += `of type ${types3[0]}.`; return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg; } function invalidKeyType(alg, actual, secret) { - const types2 = ["CryptoKey", "KeyObject", "JSON Web Key"]; - return secret && types2.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types2)); + const types3 = ["CryptoKey", "KeyObject", "JSON Web Key"]; + return secret && types3.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types3)); } var unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); function checkUsage(key, usage) { @@ -89632,10 +151867,10 @@ function mergeDefs(...defs) { function cloneDef(schema) { return mergeDefs(schema._zod.def); } -function getElementAtPath(obj2, path) { - if (!path) +function getElementAtPath(obj2, path2) { + if (!path2) return obj2; - return path.reduce((acc, key) => acc?.[key], obj2); + return path2.reduce((acc, key) => acc?.[key], obj2); } function promiseAllObject(promisesObj) { const keys2 = Object.keys(promisesObj); @@ -89649,10 +151884,10 @@ function promiseAllObject(promisesObj) { }); } function randomString(length = 10) { - const chars = "abcdefghijklmnopqrstuvwxyz"; + const chars2 = "abcdefghijklmnopqrstuvwxyz"; let str = ""; for (let i = 0; i < length; i++) { - str += chars[Math.floor(Math.random() * chars.length)]; + str += chars2[Math.floor(Math.random() * chars2.length)]; } return str; } @@ -89975,11 +152210,11 @@ function explicitlyAborted(x, startIndex = 0) { } return false; } -function prefixIssues(path, issues) { +function prefixIssues(path2, issues) { return issues.map((iss) => { var _a3; (_a3 = iss).path ?? (_a3.path = []); - iss.path.unshift(path); + iss.path.unshift(path2); return iss; }); } @@ -89988,13 +152223,13 @@ function unwrapMessage(message2) { } function sizeCaps(defChecks) { const caps = []; - for (const ch of defChecks ?? []) { - const d = ch._zod.def; + for (const ch2 of defChecks ?? []) { + const d = ch2._zod.def; if (!/_(length|size)$|_equals$/.test(d.check)) break; const max2 = d.maximum ?? d.length ?? d.size; if (max2 >= 0) - caps.push([max2, ch]); + caps.push([max2, ch2]); } return caps; } @@ -90330,9 +152565,9 @@ function $constructor(name, initializer3, proto, params) { function _3(def) { const inst = params?.Parent ? newError(Definition) : this; init(inst, def); - const deferred = inst._zod.deferred; - if (deferred) { - for (const fn of deferred) { + const deferred2 = inst._zod.deferred; + if (deferred2) { + for (const fn of deferred2) { fn(); } inst._zod.deferred = void 0; @@ -90441,16 +152676,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) { } function formatError(error62, mapper = (issue2) => issue2.message) { const fieldErrors = { _errors: [] }; - const processError = (error63, path = []) => { + const processError = (error63, path2 = []) => { for (const issue2 of error63.issues) { if (issue2.code === "invalid_union" && issue2.errors.length) { - issue2.errors.map((issues) => processError({ issues }, [...path, ...issue2.path])); + issue2.errors.map((issues) => processError({ issues }, [...path2, ...issue2.path])); } else if (issue2.code === "invalid_key") { - processError({ issues: issue2.issues }, [...path, ...issue2.path]); + processError({ issues: issue2.issues }, [...path2, ...issue2.path]); } else if (issue2.code === "invalid_element") { - processError({ issues: issue2.issues }, [...path, ...issue2.path]); + processError({ issues: issue2.issues }, [...path2, ...issue2.path]); } else { - const fullpath = [...path, ...issue2.path]; + const fullpath = [...path2, ...issue2.path]; if (fullpath.length === 0) { fieldErrors._errors.push(mapper(issue2)); } else { @@ -90489,17 +152724,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) { } function treeifyError(error62, mapper = (issue2) => issue2.message) { const result2 = { errors: [] }; - const processError = (error63, path = []) => { + const processError = (error63, path2 = []) => { var _a3; for (const issue2 of error63.issues) { if (issue2.code === "invalid_union" && issue2.errors.length) { - issue2.errors.map((issues) => processError({ issues }, [...path, ...issue2.path])); + issue2.errors.map((issues) => processError({ issues }, [...path2, ...issue2.path])); } else if (issue2.code === "invalid_key") { - processError({ issues: issue2.issues }, [...path, ...issue2.path]); + processError({ issues: issue2.issues }, [...path2, ...issue2.path]); } else if (issue2.code === "invalid_element") { - processError({ issues: issue2.issues }, [...path, ...issue2.path]); + processError({ issues: issue2.issues }, [...path2, ...issue2.path]); } else { - const fullpath = [...path, ...issue2.path]; + const fullpath = [...path2, ...issue2.path]; if (fullpath.length === 0) { result2.errors.push(mapper(issue2)); continue; @@ -90538,8 +152773,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) { } function toDotPath(_path) { const segs = []; - const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg); - for (const seg of path) { + const path2 = _path.map((seg) => typeof seg === "object" ? seg.key : seg); + for (const seg of path2) { if (typeof seg === "number") segs.push(`[${seg}]`); else if (typeof seg === "symbol") @@ -91430,8 +153665,8 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => { inst._zod.version = version; const defChecks = inst._zod.def.checks; const checks = inst._zod.traits.has("$ZodCheck") ? [inst, ...defChecks ?? []] : defChecks?.length ? [...defChecks] : []; - for (const ch of checks) { - for (const fn of ch._zod.onattach) { + for (const ch2 of checks) { + for (const fn of ch2._zod.onattach) { fn(inst); } } @@ -91446,18 +153681,18 @@ var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => { return payload; let isAborted = aborted(payload); let asyncResult; - for (const ch of checks2) { - if (ch._zod.def.when) { + for (const ch2 of checks2) { + if (ch2._zod.def.when) { if (explicitlyAborted(payload)) continue; - const shouldRun = ch._zod.def.when(payload); + const shouldRun = ch2._zod.def.when(payload); if (!shouldRun) continue; } else if (isAborted) { continue; } const currLen = payload.issues.length; - const _3 = ch._zod.check(payload); + const _3 = ch2._zod.check(payload); if (_3 instanceof Promise && ctx?.async === false) { throw new $ZodAsyncError(); } @@ -92183,10 +154418,10 @@ function capSize(inst, size3) { inst._zod.parse = (payload, ctx) => { const n = size3(payload.value); if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") { - for (const [max2, ch] of sizeCaps(inst._zod.def.checks)) { - if (n > max2 && ch._zod.def.when(payload)) { + for (const [max2, ch2] of sizeCaps(inst._zod.def.checks)) { + if (n > max2 && ch2._zod.def.when(payload)) { const start = payload.issues.length; - ch._zod.check(payload); + ch2._zod.check(payload); payload.issues[start].continue = false; attachSchema(payload.issues, start, inst); return payload; @@ -93648,8 +155883,8 @@ function leafPattern(schema) { let isInt = !!def.format?.includes("int"); let minimum; let maximum; - for (const ch of def.checks ?? []) { - const d = ch._zod.def; + for (const ch2 of def.checks ?? []) { + const d = ch2._zod.def; if (d.pattern) pattern = d.pattern; isInt || (isInt = !!d.format?.includes("int")); @@ -103939,12 +166174,12 @@ function _size(size3, params) { } // @__NO_SIDE_EFFECTS__ function _maxLength(maximum, params) { - const ch = new $ZodCheckMaxLength({ + const ch2 = new $ZodCheckMaxLength({ check: "max_length", ...normalizeParams(params), maximum }); - return ch; + return ch2; } // @__NO_SIDE_EFFECTS__ function _minLength(minimum, params) { @@ -104032,10 +166267,10 @@ function _properties(shape, params) { }); } // @__NO_SIDE_EFFECTS__ -function _mime(types2, params) { +function _mime(types3, params) { return new $ZodCheckMimeType({ check: "mime_type", - mime: types2, + mime: types3, ...normalizeParams(params) }); } @@ -104295,10 +166530,10 @@ function _refine(Class2, fn, _params) { } // @__NO_SIDE_EFFECTS__ function _superRefine(fn, params) { - const ch = /* @__PURE__ */ _check((payload) => { + const ch2 = /* @__PURE__ */ _check((payload) => { payload.addIssue = (issue2) => { if (typeof issue2 === "string") { - payload.issues.push(issue(issue2, payload.value, ch._zod.def)); + payload.issues.push(issue(issue2, payload.value, ch2._zod.def)); } else { const _issue = issue2; if (_issue.fatal) @@ -104306,49 +166541,49 @@ function _superRefine(fn, params) { _issue.code ?? (_issue.code = "custom"); if (!("input" in _issue)) _issue.input = payload.value; - _issue.inst ?? (_issue.inst = ch); - _issue.continue ?? (_issue.continue = !ch._zod.def.abort); + _issue.inst ?? (_issue.inst = ch2); + _issue.continue ?? (_issue.continue = !ch2._zod.def.abort); payload.issues.push(issue(_issue)); } }; return fn(payload.value, payload); }, params); - return ch; + return ch2; } // @__NO_SIDE_EFFECTS__ function _check(fn, params) { - const ch = new $ZodCheck({ + const ch2 = new $ZodCheck({ check: "custom", ...normalizeParams(params) }); - ch._zod.check = fn; - return ch; + ch2._zod.check = fn; + return ch2; } // @__NO_SIDE_EFFECTS__ function describe(description) { - const ch = new $ZodCheck({ check: "describe" }); - ch._zod.onattach = [ + const ch2 = new $ZodCheck({ check: "describe" }); + ch2._zod.onattach = [ (inst) => { const existing = globalRegistry.get(inst) ?? {}; globalRegistry.add(inst, { ...existing, description }); } ]; - ch._zod.check = () => { + ch2._zod.check = () => { }; - return ch; + return ch2; } // @__NO_SIDE_EFFECTS__ function meta(metadata) { - const ch = new $ZodCheck({ check: "meta" }); - ch._zod.onattach = [ + const ch2 = new $ZodCheck({ check: "meta" }); + ch2._zod.onattach = [ (inst) => { const existing = globalRegistry.get(inst) ?? {}; globalRegistry.add(inst, { ...existing, ...metadata }); } ]; - ch._zod.check = () => { + ch2._zod.check = () => { }; - return ch; + return ch2; } // @__NO_SIDE_EFFECTS__ function _stringbool(Classes, _params) { @@ -104622,7 +166857,7 @@ function compactTypeUnion(schema) { const options = schema.anyOf; if (!Array.isArray(options) || options.length === 0 || schema.type !== void 0) return; - const types2 = []; + const types3 = []; for (const option of options) { if (!option || typeof option !== "object") return; @@ -104634,12 +166869,12 @@ function compactTypeUnion(schema) { for (const member of Array.isArray(type) ? type : [type]) { if (typeof member !== "string") return; - if (!types2.includes(member)) - types2.push(member); + if (!types3.includes(member)) + types3.push(member); } } delete schema.anyOf; - schema.type = types2.length === 1 ? types2[0] : types2; + schema.type = types3.length === 1 ? types3[0] : types3; } var FOLDABLE_KEYS = /* @__PURE__ */ new Set(["type", "properties", "required", "additionalProperties"]); var UNION_KEYS = ["oneOf", "anyOf"]; @@ -105016,8 +167251,8 @@ function aggregateChecks(schema) { const agg = {}; const def = schema._zod.def; const list = schema._zod.traits.has("$ZodCheck") ? [schema, ...def.checks ?? []] : def.checks ?? []; - for (const ch of list) - contributors[ch._zod.def.check]?.(agg, ch._zod.def); + for (const ch2 of list) + contributors[ch2._zod.def.check]?.(agg, ch2._zod.def); const bag = schema._zod.bag; if (bag.minimum !== void 0) narrowMin(agg, "minimum", bag.minimum); @@ -105438,8 +167673,8 @@ function stringifyKeyNames(bySchema, json3, visited) { if (mapped.some((branch, i) => branch !== branches[i])) json3 = { ...json3, [keyword]: mapped }; } - const types2 = Array.isArray(json3.type) ? json3.type : [json3.type]; - const numericType = !types2.includes("string") && types2.some((t) => t === "number" || t === "integer"); + const types3 = Array.isArray(json3.type) ? json3.type : [json3.type]; + const numericType = !types3.includes("string") && types3.some((t) => t === "number" || t === "integer"); const values3 = json3.enum ?? (json3.const !== void 0 ? [json3.const] : void 0); if (!numericType && !values3?.some((v) => typeof v === "number")) return json3; @@ -105452,7 +167687,7 @@ function stringifyKeyNames(bySchema, json3, visited) { return rest2; rest2.type = "string"; if (!values3) - rest2.pattern = (types2.includes("number") ? number : integer).source; + rest2.pattern = (types3.includes("number") ? number : integer).source; return rest2; } var pendingRecords = /* @__PURE__ */ new WeakMap(); @@ -106077,7 +168312,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => { return this.clone(util_exports.mergeDefs(def, { checks: [ ...def.checks ?? [], - ...chks.map((ch) => typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch) + ...chks.map((ch2) => typeof ch2 === "function" ? { _zod: { check: ch2, def: { check: "custom" }, onattach: [] } } : ch2) ] }), { parent: true }); }, @@ -107185,7 +169420,7 @@ var ZodFile = /* @__PURE__ */ $constructor("ZodFile", (inst, def) => { inst._zod.processJSONSchema = (ctx, json3, params) => fileProcessor(inst, ctx, json3, params); inst.min = (size3, params) => inst.check(_minSize(size3, params)); inst.max = (size3, params) => inst.check(_maxSize(size3, params)); - inst.mime = (types2, params) => inst.check(_mime(Array.isArray(types2) ? types2 : [types2], params)); + inst.mime = (types3, params) => inst.check(_mime(Array.isArray(types3) ? types3 : [types3], params)); }); function file(params) { return _file(ZodFile, params); @@ -107455,12 +169690,12 @@ var ZodCustom = /* @__PURE__ */ $constructor("ZodCustom", (inst, def) => { inst._zod.processJSONSchema = (ctx, json3, params) => customProcessor(inst, ctx, json3, params); }); function check(fn) { - const ch = new $ZodCheck({ + const ch2 = new $ZodCheck({ check: "custom" // ...util.normalizeParams(params), }); - ch._zod.check = fn; - return ch; + ch2._zod.check = fn; + return ch2; } function custom(fn, _params) { return _custom(ZodCustom, fn ?? (() => true), _params); @@ -107672,13 +169907,13 @@ function resolveRef(ref, ctx) { if (!ref.startsWith("#")) { throw new Error("External $ref is not supported, only local refs (#/...) are allowed"); } - const path = ref.slice(1).split("/").filter(Boolean); - if (path.length === 0) { + const path2 = ref.slice(1).split("/").filter(Boolean); + if (path2.length === 0) { return ctx.rootSchema; } const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions"; - if (path[0] === defsKey) { - const key = path[1] === void 0 ? void 0 : decodeJSONPointerSegment(path[1]); + if (path2[0] === defsKey) { + const key = path2[1] === void 0 ? void 0 : decodeJSONPointerSegment(path2[1]); if (!key || !ctx.defs[key]) { throw new Error(`Reference not found: ${ref}`); } @@ -109488,14 +171723,26 @@ function createTokenVerifierConfig(env3) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -109797,50 +172044,50 @@ var Builder = class extends NotTagged { this.first = first2; this.rest = rest2; } - build(before2, parameters, types2, options) { + build(before2, parameters, types3, options) { const keyword = builders.map(([x, fn]) => ({ fn, i: before2.search(x) })).sort((a, b2) => a.i - b2.i).pop(); - return keyword.i === -1 ? escapeIdentifiers(this.first, options) : keyword.fn(this.first, this.rest, parameters, types2, options); + return keyword.i === -1 ? escapeIdentifiers(this.first, options) : keyword.fn(this.first, this.rest, parameters, types3, options); } }; -function handleValue(x, parameters, types2, options) { +function handleValue(x, parameters, types3, options) { let value = x instanceof Parameter ? x.value : x; if (value === void 0) { x instanceof Parameter ? x.value = options.transform.undefined : value = x = options.transform.undefined; if (value === void 0) throw Errors.generic("UNDEFINED_VALUE", "Undefined values are not allowed"); } - return "$" + types2.push( + return "$" + types3.push( x instanceof Parameter ? (parameters.push(x.value), x.array ? x.array[x.type || inferType(x.value)] || x.type || firstIsString(x.value) : x.type) : (parameters.push(x), inferType(x)) ); } var defaultHandlers = typeHandlers(types); -function stringify(q, string4, value, parameters, types2, options) { +function stringify(q, string4, value, parameters, types3, options) { for (let i = 1; i < q.strings.length; i++) { - string4 += stringifyValue(string4, value, parameters, types2, options) + q.strings[i]; + string4 += stringifyValue(string4, value, parameters, types3, options) + q.strings[i]; value = q.args[i]; } return string4; } -function stringifyValue(string4, value, parameters, types2, o) { - return value instanceof Builder ? value.build(string4, parameters, types2, o) : value instanceof Query ? fragment(value, parameters, types2, o) : value instanceof Identifier ? value.value : value && value[0] instanceof Query ? value.reduce((acc, x) => acc + " " + fragment(x, parameters, types2, o), "") : handleValue(value, parameters, types2, o); +function stringifyValue(string4, value, parameters, types3, o) { + return value instanceof Builder ? value.build(string4, parameters, types3, o) : value instanceof Query ? fragment(value, parameters, types3, o) : value instanceof Identifier ? value.value : value && value[0] instanceof Query ? value.reduce((acc, x) => acc + " " + fragment(x, parameters, types3, o), "") : handleValue(value, parameters, types3, o); } -function fragment(q, parameters, types2, options) { +function fragment(q, parameters, types3, options) { q.fragment = true; - return stringify(q, q.strings[0], q.args[0], parameters, types2, options); + return stringify(q, q.strings[0], q.args[0], parameters, types3, options); } -function valuesBuilder(first2, parameters, types2, columns, options) { +function valuesBuilder(first2, parameters, types3, columns, options) { return first2.map( (row) => "(" + columns.map( - (column) => stringifyValue("values", row[column], parameters, types2, options) + (column) => stringifyValue("values", row[column], parameters, types3, options) ).join(",") + ")" ).join(","); } -function values(first2, rest2, parameters, types2, options) { +function values(first2, rest2, parameters, types3, options) { const multi = Array.isArray(first2[0]); const columns = rest2.length ? rest2.flat() : Object.keys(multi ? first2[0] : first2); - return valuesBuilder(multi ? first2 : [first2], parameters, types2, columns, options); + return valuesBuilder(multi ? first2 : [first2], parameters, types3, columns, options); } -function select(first2, rest2, parameters, types2, options) { +function select(first2, rest2, parameters, types3, options) { typeof first2 === "string" && (first2 = [first2].concat(rest2)); if (Array.isArray(first2)) return escapeIdentifiers(first2, options); @@ -109848,7 +172095,7 @@ function select(first2, rest2, parameters, types2, options) { const columns = rest2.length ? rest2.flat() : Object.keys(first2); return columns.map((x) => { value = first2[x]; - return (value instanceof Query ? fragment(value, parameters, types2, options) : value instanceof Identifier ? value.value : handleValue(value, parameters, types2, options)) + " as " + escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x); + return (value instanceof Query ? fragment(value, parameters, types3, options) : value instanceof Identifier ? value.value : handleValue(value, parameters, types3, options)) + " as " + escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x); }).join(","); } var builders = Object.entries({ @@ -109861,14 +172108,14 @@ var builders = Object.entries({ as: select, returning: select, "\\(": select, - update(first2, rest2, parameters, types2, options) { + update(first2, rest2, parameters, types3, options) { return (rest2.length ? rest2.flat() : Object.keys(first2)).map( - (x) => escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x) + "=" + stringifyValue("values", first2[x], parameters, types2, options) + (x) => escapeIdentifier(options.transform.column.to ? options.transform.column.to(x) : x) + "=" + stringifyValue("values", first2[x], parameters, types3, options) ); }, - insert(first2, rest2, parameters, types2, options) { + insert(first2, rest2, parameters, types3, options) { const columns = rest2.length ? rest2.flat() : Object.keys(Array.isArray(first2) ? first2[0] : first2); - return "(" + escapeIdentifiers(columns, options) + ")values" + valuesBuilder(Array.isArray(first2) ? first2 : [first2], parameters, types2, columns, options); + return "(" + escapeIdentifiers(columns, options) + ")values" + valuesBuilder(Array.isArray(first2) ? first2 : [first2], parameters, types3, columns, options); } }).map(([x, fn]) => [new RegExp("((?:^|[\\s(])" + x + "(?:$|[\\s(]))(?![\\s\\S]*\\1)", "i"), fn]); function notTagged() { @@ -109881,19 +172128,19 @@ function firstIsString(x) { return firstIsString(x[0]); return typeof x === "string" ? 1009 : 0; } -var mergeUserTypes = function(types2) { - const user = typeHandlers(types2 || {}); +var mergeUserTypes = function(types3) { + const user = typeHandlers(types3 || {}); return { serializers: Object.assign({}, serializers, user.serializers), parsers: Object.assign({}, parsers, user.parsers) }; }; -function typeHandlers(types2) { - return Object.keys(types2).reduce((acc, k) => { - types2[k].from && [].concat(types2[k].from).forEach((x) => acc.parsers[x] = types2[k].parse); - if (types2[k].serialize) { - acc.serializers[types2[k].to] = types2[k].serialize; - types2[k].from && [].concat(types2[k].from).forEach((x) => acc.serializers[x] = types2[k].serialize); +function typeHandlers(types3) { + return Object.keys(types3).reduce((acc, k) => { + types3[k].from && [].concat(types3[k].from).forEach((x) => acc.parsers[x] = types3[k].parse); + if (types3[k].serialize) { + acc.serializers[types3[k].to] = types3[k].serialize; + types3[k].from && [].concat(types3[k].from).forEach((x) => acc.serializers[x] = types3[k].serialize); } return acc; }, { parsers: {}, serializers: {} }); @@ -110281,8 +172528,8 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose } function prepared(q) { return Buffer.concat([ - Bind(q.parameters, q.statement.types, q.statement.name, q.cursorName), - q.cursorFn ? Execute("", q.cursorRows) : ExecuteUnnamed + Bind2(q.parameters, q.statement.types, q.statement.name, q.cursorName), + q.cursorFn ? Execute2("", q.cursorRows) : ExecuteUnnamed ]); } function unnamed(q) { @@ -110293,18 +172540,18 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose ]); } function build2(q) { - const parameters = [], types2 = []; - const string4 = stringify(q, q.strings[0], q.args[0], parameters, types2, options); - !q.tagged && q.args.forEach((x) => handleValue(x, parameters, types2, options)); + const parameters = [], types3 = []; + const string4 = stringify(q, q.strings[0], q.args[0], parameters, types3, options); + !q.tagged && q.args.forEach((x) => handleValue(x, parameters, types3, options)); q.prepare = options.prepare && ("prepare" in q.options ? q.options.prepare : true); q.string = string4; - q.signature = q.prepare && types2 + string4; + q.signature = q.prepare && types3 + string4; q.onlyDescribe && delete statements[q.signature]; q.parameters = q.parameters || parameters; q.prepared = q.prepare && q.signature in statements; q.describeFirst = q.onlyDescribe || parameters.length && !q.prepared; - q.statement = q.prepared ? statements[q.signature] : { string: string4, types: types2, name: q.prepare ? statementId + statementCount++ : "" }; - typeof options.debug === "function" && options.debug(id, string4, parameters, types2); + q.statement = q.prepared ? statements[q.signature] : { string: string4, types: types3, name: q.prepare ? statementId + statementCount++ : "" }; + typeof options.debug === "function" && options.debug(id, string4, parameters, types3); } function write(x, fn) { chunk2 = chunk2 ? Buffer.concat([chunk2, x]) : Buffer.from(x); @@ -110741,7 +172988,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose } async function fetchArrayTypes() { needsTypes = false; - const types2 = await new Query([` + const types3 = await new Query([` select b.oid, b.typarray from pg_catalog.pg_type a left join pg_catalog.pg_type b on b.oid = a.typelem @@ -110749,7 +172996,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose group by b.oid, b.typarray order by b.oid `], [], execute); - types2.forEach(({ oid, typarray }) => addArrayType(oid, typarray)); + types3.forEach(({ oid, typarray }) => addArrayType(oid, typarray)); } function addArrayType(oid, typarray) { if (!!options.parsers[typarray] && !!options.serializers[typarray]) return; @@ -110800,7 +173047,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose try { const x = await Promise.resolve(query.cursorFn(result2)); rows = 0; - x === CLOSE ? write(Close(query.portal)) : (result2 = new Result(), write(Execute("", query.cursorRows))); + x === CLOSE ? write(Close(query.portal)) : (result2 = new Result(), write(Execute2("", query.cursorRows))); } catch (err) { write(Sync); query.reject(err); @@ -110883,13 +173130,13 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose function UnknownAuth(x, type) { console.error("Postgres.js : Unknown Auth:", type); } - function Bind(parameters, types2, statement = "", portal = "") { + function Bind2(parameters, types3, statement = "", portal = "") { let prev, type; bytes_default().B().str(portal + bytes_default.N).str(statement + bytes_default.N).i16(0).i16(parameters.length); parameters.forEach((x, i) => { if (x === null) return bytes_default.i32(4294967295); - type = types2[i]; + type = types3[i]; parameters[i] = x = type in options.serializers ? options.serializers[type](x) : "" + x; prev = bytes_default.i; bytes_default.inc(4).str(x).i32(bytes_default.i - prev - 4, prev); @@ -110897,15 +173144,15 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose bytes_default.i16(0); return bytes_default.end(); } - function Parse(str, parameters, types2, name = "") { + function Parse(str, parameters, types3, name = "") { bytes_default().P().str(name + bytes_default.N).str(str + bytes_default.N).i16(parameters.length); - parameters.forEach((x, i) => bytes_default.i32(types2[i] || 0)); + parameters.forEach((x, i) => bytes_default.i32(types3[i] || 0)); return bytes_default.end(); } function Describe(x, name = "") { return bytes_default().D().str(x).str(name + bytes_default.N).end(); } - function Execute(portal = "", rows2 = 0) { + function Execute2(portal = "", rows2 = 0) { return Buffer.concat([ bytes_default().E().str(portal + bytes_default.N).i32(rows2).end(), Flush @@ -111066,13 +173313,13 @@ function Subscribe(postgres2, options) { } } function handle(a, b2) { - const path = b2.relation.schema + "." + b2.relation.table; + const path2 = b2.relation.schema + "." + b2.relation.table; call("*", a, b2); - call("*:" + path, a, b2); - b2.relation.keys.length && call("*:" + path + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2); + call("*:" + path2, a, b2); + b2.relation.keys.length && call("*:" + path2 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2); call(b2.command, a, b2); - call(b2.command + ":" + path, a, b2); - b2.relation.keys.length && call(b2.command + ":" + path + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2); + call(b2.command + ":" + path2, a, b2); + b2.relation.keys.length && call(b2.command + ":" + path2 + "=" + b2.relation.keys.map((x2) => a[x2.name]), a, b2); } function pong() { const x2 = Buffer.alloc(34); @@ -111185,8 +173432,8 @@ function parseEvent2(x) { const xs = x.match(/^(\*|insert|update|delete)?:?([^.]+?\.?[^=]+)?=?(.+)?/i) || []; if (!xs) throw new Error("Malformed subscribe pattern: " + x); - const [, command, path, key] = xs; - return (command || "*") + (path ? ":" + (path.indexOf(".") === -1 ? "public." + path : path) : "") + (key ? "=" + key : ""); + const [, command, path2, key] = xs; + return (command || "*") + (path2 ? ":" + (path2.indexOf(".") === -1 ? "public." + path2 : path2) : "") + (key ? "=" + key : ""); } // node_modules/.pnpm/postgres@3.4.9/node_modules/postgres/src/large.js @@ -111331,10 +173578,10 @@ function Postgres(a, b2) { }); return query; } - function file2(path, args = [], options2 = {}) { + function file2(path2, args = [], options2 = {}) { arguments.length === 2 && !Array.isArray(args) && (options2 = args, args = []); const query = new Query([], args, (query2) => { - fs.readFile(path, "utf8", (err, string4) => { + fs.readFile(path2, "utf8", (err, string4) => { if (err) return query2.reject(err); query2.strings = [string4]; @@ -112667,7 +174914,7 @@ var SQL = class _SQL { return { sql: escapeParam(paramStartIndex.value++, chunk2), params: [chunk2], typings: ["none"] }; })); } - mapInlineParam(chunk2, { escapeString }) { + mapInlineParam(chunk2, { escapeString: escapeString2 }) { if (chunk2 === null) { return "null"; } @@ -112675,14 +174922,14 @@ var SQL = class _SQL { return chunk2.toString(); } if (typeof chunk2 === "string") { - return escapeString(chunk2); + return escapeString2(chunk2); } if (typeof chunk2 === "object") { const mappedValueAsString = chunk2.toString(); if (mappedValueAsString === "[object Object]") { - return escapeString(JSON.stringify(chunk2)); + return escapeString2(JSON.stringify(chunk2)); } - return escapeString(mappedValueAsString); + return escapeString2(mappedValueAsString); } throw new Error("Unexpected param value: " + chunk2); } @@ -113043,7 +175290,7 @@ var SelectionProxyHandler = class _SelectionProxyHandler { function mapResultRow(columns, row, joinsNotNullableMap) { const nullifyMap = {}; const result2 = columns.reduce( - (result22, { path, field }, columnIndex) => { + (result22, { path: path2, field }, columnIndex) => { let decoder2; if (is(field, Column)) { decoder2 = field; @@ -113055,8 +175302,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) { decoder2 = field.sql.decoder; } let node2 = result22; - for (const [pathChunkIndex, pathChunk] of path.entries()) { - if (pathChunkIndex < path.length - 1) { + for (const [pathChunkIndex, pathChunk] of path2.entries()) { + if (pathChunkIndex < path2.length - 1) { if (!(pathChunk in node2)) { node2[pathChunk] = {}; } @@ -113064,8 +175311,8 @@ function mapResultRow(columns, row, joinsNotNullableMap) { } else { const rawValue = row[columnIndex]; const value = node2[pathChunk] = rawValue === null ? null : decoder2.mapFromDriverValue(rawValue); - if (joinsNotNullableMap && is(field, Column) && path.length === 2) { - const objectName = path[0]; + if (joinsNotNullableMap && is(field, Column) && path2.length === 2) { + const objectName = path2[0]; if (!(objectName in nullifyMap)) { nullifyMap[objectName] = value === null ? getTableName(field.table) : false; } else if (typeof nullifyMap[objectName] === "string" && nullifyMap[objectName] !== getTableName(field.table)) { @@ -120102,7 +182349,7 @@ function resolveKeyPath(root2, key) { function createLocalDriver(options) { const root2 = options.root; return { - async put(key, data, _options) { + async put(key, data, _options2) { const target = resolveKeyPath(root2, key); await mkdir(dirname(target), { recursive: true }); await writeFile(target, data); @@ -120178,8 +182425,8 @@ function createSupabaseDriver(options) { } return { async put(key, data, putOptions) { - const path = toObjectPath(key); - const response = await request(`${base}/${bucket}/${path}`, { + const path2 = toObjectPath(key); + const response = await request(`${base}/${bucket}/${path2}`, { method: "POST", headers: { ...authHeaders, @@ -120196,8 +182443,8 @@ function createSupabaseDriver(options) { return { key, byteSize: data.length }; }, async get(key) { - const path = toObjectPath(key); - const response = await request(`${base}/${bucket}/${path}`, { method: "GET", headers: authHeaders }); + const path2 = toObjectPath(key); + const response = await request(`${base}/${bucket}/${path2}`, { method: "GET", headers: authHeaders }); if (await isMissing(response)) { throw new AppError("NOT_FOUND", `No stored object for key "${key}"`); } @@ -120222,8 +182469,8 @@ function createSupabaseDriver(options) { } }, async exists(key) { - const path = toObjectPath(key); - const response = await request(`${base}/${bucket}/${path}`, { method: "HEAD", headers: authHeaders }); + const path2 = toObjectPath(key); + const response = await request(`${base}/${bucket}/${path2}`, { method: "HEAD", headers: authHeaders }); if (response.ok) return true; if (response.status === 404 || response.status === 400) return false; throw new AppError("UPSTREAM_UNAVAILABLE", "File storage could not check the file", { @@ -120321,18 +182568,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -120346,8 +182685,8 @@ function loadEnv(service, schema, source = process.env) { const result2 = schema.safeParse(source); if (!result2.success) { const issues = result2.error.issues.map((issue2) => { - const path = issue2.path.join(".") || "(root)"; - return `${path}: ${issue2.message}`; + const path2 = issue2.path.join(".") || "(root)"; + return `${path2}: ${issue2.message}`; }); throw new ConfigError(service, issues); } @@ -120356,8 +182695,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -120443,10 +182781,10 @@ function registerRateLimitedRoutes(app2, options, declareRoutes) { } // packages/observability/src/timestamps.ts -var PG_TIMESTAMP = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; +var PG_TIMESTAMP2 = /^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})(?:\.(\d{1,9}))?(Z|[+-]\d{2}(?::?\d{2})?)$/; var TIMESTAMP_KEY = /_at$/; function toIsoTimestamp(value) { - const match = PG_TIMESTAMP.exec(value); + const match = PG_TIMESTAMP2.exec(value); if (!match) return void 0; const [, date6, time4, fraction = "", zone = "Z"] = match; const millis = fraction.slice(0, 3).padEnd(3, "0"); @@ -120533,6 +182871,9 @@ async function insertPending(db2, input2) { if (!row) throw new Error("insertPending: insert returned no row"); return row; } +async function deleteById(db2, resumeId) { + await db2.delete(schema_exports.resumes).where(eq(schema_exports.resumes.resumeId, resumeId)); +} async function markParsed(db2, resumeId, result2) { const now = (/* @__PURE__ */ new Date()).toISOString(); await db2.update(schema_exports.resumes).set({ @@ -120549,9 +182890,9 @@ async function markFailed(db2, resumeId, reason) { await db2.update(schema_exports.resumes).set({ status: "failed", failureReason: reason, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(schema_exports.resumes.resumeId, resumeId)); } async function listForUser(db2, userId, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === "string" ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = [eq(schema_exports.resumes.userId, userId)]; if (cursorCreatedAt && cursorId) { const tieBreak = or( @@ -120880,7 +183221,7 @@ function analyzeResumeForJob(profile, rawText, target) { } // packages/ai/src/resume-parser.ts -var EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; +var EMAIL_RE = /[a-zA-Z0-9._%+-]{1,64}@[a-zA-Z0-9.-]{1,255}\.[a-zA-Z]{2,24}/; var PHONE_RE = /(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/; var URL_RE = /\bhttps?:\/\/[^\s,;)]+|(?:www\.)[^\s,;)]+/gi; var MONTHS = { @@ -121099,7 +183440,7 @@ function optimizeResumeRoute(app2, deps) { // services/profile/src/lib/extract-text.ts var import_mammoth = __toESM(require_lib7(), 1); -import { inflateRaw } from "node:zlib"; +import { inflateRaw, inflateSync } from "node:zlib"; import { promisify } from "node:util"; // node_modules/.pnpm/pdfjs-dist@5.4.296/node_modules/pdfjs-dist/legacy/build/pdf.mjs @@ -121166,8 +183507,8 @@ var __webpack_modules__ = { /***/ 34: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isCallable = __webpack_require__2(4901); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); module2.exports = function(it) { return typeof it == "object" ? it !== null : isCallable(it); }; @@ -121176,12 +183517,12 @@ var __webpack_modules__ = { /***/ 81: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var tryToString = __webpack_require__2(6823); - var getIteratorMethod = __webpack_require__2(851); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var tryToString = __webpack_require__3(6823); + var getIteratorMethod = __webpack_require__3(851); var $TypeError = TypeError; module2.exports = function(argument, usingIterator) { var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator; @@ -121193,18 +183534,18 @@ var __webpack_modules__ = { /***/ 116: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var iterate = __webpack_require__2(2652); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var findWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("find", TypeError); $({ target: "Iterator", proto: true, real: true, forced: findWithoutClosingOnEarlyError }, { - find: function find2(predicate) { + find: function find3(predicate) { anObject(this); try { aCallable(predicate); @@ -121224,15 +183565,15 @@ var __webpack_modules__ = { /***/ 283: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var fails = __webpack_require__2(9039); - var isCallable = __webpack_require__2(4901); - var hasOwn = __webpack_require__2(9297); - var DESCRIPTORS = __webpack_require__2(3724); - var CONFIGURABLE_FUNCTION_NAME = __webpack_require__2(350).CONFIGURABLE; - var inspectSource = __webpack_require__2(3706); - var InternalStateModule = __webpack_require__2(1181); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); + var hasOwn = __webpack_require__3(9297); + var DESCRIPTORS = __webpack_require__3(3724); + var CONFIGURABLE_FUNCTION_NAME = __webpack_require__3(350).CONFIGURABLE; + var inspectSource = __webpack_require__3(3706); + var InternalStateModule = __webpack_require__3(1181); var enforceInternalState = InternalStateModule.enforce; var getInternalState = InternalStateModule.get; var $String = String; @@ -121278,9 +183619,9 @@ var __webpack_modules__ = { /***/ 350: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var hasOwn = __webpack_require__2(9297); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var hasOwn = __webpack_require__3(9297); var FunctionPrototype = Function.prototype; var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor; var EXISTS = hasOwn(FunctionPrototype, "name"); @@ -121297,8 +183638,8 @@ var __webpack_modules__ = { /***/ 397: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var getBuiltIn = __webpack_require__2(7751); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); module2.exports = getBuiltIn("document", "documentElement"); } ), @@ -121312,13 +183653,13 @@ var __webpack_modules__ = { /***/ 456: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var uncurryThis = __webpack_require__2(9504); - var anUint8Array = __webpack_require__2(4154); - var notDetached = __webpack_require__2(5169); - var numberToString = uncurryThis(1.1.toString); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var numberToString2 = uncurryThis(1.1.toString); var Uint8Array2 = globalThis2.Uint8Array; var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !function() { try { @@ -121334,7 +183675,7 @@ var __webpack_modules__ = { notDetached(this.buffer); var result2 = ""; for (var i = 0, length = this.length; i < length; i++) { - var hex3 = numberToString(this[i], 16); + var hex3 = numberToString2(this[i], 16); result2 += hex3.length === 1 ? "0" + hex3 : hex3; } return result2; @@ -121345,8 +183686,8 @@ var __webpack_modules__ = { /***/ 507: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); module2.exports = function(record2, fn, ITERATOR_INSTEAD_OF_RECORD) { var iterator = ITERATOR_INSTEAD_OF_RECORD ? record2 : record2.iterator; var next = record2.next; @@ -121361,18 +183702,18 @@ var __webpack_modules__ = { /***/ 531: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var getIteratorFlattenable = __webpack_require__2(8646); - var createIteratorProxy = __webpack_require__2(9462); - var iteratorClose = __webpack_require__2(9539); - var IS_PURE = __webpack_require__2(6395); - var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var getIteratorFlattenable = __webpack_require__3(8646); + var createIteratorProxy = __webpack_require__3(9462); + var iteratorClose = __webpack_require__3(9539); + var IS_PURE = __webpack_require__3(6395); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("flatMap", function() { }); var flatMapWithoutClosingOnEarlyError = !IS_PURE && !FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("flatMap", TypeError); @@ -121418,8 +183759,8 @@ var __webpack_modules__ = { /***/ 616: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); module2.exports = !fails(function() { var test = function() { }.bind(); @@ -121430,8 +183771,8 @@ var __webpack_modules__ = { /***/ 655: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classof = __webpack_require__2(6955); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); var $String = String; module2.exports = function(argument) { if (classof(argument) === "Symbol") throw new TypeError("Cannot convert a Symbol value to a string"); @@ -121442,8 +183783,8 @@ var __webpack_modules__ = { /***/ 679: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isPrototypeOf = __webpack_require__2(1625); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isPrototypeOf = __webpack_require__3(1625); var $TypeError = TypeError; module2.exports = function(it, Prototype) { if (isPrototypeOf(Prototype, it)) return it; @@ -121480,11 +183821,11 @@ var __webpack_modules__ = { /***/ 757: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var getBuiltIn = __webpack_require__2(7751); - var isCallable = __webpack_require__2(4901); - var isPrototypeOf = __webpack_require__2(1625); - var USE_SYMBOL_AS_UID = __webpack_require__2(7040); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + var isCallable = __webpack_require__3(4901); + var isPrototypeOf = __webpack_require__3(1625); + var USE_SYMBOL_AS_UID = __webpack_require__3(7040); var $Object = Object; module2.exports = USE_SYMBOL_AS_UID ? function(it) { return typeof it == "symbol"; @@ -121497,12 +183838,12 @@ var __webpack_modules__ = { /***/ 851: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classof = __webpack_require__2(6955); - var getMethod = __webpack_require__2(5966); - var isNullOrUndefined = __webpack_require__2(4117); - var Iterators = __webpack_require__2(6269); - var wellKnownSymbol = __webpack_require__2(8227); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); + var getMethod = __webpack_require__3(5966); + var isNullOrUndefined = __webpack_require__3(4117); + var Iterators = __webpack_require__3(6269); + var wellKnownSymbol = __webpack_require__3(8227); var ITERATOR = wellKnownSymbol("iterator"); module2.exports = function(it) { if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR) || getMethod(it, "@@iterator") || Iterators[classof(it)]; @@ -121524,9 +183865,9 @@ var __webpack_modules__ = { /***/ 1072: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var internalObjectKeys = __webpack_require__2(1828); - var enumBugKeys = __webpack_require__2(8727); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var internalObjectKeys = __webpack_require__3(1828); + var enumBugKeys = __webpack_require__3(8727); module2.exports = Object.keys || function keys2(O) { return internalObjectKeys(O, enumBugKeys); }; @@ -121548,8 +183889,8 @@ var __webpack_modules__ = { /***/ 1108: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classof = __webpack_require__2(6955); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); module2.exports = function(it) { var klass = classof(it); return klass === "BigInt64Array" || klass === "BigUint64Array"; @@ -121559,15 +183900,15 @@ var __webpack_modules__ = { /***/ 1148: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var iterate = __webpack_require__2(2652); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var everyWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("every", TypeError); $({ target: "Iterator", proto: true, real: true, forced: everyWithoutClosingOnEarlyError }, { every: function every2(predicate) { @@ -121590,15 +183931,15 @@ var __webpack_modules__ = { /***/ 1181: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_WEAK_MAP = __webpack_require__2(8622); - var globalThis2 = __webpack_require__2(4576); - var isObject5 = __webpack_require__2(34); - var createNonEnumerableProperty = __webpack_require__2(6699); - var hasOwn = __webpack_require__2(9297); - var shared = __webpack_require__2(7629); - var sharedKey = __webpack_require__2(6119); - var hiddenKeys = __webpack_require__2(421); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_WEAK_MAP = __webpack_require__3(8622); + var globalThis2 = __webpack_require__3(4576); + var isObject5 = __webpack_require__3(34); + var createNonEnumerableProperty = __webpack_require__3(6699); + var hasOwn = __webpack_require__3(9297); + var shared = __webpack_require__3(7629); + var sharedKey = __webpack_require__3(6119); + var hiddenKeys = __webpack_require__3(421); var OBJECT_ALREADY_INITIALIZED = "Object already initialized"; var TypeError2 = globalThis2.TypeError; var WeakMap2 = globalThis2.WeakMap; @@ -121660,8 +184001,8 @@ var __webpack_modules__ = { /***/ 1291: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var trunc = __webpack_require__2(741); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var trunc = __webpack_require__3(741); module2.exports = function(argument) { var number4 = +argument; return number4 !== number4 || number4 === 0 ? 0 : trunc(number4); @@ -121671,8 +184012,8 @@ var __webpack_modules__ = { /***/ 1385: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var iteratorClose = __webpack_require__2(9539); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var iteratorClose = __webpack_require__3(9539); module2.exports = function(iters, kind, value) { for (var i = iters.length - 1; i >= 0; i--) { if (iters[i] === void 0) continue; @@ -121691,11 +184032,11 @@ var __webpack_modules__ = { /***/ 1548: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var fails = __webpack_require__2(9039); - var V8 = __webpack_require__2(9519); - var ENVIRONMENT = __webpack_require__2(4215); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var fails = __webpack_require__3(9039); + var V8 = __webpack_require__3(9519); + var ENVIRONMENT = __webpack_require__3(4215); var structuredClone2 = globalThis2.structuredClone; module2.exports = !!structuredClone2 && !fails(function() { if (ENVIRONMENT === "DENO" && V8 > 92 || ENVIRONMENT === "NODE" && V8 > 94 || ENVIRONMENT === "BROWSER" && V8 > 97) return false; @@ -121708,29 +184049,29 @@ var __webpack_modules__ = { /***/ 1549: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(6632); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(6632); } ), /***/ 1625: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); module2.exports = uncurryThis({}.isPrototypeOf); } ), /***/ 1689: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var apply = __webpack_require__2(8745); - var slice2 = __webpack_require__2(7680); - var newPromiseCapabilityModule = __webpack_require__2(6043); - var aCallable = __webpack_require__2(9306); - var perform = __webpack_require__2(1103); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var apply = __webpack_require__3(8745); + var slice2 = __webpack_require__3(7680); + var newPromiseCapabilityModule = __webpack_require__3(6043); + var aCallable = __webpack_require__3(9306); + var perform = __webpack_require__3(1103); var Promise2 = globalThis2.Promise; var ACCEPT_ARGUMENTS = false; var FORCED = !Promise2 || !Promise2["try"] || perform(function() { @@ -121754,11 +184095,11 @@ var __webpack_modules__ = { /***/ 1698: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var union3 = __webpack_require__2(4204); - var setMethodGetKeysBeforeCloning = __webpack_require__2(9835); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var union3 = __webpack_require__3(4204); + var setMethodGetKeysBeforeCloning = __webpack_require__3(9835); + var setMethodAcceptSetLike = __webpack_require__3(4916); var FORCED = !setMethodAcceptSetLike("union") || !setMethodGetKeysBeforeCloning("union"); $({ target: "Set", proto: true, real: true, forced: FORCED }, { union: union3 @@ -121768,18 +184109,18 @@ var __webpack_modules__ = { /***/ 1701: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var createIteratorProxy = __webpack_require__2(9462); - var callWithSafeIterationClosing = __webpack_require__2(6319); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); - var IS_PURE = __webpack_require__2(6395); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var createIteratorProxy = __webpack_require__3(9462); + var callWithSafeIterationClosing = __webpack_require__3(6319); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var IS_PURE = __webpack_require__3(6395); var MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("map", function() { }); var mapWithoutClosingOnEarlyError = !IS_PURE && !MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("map", TypeError); @@ -121822,12 +184163,12 @@ var __webpack_modules__ = { /***/ 1828: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var hasOwn = __webpack_require__2(9297); - var toIndexedObject = __webpack_require__2(5397); - var indexOf = __webpack_require__2(9617).indexOf; - var hiddenKeys = __webpack_require__2(421); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var hasOwn = __webpack_require__3(9297); + var toIndexedObject = __webpack_require__3(5397); + var indexOf = __webpack_require__3(9617).indexOf; + var hiddenKeys = __webpack_require__3(421); var push2 = uncurryThis([].push); module2.exports = function(object3, names) { var O = toIndexedObject(object3); @@ -121845,9 +184186,9 @@ var __webpack_modules__ = { /***/ 2106: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var makeBuiltIn = __webpack_require__2(283); - var defineProperty = __webpack_require__2(4913); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var makeBuiltIn = __webpack_require__3(283); + var defineProperty = __webpack_require__3(4913); module2.exports = function(target, name, descriptor) { if (descriptor.get) makeBuiltIn(descriptor.get, name, { getter: true }); if (descriptor.set) makeBuiltIn(descriptor.set, name, { setter: true }); @@ -121858,8 +184199,8 @@ var __webpack_modules__ = { /***/ 2140: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var wellKnownSymbol = __webpack_require__2(8227); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var wellKnownSymbol = __webpack_require__3(8227); var TO_STRING_TAG = wellKnownSymbol("toStringTag"); var test = {}; test[TO_STRING_TAG] = "z"; @@ -121869,8 +184210,8 @@ var __webpack_modules__ = { /***/ 2195: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); var toString2 = uncurryThis({}.toString); var stringSlice = uncurryThis("".slice); module2.exports = function(it) { @@ -121881,8 +184222,8 @@ var __webpack_modules__ = { /***/ 2211: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); module2.exports = !fails(function() { function F() { } @@ -121894,9 +184235,9 @@ var __webpack_modules__ = { /***/ 2303: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); var Uint8Array2 = globalThis2.Uint8Array; var SyntaxError2 = globalThis2.SyntaxError; var parseInt2 = globalThis2.parseInt; @@ -121923,14 +184264,14 @@ var __webpack_modules__ = { /***/ 2360: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var anObject = __webpack_require__2(8551); - var definePropertiesModule = __webpack_require__2(6801); - var enumBugKeys = __webpack_require__2(8727); - var hiddenKeys = __webpack_require__2(421); - var html = __webpack_require__2(397); - var documentCreateElement = __webpack_require__2(4055); - var sharedKey = __webpack_require__2(6119); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var anObject = __webpack_require__3(8551); + var definePropertiesModule = __webpack_require__3(6801); + var enumBugKeys = __webpack_require__3(8727); + var hiddenKeys = __webpack_require__3(421); + var html = __webpack_require__3(397); + var documentCreateElement = __webpack_require__3(4055); + var sharedKey = __webpack_require__3(6119); var GT = ">"; var LT = "<"; var PROTOTYPE = "prototype"; @@ -121988,10 +184329,10 @@ var __webpack_modules__ = { /***/ 2475: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var isSupersetOf = __webpack_require__2(8527); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isSupersetOf = __webpack_require__3(8527); + var setMethodAcceptSetLike = __webpack_require__3(4916); var INCORRECT = !setMethodAcceptSetLike("isSupersetOf", function(result2) { return !result2; }); @@ -122003,18 +184344,18 @@ var __webpack_modules__ = { /***/ 2489: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var createIteratorProxy = __webpack_require__2(9462); - var callWithSafeIterationClosing = __webpack_require__2(6319); - var IS_PURE = __webpack_require__2(6395); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var createIteratorProxy = __webpack_require__3(9462); + var callWithSafeIterationClosing = __webpack_require__3(6319); + var IS_PURE = __webpack_require__3(6395); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("filter", function() { }); var filterWithoutClosingOnEarlyError = !IS_PURE && !FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("filter", TypeError); @@ -122060,8 +184401,8 @@ var __webpack_modules__ = { /***/ 2603: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toString2 = __webpack_require__2(655); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toString2 = __webpack_require__3(655); module2.exports = function(argument, $default) { return argument === void 0 ? arguments.length < 2 ? "" : $default : toString2(argument); }; @@ -122070,17 +184411,17 @@ var __webpack_modules__ = { /***/ 2652: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var bind = __webpack_require__2(6080); - var call = __webpack_require__2(9565); - var anObject = __webpack_require__2(8551); - var tryToString = __webpack_require__2(6823); - var isArrayIteratorMethod = __webpack_require__2(4209); - var lengthOfArrayLike = __webpack_require__2(6198); - var isPrototypeOf = __webpack_require__2(1625); - var getIterator = __webpack_require__2(81); - var getIteratorMethod = __webpack_require__2(851); - var iteratorClose = __webpack_require__2(9539); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var bind = __webpack_require__3(6080); + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var tryToString = __webpack_require__3(6823); + var isArrayIteratorMethod = __webpack_require__3(4209); + var lengthOfArrayLike = __webpack_require__3(6198); + var isPrototypeOf = __webpack_require__3(1625); + var getIterator = __webpack_require__3(81); + var getIteratorMethod = __webpack_require__3(851); + var iteratorClose = __webpack_require__3(9539); var $TypeError = TypeError; var Result2 = function(stopped, result2) { this.stopped = stopped; @@ -122138,13 +184479,13 @@ var __webpack_modules__ = { /***/ 2777: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var isObject5 = __webpack_require__2(34); - var isSymbol = __webpack_require__2(757); - var getMethod = __webpack_require__2(5966); - var ordinaryToPrimitive = __webpack_require__2(4270); - var wellKnownSymbol = __webpack_require__2(8227); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var isObject5 = __webpack_require__3(34); + var isSymbol = __webpack_require__3(757); + var getMethod = __webpack_require__3(5966); + var ordinaryToPrimitive = __webpack_require__3(4270); + var wellKnownSymbol = __webpack_require__3(8227); var $TypeError = TypeError; var TO_PRIMITIVE = wellKnownSymbol("toPrimitive"); module2.exports = function(input2, pref) { @@ -122165,12 +184506,12 @@ var __webpack_modules__ = { /***/ 2787: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var hasOwn = __webpack_require__2(9297); - var isCallable = __webpack_require__2(4901); - var toObject = __webpack_require__2(8981); - var sharedKey = __webpack_require__2(6119); - var CORRECT_PROTOTYPE_GETTER = __webpack_require__2(2211); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var hasOwn = __webpack_require__3(9297); + var isCallable = __webpack_require__3(4901); + var toObject = __webpack_require__3(8981); + var sharedKey = __webpack_require__3(6119); + var CORRECT_PROTOTYPE_GETTER = __webpack_require__3(2211); var IE_PROTO = sharedKey("IE_PROTO"); var $Object = Object; var ObjectPrototype = $Object.prototype; @@ -122188,9 +184529,9 @@ var __webpack_modules__ = { /***/ 2796: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); - var isCallable = __webpack_require__2(4901); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); var replacement = /#|\.prototype\./; var isForced = function(feature, detection) { var value = data[normalize(feature)]; @@ -122240,8 +184581,8 @@ var __webpack_modules__ = { /***/ 2839: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); var navigator2 = globalThis2.navigator; var userAgent = navigator2 && navigator2.userAgent; module2.exports = userAgent ? String(userAgent) : ""; @@ -122250,11 +184591,11 @@ var __webpack_modules__ = { /***/ 2967: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThisAccessor = __webpack_require__2(6706); - var isObject5 = __webpack_require__2(34); - var requireObjectCoercible = __webpack_require__2(7750); - var aPossiblePrototype = __webpack_require__2(3506); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThisAccessor = __webpack_require__3(6706); + var isObject5 = __webpack_require__3(34); + var requireObjectCoercible = __webpack_require__3(7750); + var aPossiblePrototype = __webpack_require__3(3506); module2.exports = Object.setPrototypeOf || ("__proto__" in {} ? function() { var CORRECT_SETTER = false; var test = {}; @@ -122279,10 +184620,10 @@ var __webpack_modules__ = { /***/ 3068: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var uncurryThis = __webpack_require__2(9504); - var iterate = __webpack_require__2(2652); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var uncurryThis = __webpack_require__3(9504); + var iterate = __webpack_require__3(2652); var $RangeError = RangeError; var $TypeError = TypeError; var $Infinity = Infinity; @@ -122412,10 +184753,10 @@ var __webpack_modules__ = { /***/ 3167: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isCallable = __webpack_require__2(4901); - var isObject5 = __webpack_require__2(34); - var setPrototypeOf = __webpack_require__2(2967); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var setPrototypeOf = __webpack_require__3(2967); module2.exports = function($this, dummy, Wrapper) { var NewTarget, NewTargetPrototype; if ( @@ -122430,10 +184771,10 @@ var __webpack_modules__ = { /***/ 3238: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var NATIVE_ARRAY_BUFFER = __webpack_require__2(7811); - var arrayBufferByteLength = __webpack_require__2(7394); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var NATIVE_ARRAY_BUFFER = __webpack_require__3(7811); + var arrayBufferByteLength = __webpack_require__3(7394); var DataView2 = globalThis2.DataView; module2.exports = function(O) { if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false; @@ -122449,8 +184790,8 @@ var __webpack_modules__ = { /***/ 3392: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); var id = 0; var postfix = Math.random(); var toString2 = uncurryThis(1.1.toString); @@ -122462,14 +184803,14 @@ var __webpack_modules__ = { /***/ 3440: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var SetHelpers = __webpack_require__2(4402); - var clone3 = __webpack_require__2(9286); - var size3 = __webpack_require__2(5170); - var getSetRecord = __webpack_require__2(3789); - var iterateSet = __webpack_require__2(8469); - var iterateSimple = __webpack_require__2(507); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var clone3 = __webpack_require__3(9286); + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); var has3 = SetHelpers.has; var remove = SetHelpers.remove; module2.exports = function difference(other) { @@ -122500,8 +184841,8 @@ var __webpack_modules__ = { /***/ 3506: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isPossiblePrototype = __webpack_require__2(3925); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isPossiblePrototype = __webpack_require__3(3925); var $String = String; var $TypeError = TypeError; module2.exports = function(argument) { @@ -122513,15 +184854,15 @@ var __webpack_modules__ = { /***/ 3579: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var iterate = __webpack_require__2(2652); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var someWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("some", TypeError); $({ target: "Iterator", proto: true, real: true, forced: someWithoutClosingOnEarlyError }, { some: function some2(predicate) { @@ -122544,12 +184885,12 @@ var __webpack_modules__ = { /***/ 3650: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var SetHelpers = __webpack_require__2(4402); - var clone3 = __webpack_require__2(9286); - var getSetRecord = __webpack_require__2(3789); - var iterateSimple = __webpack_require__2(507); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var clone3 = __webpack_require__3(9286); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); var add = SetHelpers.add; var has3 = SetHelpers.has; var remove = SetHelpers.remove; @@ -122568,10 +184909,10 @@ var __webpack_modules__ = { /***/ 3706: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var isCallable = __webpack_require__2(4901); - var store = __webpack_require__2(7629); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var isCallable = __webpack_require__3(4901); + var store = __webpack_require__3(7629); var functionToString = uncurryThis(Function.toString); if (!isCallable(store.inspectSource)) { store.inspectSource = function(it) { @@ -122591,8 +184932,8 @@ var __webpack_modules__ = { /***/ 3724: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); module2.exports = !fails(function() { return Object.defineProperty({}, 1, { get: function() { return 7; @@ -122603,12 +184944,12 @@ var __webpack_modules__ = { /***/ 3789: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var call = __webpack_require__2(9565); - var toIntegerOrInfinity = __webpack_require__2(1291); - var getIteratorDirect = __webpack_require__2(1767); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var call = __webpack_require__3(9565); + var toIntegerOrInfinity = __webpack_require__3(1291); + var getIteratorDirect = __webpack_require__3(1767); var INVALID_SIZE = "Invalid size"; var $RangeError = RangeError; var $TypeError = TypeError; @@ -122640,11 +184981,11 @@ var __webpack_modules__ = { /***/ 3838: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var size3 = __webpack_require__2(5170); - var iterate = __webpack_require__2(8469); - var getSetRecord = __webpack_require__2(3789); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var size3 = __webpack_require__3(5170); + var iterate = __webpack_require__3(8469); + var getSetRecord = __webpack_require__3(3789); module2.exports = function isSubsetOf(other) { var O = aSet(this); var otherRec = getSetRecord(other); @@ -122658,10 +184999,10 @@ var __webpack_modules__ = { /***/ 3853: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var isDisjointFrom = __webpack_require__2(4449); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isDisjointFrom = __webpack_require__3(4449); + var setMethodAcceptSetLike = __webpack_require__3(4916); var INCORRECT = !setMethodAcceptSetLike("isDisjointFrom", function(result2) { return !result2; }); @@ -122673,8 +185014,8 @@ var __webpack_modules__ = { /***/ 3925: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isObject5 = __webpack_require__2(34); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); module2.exports = function(argument) { return isObject5(argument) || argument === null; }; @@ -122683,8 +185024,8 @@ var __webpack_modules__ = { /***/ 3972: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isObject5 = __webpack_require__2(34); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); var $String = String; var $TypeError = TypeError; module2.exports = function(argument) { @@ -122696,9 +185037,9 @@ var __webpack_modules__ = { /***/ 4055: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var isObject5 = __webpack_require__2(34); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isObject5 = __webpack_require__3(34); var document2 = globalThis2.document; var EXISTS = isObject5(document2) && isObject5(document2.createElement); module2.exports = function(it) { @@ -122709,13 +185050,13 @@ var __webpack_modules__ = { /***/ 4114: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var toObject = __webpack_require__2(8981); - var lengthOfArrayLike = __webpack_require__2(6198); - var setArrayLength = __webpack_require__2(4527); - var doesNotExceedSafeInteger = __webpack_require__2(6837); - var fails = __webpack_require__2(9039); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var toObject = __webpack_require__3(8981); + var lengthOfArrayLike = __webpack_require__3(6198); + var setArrayLength = __webpack_require__3(4527); + var doesNotExceedSafeInteger = __webpack_require__3(6837); + var fails = __webpack_require__3(9039); var INCORRECT_TO_LENGTH = fails(function() { return [].push.call({ length: 4294967296 }, 1) !== 4294967297; }); @@ -122767,8 +185108,8 @@ var __webpack_modules__ = { /***/ 4154: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classof = __webpack_require__2(6955); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(6955); var $TypeError = TypeError; module2.exports = function(argument) { if (classof(argument) === "Uint8Array") return argument; @@ -122779,12 +185120,12 @@ var __webpack_modules__ = { /***/ 4204: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var add = __webpack_require__2(4402).add; - var clone3 = __webpack_require__2(9286); - var getSetRecord = __webpack_require__2(3789); - var iterateSimple = __webpack_require__2(507); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var add = __webpack_require__3(4402).add; + var clone3 = __webpack_require__3(9286); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); module2.exports = function union3(other) { var O = aSet(this); var keysIter = getSetRecord(other).getIterator(); @@ -122799,9 +185140,9 @@ var __webpack_modules__ = { /***/ 4209: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var wellKnownSymbol = __webpack_require__2(8227); - var Iterators = __webpack_require__2(6269); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var wellKnownSymbol = __webpack_require__3(8227); + var Iterators = __webpack_require__3(6269); var ITERATOR = wellKnownSymbol("iterator"); var ArrayPrototype = Array.prototype; module2.exports = function(it) { @@ -122812,10 +185153,10 @@ var __webpack_modules__ = { /***/ 4215: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var userAgent = __webpack_require__2(2839); - var classof = __webpack_require__2(2195); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var userAgent = __webpack_require__3(2839); + var classof = __webpack_require__3(2195); var userAgentStartsWith = function(string4) { return userAgent.slice(0, string4.length) === string4; }; @@ -122835,13 +185176,13 @@ var __webpack_modules__ = { /***/ 4226: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var aString = __webpack_require__2(3463); - var anUint8Array = __webpack_require__2(4154); - var notDetached = __webpack_require__2(5169); - var $fromHex = __webpack_require__2(2303); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var aString = __webpack_require__3(3463); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var $fromHex = __webpack_require__3(2303); if (globalThis2.Uint8Array) $({ target: "Uint8Array", proto: true }, { setFromHex: function setFromHex(string4) { anUint8Array(this); @@ -122856,17 +185197,17 @@ var __webpack_modules__ = { /***/ 4235: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(3068); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(3068); } ), /***/ 4270: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var isCallable = __webpack_require__2(4901); - var isObject5 = __webpack_require__2(34); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); var $TypeError = TypeError; module2.exports = function(input2, pref) { var fn, val; @@ -122880,8 +185221,8 @@ var __webpack_modules__ = { /***/ 4376: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classof = __webpack_require__2(2195); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classof = __webpack_require__3(2195); module2.exports = Array.isArray || function isArray(argument) { return classof(argument) === "Array"; }; @@ -122890,8 +185231,8 @@ var __webpack_modules__ = { /***/ 4402: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); var SetPrototype = Set.prototype; module2.exports = { // eslint-disable-next-line es/no-set -- safe @@ -122906,14 +185247,14 @@ var __webpack_modules__ = { /***/ 4449: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var has3 = __webpack_require__2(4402).has; - var size3 = __webpack_require__2(5170); - var getSetRecord = __webpack_require__2(3789); - var iterateSet = __webpack_require__2(8469); - var iterateSimple = __webpack_require__2(507); - var iteratorClose = __webpack_require__2(9539); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var has3 = __webpack_require__3(4402).has; + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); + var iteratorClose = __webpack_require__3(9539); module2.exports = function isDisjointFrom(other) { var O = aSet(this); var otherRec = getSetRecord(other); @@ -122930,10 +185271,10 @@ var __webpack_modules__ = { /***/ 4483: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var getBuiltInNodeModule = __webpack_require__2(9429); - var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__2(1548); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var getBuiltInNodeModule = __webpack_require__3(9429); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__3(1548); var structuredClone2 = globalThis2.structuredClone; var $ArrayBuffer = globalThis2.ArrayBuffer; var $MessageChannel = globalThis2.MessageChannel; @@ -122967,10 +185308,10 @@ var __webpack_modules__ = { /***/ 4495: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var V8_VERSION = __webpack_require__2(9519); - var fails = __webpack_require__2(9039); - var globalThis2 = __webpack_require__2(4576); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var V8_VERSION = __webpack_require__3(9519); + var fails = __webpack_require__3(9039); + var globalThis2 = __webpack_require__3(4576); var $String = globalThis2.String; module2.exports = !!Object.getOwnPropertySymbols && !fails(function() { var symbol2 = Symbol("symbol detection"); @@ -122982,9 +185323,9 @@ var __webpack_modules__ = { /***/ 4527: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var isArray = __webpack_require__2(4376); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var isArray = __webpack_require__3(4376); var $TypeError = TypeError; var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !function() { @@ -123008,8 +185349,8 @@ var __webpack_modules__ = { /***/ 4549: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); module2.exports = function(METHOD_NAME, ExpectedError) { var Iterator2 = globalThis2.Iterator; var IteratorPrototype = Iterator2 && Iterator2.prototype; @@ -123049,11 +185390,11 @@ var __webpack_modules__ = { /***/ 4603: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var defineBuiltIn = __webpack_require__2(6840); - var uncurryThis = __webpack_require__2(9504); - var toString2 = __webpack_require__2(655); - var validateArgumentsLength = __webpack_require__2(2812); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); + var uncurryThis = __webpack_require__3(9504); + var toString2 = __webpack_require__3(655); + var validateArgumentsLength = __webpack_require__3(2812); var $URLSearchParams = URLSearchParams; var URLSearchParamsPrototype = $URLSearchParams.prototype; var append = uncurryThis(URLSearchParamsPrototype.append); @@ -123098,9 +185439,9 @@ var __webpack_modules__ = { /***/ 4628: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var newPromiseCapabilityModule = __webpack_require__2(6043); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var newPromiseCapabilityModule = __webpack_require__3(6043); $({ target: "Promise", stat: true }, { withResolvers: function withResolvers() { var promiseCapability = newPromiseCapabilityModule.f(this); @@ -123116,24 +185457,24 @@ var __webpack_modules__ = { /***/ 4644: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_ARRAY_BUFFER = __webpack_require__2(7811); - var DESCRIPTORS = __webpack_require__2(3724); - var globalThis2 = __webpack_require__2(4576); - var isCallable = __webpack_require__2(4901); - var isObject5 = __webpack_require__2(34); - var hasOwn = __webpack_require__2(9297); - var classof = __webpack_require__2(6955); - var tryToString = __webpack_require__2(6823); - var createNonEnumerableProperty = __webpack_require__2(6699); - var defineBuiltIn = __webpack_require__2(6840); - var defineBuiltInAccessor = __webpack_require__2(2106); - var isPrototypeOf = __webpack_require__2(1625); - var getPrototypeOf = __webpack_require__2(2787); - var setPrototypeOf = __webpack_require__2(2967); - var wellKnownSymbol = __webpack_require__2(8227); - var uid2 = __webpack_require__2(3392); - var InternalStateModule = __webpack_require__2(1181); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_ARRAY_BUFFER = __webpack_require__3(7811); + var DESCRIPTORS = __webpack_require__3(3724); + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var hasOwn = __webpack_require__3(9297); + var classof = __webpack_require__3(6955); + var tryToString = __webpack_require__3(6823); + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIn = __webpack_require__3(6840); + var defineBuiltInAccessor = __webpack_require__3(2106); + var isPrototypeOf = __webpack_require__3(1625); + var getPrototypeOf = __webpack_require__3(2787); + var setPrototypeOf = __webpack_require__3(2967); + var wellKnownSymbol = __webpack_require__3(8227); + var uid3 = __webpack_require__3(3392); + var InternalStateModule = __webpack_require__3(1181); var enforceInternalState = InternalStateModule.enforce; var getInternalState = InternalStateModule.get; var Int8Array2 = globalThis2.Int8Array; @@ -123145,7 +185486,7 @@ var __webpack_modules__ = { var ObjectPrototype = Object.prototype; var TypeError2 = globalThis2.TypeError; var TO_STRING_TAG = wellKnownSymbol("toStringTag"); - var TYPED_ARRAY_TAG = uid2("TYPED_ARRAY_TAG"); + var TYPED_ARRAY_TAG = uid3("TYPED_ARRAY_TAG"); var TYPED_ARRAY_CONSTRUCTOR = "TypedArrayConstructor"; var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(globalThis2.opera) !== "Opera"; var TYPED_ARRAY_TAG_REQUIRED = false; @@ -123289,10 +185630,10 @@ var __webpack_modules__ = { /***/ 4659: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var definePropertyModule = __webpack_require__2(4913); - var createPropertyDescriptor = __webpack_require__2(6980); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var definePropertyModule = __webpack_require__3(4913); + var createPropertyDescriptor = __webpack_require__3(6980); module2.exports = function(object3, key, value) { if (DESCRIPTORS) definePropertyModule.f(object3, key, createPropertyDescriptor(0, value)); else object3[key] = value; @@ -123314,44 +185655,44 @@ var __webpack_modules__ = { /***/ 4913: ( /***/ - (__unused_webpack_module, exports2, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var IE8_DOM_DEFINE = __webpack_require__2(5917); - var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__2(8686); - var anObject = __webpack_require__2(8551); - var toPropertyKey = __webpack_require__2(6969); + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var IE8_DOM_DEFINE = __webpack_require__3(5917); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__3(8686); + var anObject = __webpack_require__3(8551); + var toPropertyKey = __webpack_require__3(6969); var $TypeError = TypeError; var $defineProperty = Object.defineProperty; var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; var ENUMERABLE = "enumerable"; var CONFIGURABLE = "configurable"; var WRITABLE = "writable"; - exports2.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) { + exports2.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P2, Attributes2) { anObject(O); - P = toPropertyKey(P); - anObject(Attributes); - if (typeof O === "function" && P === "prototype" && "value" in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) { - var current = $getOwnPropertyDescriptor(O, P); + P2 = toPropertyKey(P2); + anObject(Attributes2); + if (typeof O === "function" && P2 === "prototype" && "value" in Attributes2 && WRITABLE in Attributes2 && !Attributes2[WRITABLE]) { + var current = $getOwnPropertyDescriptor(O, P2); if (current && current[WRITABLE]) { - O[P] = Attributes.value; - Attributes = { - configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE], - enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE], + O[P2] = Attributes2.value; + Attributes2 = { + configurable: CONFIGURABLE in Attributes2 ? Attributes2[CONFIGURABLE] : current[CONFIGURABLE], + enumerable: ENUMERABLE in Attributes2 ? Attributes2[ENUMERABLE] : current[ENUMERABLE], writable: false }; } } - return $defineProperty(O, P, Attributes); - } : $defineProperty : function defineProperty(O, P, Attributes) { + return $defineProperty(O, P2, Attributes2); + } : $defineProperty : function defineProperty(O, P2, Attributes2) { anObject(O); - P = toPropertyKey(P); - anObject(Attributes); + P2 = toPropertyKey(P2); + anObject(Attributes2); if (IE8_DOM_DEFINE) try { - return $defineProperty(O, P, Attributes); + return $defineProperty(O, P2, Attributes2); } catch (error62) { } - if ("get" in Attributes || "set" in Attributes) throw new $TypeError("Accessors not supported"); - if ("value" in Attributes) O[P] = Attributes.value; + if ("get" in Attributes2 || "set" in Attributes2) throw new $TypeError("Accessors not supported"); + if ("value" in Attributes2) O[P2] = Attributes2.value; return O; }; } @@ -123359,8 +185700,8 @@ var __webpack_modules__ = { /***/ 4916: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var getBuiltIn = __webpack_require__2(7751); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); var createSetLike = function(size3) { return { size: size3, @@ -123415,17 +185756,17 @@ var __webpack_modules__ = { /***/ 4972: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var notANaN = __webpack_require__2(4149); - var toPositiveInteger = __webpack_require__2(9590); - var createIteratorProxy = __webpack_require__2(9462); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); - var IS_PURE = __webpack_require__2(6395); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var notANaN = __webpack_require__3(4149); + var toPositiveInteger = __webpack_require__3(9590); + var createIteratorProxy = __webpack_require__3(9462); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var IS_PURE = __webpack_require__3(6395); var takeWithoutClosingOnEarlyError = !IS_PURE && iteratorHelperWithoutClosingOnEarlyError("take", RangeError); var IteratorProxy = createIteratorProxy(function() { var iterator = this.iterator; @@ -123457,20 +185798,20 @@ var __webpack_modules__ = { /***/ 4979: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var getBuiltIn = __webpack_require__2(7751); - var createPropertyDescriptor = __webpack_require__2(6980); - var defineProperty = __webpack_require__2(4913).f; - var hasOwn = __webpack_require__2(9297); - var anInstance = __webpack_require__2(679); - var inheritIfRequired = __webpack_require__2(3167); - var normalizeStringArgument = __webpack_require__2(2603); - var DOMExceptionConstants = __webpack_require__2(5002); - var clearErrorStack = __webpack_require__2(8574); - var DESCRIPTORS = __webpack_require__2(3724); - var IS_PURE = __webpack_require__2(6395); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var getBuiltIn = __webpack_require__3(7751); + var createPropertyDescriptor = __webpack_require__3(6980); + var defineProperty = __webpack_require__3(4913).f; + var hasOwn = __webpack_require__3(9297); + var anInstance = __webpack_require__3(679); + var inheritIfRequired = __webpack_require__3(3167); + var normalizeStringArgument = __webpack_require__3(2603); + var DOMExceptionConstants = __webpack_require__3(5002); + var clearErrorStack = __webpack_require__3(8574); + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); var DOM_EXCEPTION = "DOMException"; var Error2 = getBuiltIn("Error"); var NativeDOMException = getBuiltIn(DOM_EXCEPTION); @@ -123548,11 +185889,11 @@ var __webpack_modules__ = { /***/ 5024: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var symmetricDifference = __webpack_require__2(3650); - var setMethodGetKeysBeforeCloning = __webpack_require__2(9835); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var symmetricDifference = __webpack_require__3(3650); + var setMethodGetKeysBeforeCloning = __webpack_require__3(9835); + var setMethodAcceptSetLike = __webpack_require__3(4916); var FORCED = !setMethodAcceptSetLike("symmetricDifference") || !setMethodGetKeysBeforeCloning("symmetricDifference"); $({ target: "Set", proto: true, real: true, forced: FORCED }, { symmetricDifference @@ -123562,12 +185903,12 @@ var __webpack_modules__ = { /***/ 5031: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var getBuiltIn = __webpack_require__2(7751); - var uncurryThis = __webpack_require__2(9504); - var getOwnPropertyNamesModule = __webpack_require__2(8480); - var getOwnPropertySymbolsModule = __webpack_require__2(3717); - var anObject = __webpack_require__2(8551); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var getBuiltIn = __webpack_require__3(7751); + var uncurryThis = __webpack_require__3(9504); + var getOwnPropertyNamesModule = __webpack_require__3(8480); + var getOwnPropertySymbolsModule = __webpack_require__3(3717); + var anObject = __webpack_require__3(8551); var concat2 = uncurryThis([].concat); module2.exports = getBuiltIn("Reflect", "ownKeys") || function ownKeys(it) { var keys2 = getOwnPropertyNamesModule.f(anObject(it)); @@ -123579,8 +185920,8 @@ var __webpack_modules__ = { /***/ 5169: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isDetached = __webpack_require__2(3238); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isDetached = __webpack_require__3(3238); var $TypeError = TypeError; module2.exports = function(it) { if (isDetached(it)) throw new $TypeError("ArrayBuffer is detached"); @@ -123591,9 +185932,9 @@ var __webpack_modules__ = { /***/ 5170: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThisAccessor = __webpack_require__2(6706); - var SetHelpers = __webpack_require__2(4402); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThisAccessor = __webpack_require__3(6706); + var SetHelpers = __webpack_require__3(4402); module2.exports = uncurryThisAccessor(SetHelpers.proto, "size", "get") || function(set2) { return set2.size; }; @@ -123602,11 +185943,11 @@ var __webpack_modules__ = { /***/ 5213: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var arrayFromConstructorAndList = __webpack_require__2(5370); - var $fromBase64 = __webpack_require__2(9143); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var arrayFromConstructorAndList = __webpack_require__3(5370); + var $fromBase64 = __webpack_require__3(9143); var Uint8Array2 = globalThis2.Uint8Array; var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.fromBase64 || !function() { try { @@ -123631,8 +185972,8 @@ var __webpack_modules__ = { /***/ 5370: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var lengthOfArrayLike = __webpack_require__2(6198); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var lengthOfArrayLike = __webpack_require__3(6198); module2.exports = function(Constructor, list, $length) { var index2 = 0; var length = arguments.length > 2 ? $length : lengthOfArrayLike(list); @@ -123645,9 +185986,9 @@ var __webpack_modules__ = { /***/ 5397: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var IndexedObject = __webpack_require__2(7055); - var requireObjectCoercible = __webpack_require__2(7750); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var IndexedObject = __webpack_require__3(7055); + var requireObjectCoercible = __webpack_require__3(7750); module2.exports = function(it) { return IndexedObject(requireObjectCoercible(it)); }; @@ -123656,8 +185997,8 @@ var __webpack_modules__ = { /***/ 5610: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toIntegerOrInfinity = __webpack_require__2(1291); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); var max2 = Math.max; var min2 = Math.min; module2.exports = function(index2, length) { @@ -123669,22 +186010,22 @@ var __webpack_modules__ = { /***/ 5623: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(456); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(456); } ), /***/ 5636: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var uncurryThis = __webpack_require__2(9504); - var uncurryThisAccessor = __webpack_require__2(6706); - var toIndex = __webpack_require__2(7696); - var notDetached = __webpack_require__2(5169); - var arrayBufferByteLength = __webpack_require__2(7394); - var detachTransferable = __webpack_require__2(4483); - var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__2(1548); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var uncurryThisAccessor = __webpack_require__3(6706); + var toIndex = __webpack_require__3(7696); + var notDetached = __webpack_require__3(5169); + var arrayBufferByteLength = __webpack_require__3(7394); + var detachTransferable = __webpack_require__3(4483); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__3(1548); var structuredClone2 = globalThis2.structuredClone; var ArrayBuffer2 = globalThis2.ArrayBuffer; var DataView2 = globalThis2.DataView; @@ -123724,8 +186065,8 @@ var __webpack_modules__ = { /***/ 5745: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var store = __webpack_require__2(7629); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var store = __webpack_require__3(7629); module2.exports = function(key, value) { return store[key] || (store[key] = value || {}); }; @@ -123734,12 +186075,12 @@ var __webpack_modules__ = { /***/ 5781: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var getBuiltIn = __webpack_require__2(7751); - var validateArgumentsLength = __webpack_require__2(2812); - var toString2 = __webpack_require__2(655); - var USE_NATIVE_URL = __webpack_require__2(7416); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var getBuiltIn = __webpack_require__3(7751); + var validateArgumentsLength = __webpack_require__3(2812); + var toString2 = __webpack_require__3(655); + var USE_NATIVE_URL = __webpack_require__3(7416); var URL2 = getBuiltIn("URL"); $({ target: "URL", stat: true, forced: !USE_NATIVE_URL }, { parse: function parse4(url2) { @@ -123758,8 +186099,8 @@ var __webpack_modules__ = { /***/ 5854: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toPrimitive = __webpack_require__2(2777); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toPrimitive = __webpack_require__3(2777); var $TypeError = TypeError; module2.exports = function(argument) { var prim = toPrimitive(argument, "number"); @@ -123771,10 +186112,10 @@ var __webpack_modules__ = { /***/ 5876: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var isSubsetOf = __webpack_require__2(3838); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var isSubsetOf = __webpack_require__3(3838); + var setMethodAcceptSetLike = __webpack_require__3(4916); var INCORRECT = !setMethodAcceptSetLike("isSubsetOf", function(result2) { return result2; }); @@ -123786,10 +186127,10 @@ var __webpack_modules__ = { /***/ 5917: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var fails = __webpack_require__2(9039); - var createElement = __webpack_require__2(4055); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var fails = __webpack_require__3(9039); + var createElement = __webpack_require__3(4055); module2.exports = !DESCRIPTORS && !fails(function() { return Object.defineProperty(createElement("div"), "a", { get: function() { @@ -123802,11 +186143,11 @@ var __webpack_modules__ = { /***/ 5966: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aCallable = __webpack_require__2(9306); - var isNullOrUndefined = __webpack_require__2(4117); - module2.exports = function(V, P) { - var func = V[P]; + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); + var isNullOrUndefined = __webpack_require__3(4117); + module2.exports = function(V, P2) { + var func = V[P2]; return isNullOrUndefined(func) ? void 0 : aCallable(func); }; } @@ -123814,8 +186155,8 @@ var __webpack_modules__ = { /***/ 6043: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aCallable = __webpack_require__2(9306); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aCallable = __webpack_require__3(9306); var $TypeError = TypeError; var PromiseCapability = function(C) { var resolve2, reject2; @@ -123835,10 +186176,10 @@ var __webpack_modules__ = { /***/ 6080: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(7476); - var aCallable = __webpack_require__2(9306); - var NATIVE_BIND = __webpack_require__2(616); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(7476); + var aCallable = __webpack_require__3(9306); + var NATIVE_BIND = __webpack_require__3(616); var bind = uncurryThis(uncurryThis.bind); module2.exports = function(fn, that) { aCallable(fn); @@ -123851,28 +186192,28 @@ var __webpack_modules__ = { /***/ 6119: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var shared = __webpack_require__2(5745); - var uid2 = __webpack_require__2(3392); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var shared = __webpack_require__3(5745); + var uid3 = __webpack_require__3(3392); var keys2 = shared("keys"); module2.exports = function(key) { - return keys2[key] || (keys2[key] = uid2(key)); + return keys2[key] || (keys2[key] = uid3(key)); }; } ), /***/ 6193: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var ENVIRONMENT = __webpack_require__2(4215); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var ENVIRONMENT = __webpack_require__3(4215); module2.exports = ENVIRONMENT === "NODE"; } ), /***/ 6198: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toLength = __webpack_require__2(8014); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toLength = __webpack_require__3(8014); module2.exports = function(obj2) { return toLength(obj2.length); }; @@ -123888,8 +186229,8 @@ var __webpack_modules__ = { /***/ 6279: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var defineBuiltIn = __webpack_require__2(6840); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); module2.exports = function(target, src, options) { for (var key in src) defineBuiltIn(target, key, src[key], options); return target; @@ -123899,9 +186240,9 @@ var __webpack_modules__ = { /***/ 6319: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var anObject = __webpack_require__2(8551); - var iteratorClose = __webpack_require__2(9539); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var anObject = __webpack_require__3(8551); + var iteratorClose = __webpack_require__3(9539); module2.exports = function(iterator, fn, value, ENTRIES) { try { return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); @@ -123921,14 +186262,14 @@ var __webpack_modules__ = { /***/ 6518: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var getOwnPropertyDescriptor = __webpack_require__2(7347).f; - var createNonEnumerableProperty = __webpack_require__2(6699); - var defineBuiltIn = __webpack_require__2(6840); - var defineGlobalProperty = __webpack_require__2(9433); - var copyConstructorProperties = __webpack_require__2(7740); - var isForced = __webpack_require__2(2796); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var getOwnPropertyDescriptor = __webpack_require__3(7347).f; + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIn = __webpack_require__3(6840); + var defineGlobalProperty = __webpack_require__3(9433); + var copyConstructorProperties = __webpack_require__3(7740); + var isForced = __webpack_require__3(2796); module2.exports = function(options, source) { var TARGET = options.target; var GLOBAL = options.global; @@ -123963,10 +186304,10 @@ var __webpack_modules__ = { /***/ 6573: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var defineBuiltInAccessor = __webpack_require__2(2106); - var isDetached = __webpack_require__2(3238); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var defineBuiltInAccessor = __webpack_require__3(2106); + var isDetached = __webpack_require__3(3238); var ArrayBufferPrototype = ArrayBuffer.prototype; if (DESCRIPTORS && !("detached" in ArrayBufferPrototype)) { defineBuiltInAccessor(ArrayBufferPrototype, "detached", { @@ -123981,11 +186322,11 @@ var __webpack_modules__ = { /***/ 6632: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var $fromBase64 = __webpack_require__2(9143); - var anUint8Array = __webpack_require__2(4154); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var $fromBase64 = __webpack_require__3(9143); + var anUint8Array = __webpack_require__3(4154); var Uint8Array2 = globalThis2.Uint8Array; var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.setFromBase64 || !function() { var target = new Uint8Array2([255, 255, 255, 255, 255]); @@ -124017,10 +186358,10 @@ var __webpack_modules__ = { /***/ 6699: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var definePropertyModule = __webpack_require__2(4913); - var createPropertyDescriptor = __webpack_require__2(6980); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var definePropertyModule = __webpack_require__3(4913); + var createPropertyDescriptor = __webpack_require__3(6980); module2.exports = DESCRIPTORS ? function(object3, key, value) { return definePropertyModule.f(object3, key, createPropertyDescriptor(1, value)); } : function(object3, key, value) { @@ -124032,9 +186373,9 @@ var __webpack_modules__ = { /***/ 6706: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var aCallable = __webpack_require__2(9306); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var aCallable = __webpack_require__3(9306); module2.exports = function(object3, key, method) { try { return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object3, key)[method])); @@ -124046,13 +186387,13 @@ var __webpack_modules__ = { /***/ 6801: ( /***/ - (__unused_webpack_module, exports2, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__2(8686); - var definePropertyModule = __webpack_require__2(4913); - var anObject = __webpack_require__2(8551); - var toIndexedObject = __webpack_require__2(5397); - var objectKeys = __webpack_require__2(1072); + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__3(8686); + var definePropertyModule = __webpack_require__3(4913); + var anObject = __webpack_require__3(8551); + var toIndexedObject = __webpack_require__3(5397); + var objectKeys = __webpack_require__3(1072); exports2.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) { anObject(O); var props = toIndexedObject(Properties); @@ -124094,11 +186435,11 @@ var __webpack_modules__ = { /***/ 6840: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isCallable = __webpack_require__2(4901); - var definePropertyModule = __webpack_require__2(4913); - var makeBuiltIn = __webpack_require__2(283); - var defineGlobalProperty = __webpack_require__2(9433); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var definePropertyModule = __webpack_require__3(4913); + var makeBuiltIn = __webpack_require__3(283); + var defineGlobalProperty = __webpack_require__3(9433); module2.exports = function(O, key, value, options) { if (!options) options = {}; var simple = options.enumerable; @@ -124128,11 +186469,11 @@ var __webpack_modules__ = { /***/ 6955: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var TO_STRING_TAG_SUPPORT = __webpack_require__2(2140); - var isCallable = __webpack_require__2(4901); - var classofRaw = __webpack_require__2(2195); - var wellKnownSymbol = __webpack_require__2(8227); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var TO_STRING_TAG_SUPPORT = __webpack_require__3(2140); + var isCallable = __webpack_require__3(4901); + var classofRaw = __webpack_require__3(2195); + var wellKnownSymbol = __webpack_require__3(8227); var TO_STRING_TAG = wellKnownSymbol("toStringTag"); var $Object = Object; var CORRECT_ARGUMENTS = classofRaw(/* @__PURE__ */ function() { @@ -124153,9 +186494,9 @@ var __webpack_modules__ = { /***/ 6969: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toPrimitive = __webpack_require__2(2777); - var isSymbol = __webpack_require__2(757); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toPrimitive = __webpack_require__3(2777); + var isSymbol = __webpack_require__3(757); module2.exports = function(argument) { var key = toPrimitive(argument, "string"); return isSymbol(key) ? key : key + ""; @@ -124179,18 +186520,18 @@ var __webpack_modules__ = { /***/ 7040: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_SYMBOL = __webpack_require__2(4495); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_SYMBOL = __webpack_require__3(4495); module2.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == "symbol"; } ), /***/ 7055: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var fails = __webpack_require__2(9039); - var classof = __webpack_require__2(2195); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var fails = __webpack_require__3(9039); + var classof = __webpack_require__3(2195); var $Object = Object; var split = uncurryThis("".split); module2.exports = fails(function() { @@ -124203,8 +186544,8 @@ var __webpack_modules__ = { /***/ 7080: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var has3 = __webpack_require__2(4402).has; + (module2, __unused_webpack_exports, __webpack_require__3) => { + var has3 = __webpack_require__3(4402).has; module2.exports = function(it) { has3(it); return it; @@ -124214,34 +186555,34 @@ var __webpack_modules__ = { /***/ 7347: ( /***/ - (__unused_webpack_module, exports2, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var call = __webpack_require__2(9565); - var propertyIsEnumerableModule = __webpack_require__2(8773); - var createPropertyDescriptor = __webpack_require__2(6980); - var toIndexedObject = __webpack_require__2(5397); - var toPropertyKey = __webpack_require__2(6969); - var hasOwn = __webpack_require__2(9297); - var IE8_DOM_DEFINE = __webpack_require__2(5917); + (__unused_webpack_module, exports2, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var call = __webpack_require__3(9565); + var propertyIsEnumerableModule = __webpack_require__3(8773); + var createPropertyDescriptor = __webpack_require__3(6980); + var toIndexedObject = __webpack_require__3(5397); + var toPropertyKey = __webpack_require__3(6969); + var hasOwn = __webpack_require__3(9297); + var IE8_DOM_DEFINE = __webpack_require__3(5917); var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; - exports2.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + exports2.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P2) { O = toIndexedObject(O); - P = toPropertyKey(P); + P2 = toPropertyKey(P2); if (IE8_DOM_DEFINE) try { - return $getOwnPropertyDescriptor(O, P); + return $getOwnPropertyDescriptor(O, P2); } catch (error62) { } - if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]); + if (hasOwn(O, P2)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P2), O[P2]); }; } ), /***/ 7394: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var uncurryThisAccessor = __webpack_require__2(6706); - var classof = __webpack_require__2(2195); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThisAccessor = __webpack_require__3(6706); + var classof = __webpack_require__3(2195); var ArrayBuffer2 = globalThis2.ArrayBuffer; var TypeError2 = globalThis2.TypeError; module2.exports = ArrayBuffer2 && uncurryThisAccessor(ArrayBuffer2.prototype, "byteLength", "get") || function(O) { @@ -124253,11 +186594,11 @@ var __webpack_modules__ = { /***/ 7416: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); - var wellKnownSymbol = __webpack_require__2(8227); - var DESCRIPTORS = __webpack_require__2(3724); - var IS_PURE = __webpack_require__2(6395); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var wellKnownSymbol = __webpack_require__3(8227); + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); var ITERATOR = wellKnownSymbol("iterator"); module2.exports = !fails(function() { var url2 = new URL("b?a=1&b=2&c=3", "https://a"); @@ -124278,9 +186619,9 @@ var __webpack_modules__ = { /***/ 7476: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var classofRaw = __webpack_require__2(2195); - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var classofRaw = __webpack_require__3(2195); + var uncurryThis = __webpack_require__3(9504); module2.exports = function(fn) { if (classofRaw(fn) === "Function") return uncurryThis(fn); }; @@ -124289,11 +186630,11 @@ var __webpack_modules__ = { /***/ 7566: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var defineBuiltIn = __webpack_require__2(6840); - var uncurryThis = __webpack_require__2(9504); - var toString2 = __webpack_require__2(655); - var validateArgumentsLength = __webpack_require__2(2812); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var defineBuiltIn = __webpack_require__3(6840); + var uncurryThis = __webpack_require__3(9504); + var toString2 = __webpack_require__3(655); + var validateArgumentsLength = __webpack_require__3(2812); var $URLSearchParams = URLSearchParams; var URLSearchParamsPrototype = $URLSearchParams.prototype; var getAll = uncurryThis(URLSearchParamsPrototype.getAll); @@ -124319,15 +186660,15 @@ var __webpack_modules__ = { /***/ 7588: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var iterate = __webpack_require__2(2652); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); var forEachWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("forEach", TypeError); $({ target: "Iterator", proto: true, real: true, forced: forEachWithoutClosingOnEarlyError }, { forEach: function forEach(fn) { @@ -124350,10 +186691,10 @@ var __webpack_modules__ = { /***/ 7629: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var IS_PURE = __webpack_require__2(6395); - var globalThis2 = __webpack_require__2(4576); - var defineGlobalProperty = __webpack_require__2(9433); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var IS_PURE = __webpack_require__3(6395); + var globalThis2 = __webpack_require__3(4576); + var defineGlobalProperty = __webpack_require__3(9433); var SHARED = "__core-js_shared__"; var store = module2.exports = globalThis2[SHARED] || defineGlobalProperty(SHARED, {}); (store.versions || (store.versions = [])).push({ @@ -124368,11 +186709,11 @@ var __webpack_modules__ = { /***/ 7642: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var difference = __webpack_require__2(3440); - var fails = __webpack_require__2(9039); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var difference = __webpack_require__3(3440); + var fails = __webpack_require__3(9039); + var setMethodAcceptSetLike = __webpack_require__3(4916); var SET_LIKE_INCORRECT_BEHAVIOR = !setMethodAcceptSetLike("difference", function(result2) { return result2.size === 0; }); @@ -124404,15 +186745,15 @@ var __webpack_modules__ = { /***/ 7657: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var fails = __webpack_require__2(9039); - var isCallable = __webpack_require__2(4901); - var isObject5 = __webpack_require__2(34); - var create2 = __webpack_require__2(2360); - var getPrototypeOf = __webpack_require__2(2787); - var defineBuiltIn = __webpack_require__2(6840); - var wellKnownSymbol = __webpack_require__2(8227); - var IS_PURE = __webpack_require__2(6395); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var fails = __webpack_require__3(9039); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var create2 = __webpack_require__3(2360); + var getPrototypeOf = __webpack_require__3(2787); + var defineBuiltIn = __webpack_require__3(6840); + var wellKnownSymbol = __webpack_require__3(8227); + var IS_PURE = __webpack_require__3(6395); var ITERATOR = wellKnownSymbol("iterator"); var BUGGY_SAFARI_ITERATORS = false; var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator; @@ -124444,17 +186785,17 @@ var __webpack_modules__ = { /***/ 7680: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); module2.exports = uncurryThis([].slice); } ), /***/ 7696: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toIntegerOrInfinity = __webpack_require__2(1291); - var toLength = __webpack_require__2(8014); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); + var toLength = __webpack_require__3(8014); var $RangeError = RangeError; module2.exports = function(it) { if (it === void 0) return 0; @@ -124468,11 +186809,11 @@ var __webpack_modules__ = { /***/ 7740: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var hasOwn = __webpack_require__2(9297); - var ownKeys = __webpack_require__2(5031); - var getOwnPropertyDescriptorModule = __webpack_require__2(7347); - var definePropertyModule = __webpack_require__2(4913); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var hasOwn = __webpack_require__3(9297); + var ownKeys = __webpack_require__3(5031); + var getOwnPropertyDescriptorModule = __webpack_require__3(7347); + var definePropertyModule = __webpack_require__3(4913); module2.exports = function(target, source, exceptions) { var keys2 = ownKeys(source); var defineProperty = definePropertyModule.f; @@ -124489,8 +186830,8 @@ var __webpack_modules__ = { /***/ 7750: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isNullOrUndefined = __webpack_require__2(4117); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isNullOrUndefined = __webpack_require__3(4117); var $TypeError = TypeError; module2.exports = function(it) { if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it); @@ -124501,9 +186842,9 @@ var __webpack_modules__ = { /***/ 7751: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var isCallable = __webpack_require__2(4901); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); var aFunction = function(argument) { return isCallable(argument) ? argument : void 0; }; @@ -124522,9 +186863,9 @@ var __webpack_modules__ = { /***/ 7936: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var $transfer = __webpack_require__2(5636); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var $transfer = __webpack_require__3(5636); if ($transfer) $({ target: "ArrayBuffer", proto: true }, { transferToFixedLength: function transferToFixedLength() { return $transfer(this, arguments.length ? arguments[0] : void 0, false); @@ -124535,11 +186876,11 @@ var __webpack_modules__ = { /***/ 8004: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var fails = __webpack_require__2(9039); - var intersection3 = __webpack_require__2(8750); - var setMethodAcceptSetLike = __webpack_require__2(4916); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var fails = __webpack_require__3(9039); + var intersection3 = __webpack_require__3(8750); + var setMethodAcceptSetLike = __webpack_require__3(4916); var INCORRECT = !setMethodAcceptSetLike("intersection", function(result2) { return result2.size === 2 && result2.has(1) && result2.has(2); }) || fails(function() { @@ -124553,8 +186894,8 @@ var __webpack_modules__ = { /***/ 8014: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toIntegerOrInfinity = __webpack_require__2(1291); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); var min2 = Math.min; module2.exports = function(argument) { var len = toIntegerOrInfinity(argument); @@ -124565,9 +186906,9 @@ var __webpack_modules__ = { /***/ 8100: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var $transfer = __webpack_require__2(5636); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var $transfer = __webpack_require__3(5636); if ($transfer) $({ target: "ArrayBuffer", proto: true }, { transfer: function transfer() { return $transfer(this, arguments.length ? arguments[0] : void 0, true); @@ -124578,21 +186919,21 @@ var __webpack_modules__ = { /***/ 8111: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var anInstance = __webpack_require__2(679); - var anObject = __webpack_require__2(8551); - var isCallable = __webpack_require__2(4901); - var getPrototypeOf = __webpack_require__2(2787); - var defineBuiltInAccessor = __webpack_require__2(2106); - var createProperty = __webpack_require__2(4659); - var fails = __webpack_require__2(9039); - var hasOwn = __webpack_require__2(9297); - var wellKnownSymbol = __webpack_require__2(8227); - var IteratorPrototype = __webpack_require__2(7657).IteratorPrototype; - var DESCRIPTORS = __webpack_require__2(3724); - var IS_PURE = __webpack_require__2(6395); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var anInstance = __webpack_require__3(679); + var anObject = __webpack_require__3(8551); + var isCallable = __webpack_require__3(4901); + var getPrototypeOf = __webpack_require__3(2787); + var defineBuiltInAccessor = __webpack_require__3(2106); + var createProperty = __webpack_require__3(4659); + var fails = __webpack_require__3(9039); + var hasOwn = __webpack_require__3(9297); + var wellKnownSymbol = __webpack_require__3(8227); + var IteratorPrototype = __webpack_require__3(7657).IteratorPrototype; + var DESCRIPTORS = __webpack_require__3(3724); + var IS_PURE = __webpack_require__3(6395); var CONSTRUCTOR = "constructor"; var ITERATOR = "Iterator"; var TO_STRING_TAG = wellKnownSymbol("toStringTag"); @@ -124634,16 +186975,16 @@ var __webpack_modules__ = { /***/ 8227: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var shared = __webpack_require__2(5745); - var hasOwn = __webpack_require__2(9297); - var uid2 = __webpack_require__2(3392); - var NATIVE_SYMBOL = __webpack_require__2(4495); - var USE_SYMBOL_AS_UID = __webpack_require__2(7040); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var shared = __webpack_require__3(5745); + var hasOwn = __webpack_require__3(9297); + var uid3 = __webpack_require__3(3392); + var NATIVE_SYMBOL = __webpack_require__3(4495); + var USE_SYMBOL_AS_UID = __webpack_require__3(7040); var Symbol2 = globalThis2.Symbol; var WellKnownSymbolsStore = shared("wks"); - var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid2; + var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid3; module2.exports = function(name) { if (!hasOwn(WellKnownSymbolsStore, name)) { WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol2, name) ? Symbol2[name] : createWellKnownSymbol("Symbol." + name); @@ -124655,9 +186996,9 @@ var __webpack_modules__ = { /***/ 8235: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var hasOwn = __webpack_require__2(9297); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var hasOwn = __webpack_require__3(9297); var $SyntaxError = SyntaxError; var $parseInt = parseInt; var fromCharCode = String.fromCharCode; @@ -124711,16 +187052,16 @@ var __webpack_modules__ = { /***/ 8237: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var iterate = __webpack_require__2(2652); - var aCallable = __webpack_require__2(9306); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var iteratorClose = __webpack_require__2(9539); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); - var apply = __webpack_require__2(8745); - var fails = __webpack_require__2(9039); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var iterate = __webpack_require__3(2652); + var aCallable = __webpack_require__3(9306); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var iteratorClose = __webpack_require__3(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var apply = __webpack_require__3(8745); + var fails = __webpack_require__3(9039); var $TypeError = TypeError; var FAILS_ON_INITIAL_UNDEFINED = fails(function() { [].keys().reduce(function() { @@ -124760,23 +187101,23 @@ var __webpack_modules__ = { /***/ 8335: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var DESCRIPTORS = __webpack_require__2(3724); - var globalThis2 = __webpack_require__2(4576); - var getBuiltIn = __webpack_require__2(7751); - var uncurryThis = __webpack_require__2(9504); - var call = __webpack_require__2(9565); - var isCallable = __webpack_require__2(4901); - var isObject5 = __webpack_require__2(34); - var isArray = __webpack_require__2(4376); - var hasOwn = __webpack_require__2(9297); - var toString2 = __webpack_require__2(655); - var lengthOfArrayLike = __webpack_require__2(6198); - var createProperty = __webpack_require__2(4659); - var fails = __webpack_require__2(9039); - var parseJSONString = __webpack_require__2(8235); - var NATIVE_SYMBOL = __webpack_require__2(4495); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var DESCRIPTORS = __webpack_require__3(3724); + var globalThis2 = __webpack_require__3(4576); + var getBuiltIn = __webpack_require__3(7751); + var uncurryThis = __webpack_require__3(9504); + var call = __webpack_require__3(9565); + var isCallable = __webpack_require__3(4901); + var isObject5 = __webpack_require__3(34); + var isArray = __webpack_require__3(4376); + var hasOwn = __webpack_require__3(9297); + var toString2 = __webpack_require__3(655); + var lengthOfArrayLike = __webpack_require__3(6198); + var createProperty = __webpack_require__3(4659); + var fails = __webpack_require__3(9039); + var parseJSONString = __webpack_require__3(8235); + var NATIVE_SYMBOL = __webpack_require__3(4495); var JSON2 = globalThis2.JSON; var Number2 = globalThis2.Number; var SyntaxError2 = globalThis2.SyntaxError; @@ -124808,7 +187149,7 @@ var __webpack_modules__ = { var val = holder[name]; var unmodified = node2 && val === node2.value; var context2 = unmodified && typeof node2.source == "string" ? { source: node2.source } : {}; - var elementRecordsLen, keys2, len, i, P; + var elementRecordsLen, keys2, len, i, P2; if (isObject5(val)) { var nodeIsArray = isArray(val); var nodes = unmodified ? node2.nodes : nodeIsArray ? [] : {}; @@ -124822,8 +187163,8 @@ var __webpack_modules__ = { keys2 = enumerableOwnProperties(val); len = lengthOfArrayLike(keys2); for (i = 0; i < len; i++) { - P = keys2[i]; - internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : void 0)); + P2 = keys2[i]; + internalizeProperty(val, P2, internalize(val, P2, reviver, hasOwn(nodes, P2) ? nodes[P2] : void 0)); } } } @@ -124997,10 +187338,10 @@ var __webpack_modules__ = { /***/ 8469: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var iterateSimple = __webpack_require__2(507); - var SetHelpers = __webpack_require__2(4402); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var iterateSimple = __webpack_require__3(507); + var SetHelpers = __webpack_require__3(4402); var Set2 = SetHelpers.Set; var SetPrototype = SetHelpers.proto; var forEach = uncurryThis(SetPrototype.forEach); @@ -125014,9 +187355,9 @@ var __webpack_modules__ = { /***/ 8480: ( /***/ - (__unused_webpack_module, exports2, __webpack_require__2) => { - var internalObjectKeys = __webpack_require__2(1828); - var enumBugKeys = __webpack_require__2(8727); + (__unused_webpack_module, exports2, __webpack_require__3) => { + var internalObjectKeys = __webpack_require__3(1828); + var enumBugKeys = __webpack_require__3(8727); var hiddenKeys = enumBugKeys.concat("length", "prototype"); exports2.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { return internalObjectKeys(O, hiddenKeys); @@ -125026,13 +187367,13 @@ var __webpack_modules__ = { /***/ 8527: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var has3 = __webpack_require__2(4402).has; - var size3 = __webpack_require__2(5170); - var getSetRecord = __webpack_require__2(3789); - var iterateSimple = __webpack_require__2(507); - var iteratorClose = __webpack_require__2(9539); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var has3 = __webpack_require__3(4402).has; + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSimple = __webpack_require__3(507); + var iteratorClose = __webpack_require__3(9539); module2.exports = function isSupersetOf(other) { var O = aSet(this); var otherRec = getSetRecord(other); @@ -125047,8 +187388,8 @@ var __webpack_modules__ = { /***/ 8551: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isObject5 = __webpack_require__2(34); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isObject5 = __webpack_require__3(34); var $String = String; var $TypeError = TypeError; module2.exports = function(argument) { @@ -125060,8 +187401,8 @@ var __webpack_modules__ = { /***/ 8574: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); var $Error = Error; var replace = uncurryThis("".replace); var TEST = function(arg) { @@ -125080,9 +187421,9 @@ var __webpack_modules__ = { /***/ 8622: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var isCallable = __webpack_require__2(4901); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var isCallable = __webpack_require__3(4901); var WeakMap2 = globalThis2.WeakMap; module2.exports = isCallable(WeakMap2) && /native code/.test(String(WeakMap2)); } @@ -125090,11 +187431,11 @@ var __webpack_modules__ = { /***/ 8646: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var getIteratorMethod = __webpack_require__2(851); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var getIteratorMethod = __webpack_require__3(851); module2.exports = function(obj2, stringHandling) { if (!stringHandling || typeof obj2 !== "string") anObject(obj2); var method = getIteratorMethod(obj2); @@ -125105,9 +187446,9 @@ var __webpack_modules__ = { /***/ 8686: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var fails = __webpack_require__2(9039); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var fails = __webpack_require__3(9039); module2.exports = DESCRIPTORS && fails(function() { return Object.defineProperty(function() { }, "prototype", { @@ -125120,10 +187461,10 @@ var __webpack_modules__ = { /***/ 8721: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var DESCRIPTORS = __webpack_require__2(3724); - var uncurryThis = __webpack_require__2(9504); - var defineBuiltInAccessor = __webpack_require__2(2106); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var DESCRIPTORS = __webpack_require__3(3724); + var uncurryThis = __webpack_require__3(9504); + var defineBuiltInAccessor = __webpack_require__3(2106); var URLSearchParamsPrototype = URLSearchParams.prototype; var forEach = uncurryThis(URLSearchParamsPrototype.forEach); if (DESCRIPTORS && !("size" in URLSearchParamsPrototype)) { @@ -125159,8 +187500,8 @@ var __webpack_modules__ = { /***/ 8745: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_BIND = __webpack_require__2(616); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); var FunctionPrototype = Function.prototype; var apply = FunctionPrototype.apply; var call = FunctionPrototype.call; @@ -125172,13 +187513,13 @@ var __webpack_modules__ = { /***/ 8750: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var aSet = __webpack_require__2(7080); - var SetHelpers = __webpack_require__2(4402); - var size3 = __webpack_require__2(5170); - var getSetRecord = __webpack_require__2(3789); - var iterateSet = __webpack_require__2(8469); - var iterateSimple = __webpack_require__2(507); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var aSet = __webpack_require__3(7080); + var SetHelpers = __webpack_require__3(4402); + var size3 = __webpack_require__3(5170); + var getSetRecord = __webpack_require__3(3789); + var iterateSet = __webpack_require__3(8469); + var iterateSimple = __webpack_require__3(507); var Set2 = SetHelpers.Set; var add = SetHelpers.add; var has3 = SetHelpers.has; @@ -125215,8 +187556,8 @@ var __webpack_modules__ = { /***/ 8981: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var requireObjectCoercible = __webpack_require__2(7750); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var requireObjectCoercible = __webpack_require__3(7750); var $Object = Object; module2.exports = function(argument) { return $Object(requireObjectCoercible(argument)); @@ -125239,15 +187580,15 @@ var __webpack_modules__ = { /***/ 9143: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var uncurryThis = __webpack_require__2(9504); - var anObjectOrUndefined = __webpack_require__2(3972); - var aString = __webpack_require__2(3463); - var hasOwn = __webpack_require__2(9297); - var base64Map = __webpack_require__2(2804); - var getAlphabetOption = __webpack_require__2(944); - var notDetached = __webpack_require__2(5169); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anObjectOrUndefined = __webpack_require__3(3972); + var aString = __webpack_require__3(3463); + var hasOwn = __webpack_require__3(9297); + var base64Map = __webpack_require__3(2804); + var getAlphabetOption = __webpack_require__3(944); + var notDetached = __webpack_require__3(5169); var base64Alphabet = base64Map.c2i; var base64UrlAlphabet = base64Map.c2iUrl; var SyntaxError2 = globalThis2.SyntaxError; @@ -125378,9 +187719,9 @@ var __webpack_modules__ = { /***/ 9286: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var SetHelpers = __webpack_require__2(4402); - var iterate = __webpack_require__2(8469); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var SetHelpers = __webpack_require__3(4402); + var iterate = __webpack_require__3(8469); var Set2 = SetHelpers.Set; var add = SetHelpers.add; module2.exports = function(set2) { @@ -125395,9 +187736,9 @@ var __webpack_modules__ = { /***/ 9297: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var uncurryThis = __webpack_require__2(9504); - var toObject = __webpack_require__2(8981); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var uncurryThis = __webpack_require__3(9504); + var toObject = __webpack_require__3(8981); var hasOwnProperty2 = uncurryThis({}.hasOwnProperty); module2.exports = Object.hasOwn || function hasOwn(it, key) { return hasOwnProperty2(toObject(it), key); @@ -125407,9 +187748,9 @@ var __webpack_modules__ = { /***/ 9306: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var isCallable = __webpack_require__2(4901); - var tryToString = __webpack_require__2(6823); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var isCallable = __webpack_require__3(4901); + var tryToString = __webpack_require__3(6823); var $TypeError = TypeError; module2.exports = function(argument) { if (isCallable(argument)) return argument; @@ -125420,18 +187761,18 @@ var __webpack_modules__ = { /***/ 9314: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var call = __webpack_require__2(9565); - var anObject = __webpack_require__2(8551); - var getIteratorDirect = __webpack_require__2(1767); - var notANaN = __webpack_require__2(4149); - var toPositiveInteger = __webpack_require__2(9590); - var iteratorClose = __webpack_require__2(9539); - var createIteratorProxy = __webpack_require__2(9462); - var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); - var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); - var IS_PURE = __webpack_require__2(6395); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getIteratorDirect = __webpack_require__3(1767); + var notANaN = __webpack_require__3(4149); + var toPositiveInteger = __webpack_require__3(9590); + var iteratorClose = __webpack_require__3(9539); + var createIteratorProxy = __webpack_require__3(9462); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__3(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__3(4549); + var IS_PURE = __webpack_require__3(6395); var DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("drop", 0); var dropWithoutClosingOnEarlyError = !IS_PURE && !DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("drop", RangeError); var FORCED = IS_PURE || DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR || dropWithoutClosingOnEarlyError; @@ -125469,9 +187810,9 @@ var __webpack_modules__ = { /***/ 9429: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var IS_NODE = __webpack_require__2(6193); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var IS_NODE = __webpack_require__3(6193); module2.exports = function(name) { if (IS_NODE) { try { @@ -125489,15 +187830,15 @@ var __webpack_modules__ = { /***/ 9432: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(5213); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(5213); } ), /***/ 9433: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); var defineProperty = Object.defineProperty; module2.exports = function(key, value) { try { @@ -125512,22 +187853,22 @@ var __webpack_modules__ = { /***/ 9462: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var create2 = __webpack_require__2(2360); - var createNonEnumerableProperty = __webpack_require__2(6699); - var defineBuiltIns = __webpack_require__2(6279); - var wellKnownSymbol = __webpack_require__2(8227); - var InternalStateModule = __webpack_require__2(1181); - var getMethod = __webpack_require__2(5966); - var IteratorPrototype = __webpack_require__2(7657).IteratorPrototype; - var createIterResultObject = __webpack_require__2(2529); - var iteratorClose = __webpack_require__2(9539); - var iteratorCloseAll = __webpack_require__2(1385); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var create2 = __webpack_require__3(2360); + var createNonEnumerableProperty = __webpack_require__3(6699); + var defineBuiltIns = __webpack_require__3(6279); + var wellKnownSymbol = __webpack_require__3(8227); + var InternalStateModule = __webpack_require__3(1181); + var getMethod = __webpack_require__3(5966); + var IteratorPrototype = __webpack_require__3(7657).IteratorPrototype; + var createIterResultObject = __webpack_require__3(2529); + var iteratorClose = __webpack_require__3(9539); + var iteratorCloseAll = __webpack_require__3(1385); var TO_STRING_TAG = wellKnownSymbol("toStringTag"); var ITERATOR_HELPER = "IteratorHelper"; var WRAP_FOR_VALID_ITERATOR = "WrapForValidIterator"; - var NORMAL = "normal"; + var NORMAL2 = "normal"; var THROW = "throw"; var setInternalState = InternalStateModule.set; var createIteratorProxyPrototype = function(IS_ITERATOR) { @@ -125554,16 +187895,16 @@ var __webpack_modules__ = { return returnMethod ? call(returnMethod, iterator) : createIterResultObject(void 0, true); } if (state.inner) try { - iteratorClose(state.inner.iterator, NORMAL); + iteratorClose(state.inner.iterator, NORMAL2); } catch (error62) { return iteratorClose(iterator, THROW, error62); } if (state.openIters) try { - iteratorCloseAll(state.openIters, NORMAL); + iteratorCloseAll(state.openIters, NORMAL2); } catch (error62) { return iteratorClose(iterator, THROW, error62); } - if (iterator) iteratorClose(iterator, NORMAL); + if (iterator) iteratorClose(iterator, NORMAL2); return createIterResultObject(void 0, true); } }); @@ -125592,15 +187933,15 @@ var __webpack_modules__ = { /***/ 9486: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var $ = __webpack_require__2(6518); - var globalThis2 = __webpack_require__2(4576); - var uncurryThis = __webpack_require__2(9504); - var anObjectOrUndefined = __webpack_require__2(3972); - var anUint8Array = __webpack_require__2(4154); - var notDetached = __webpack_require__2(5169); - var base64Map = __webpack_require__2(2804); - var getAlphabetOption = __webpack_require__2(944); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var $ = __webpack_require__3(6518); + var globalThis2 = __webpack_require__3(4576); + var uncurryThis = __webpack_require__3(9504); + var anObjectOrUndefined = __webpack_require__3(3972); + var anUint8Array = __webpack_require__3(4154); + var notDetached = __webpack_require__3(5169); + var base64Map = __webpack_require__3(2804); + var getAlphabetOption = __webpack_require__3(944); var base64Alphabet = base64Map.i2c; var base64UrlAlphabet = base64Map.i2cUrl; var charAt = uncurryThis("".charAt); @@ -125646,8 +187987,8 @@ var __webpack_modules__ = { /***/ 9504: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_BIND = __webpack_require__2(616); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); var FunctionPrototype = Function.prototype; var call = FunctionPrototype.call; var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call); @@ -125661,9 +188002,9 @@ var __webpack_modules__ = { /***/ 9519: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var globalThis2 = __webpack_require__2(4576); - var userAgent = __webpack_require__2(2839); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var globalThis2 = __webpack_require__3(4576); + var userAgent = __webpack_require__3(2839); var process2 = globalThis2.process; var Deno2 = globalThis2.Deno; var versions = process2 && process2.versions || Deno2 && Deno2.version; @@ -125686,10 +188027,10 @@ var __webpack_modules__ = { /***/ 9539: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var call = __webpack_require__2(9565); - var anObject = __webpack_require__2(8551); - var getMethod = __webpack_require__2(5966); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var call = __webpack_require__3(9565); + var anObject = __webpack_require__3(8551); + var getMethod = __webpack_require__3(5966); module2.exports = function(iterator, kind, value) { var innerResult, innerError; anObject(iterator); @@ -125714,8 +188055,8 @@ var __webpack_modules__ = { /***/ 9565: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var NATIVE_BIND = __webpack_require__2(616); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var NATIVE_BIND = __webpack_require__3(616); var call = Function.prototype.call; module2.exports = NATIVE_BIND ? call.bind(call) : function() { return call.apply(call, arguments); @@ -125725,12 +188066,12 @@ var __webpack_modules__ = { /***/ 9577: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - var arrayWith = __webpack_require__2(9928); - var ArrayBufferViewCore = __webpack_require__2(4644); - var isBigIntArray = __webpack_require__2(1108); - var toIntegerOrInfinity = __webpack_require__2(1291); - var toBigInt = __webpack_require__2(5854); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + var arrayWith = __webpack_require__3(9928); + var ArrayBufferViewCore = __webpack_require__3(4644); + var isBigIntArray = __webpack_require__3(1108); + var toIntegerOrInfinity = __webpack_require__3(1291); + var toBigInt = __webpack_require__3(5854); var aTypedArray = ArrayBufferViewCore.aTypedArray; var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor; var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; @@ -125761,8 +188102,8 @@ var __webpack_modules__ = { /***/ 9590: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toIntegerOrInfinity = __webpack_require__2(1291); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIntegerOrInfinity = __webpack_require__3(1291); var $RangeError = RangeError; module2.exports = function(it) { var result2 = toIntegerOrInfinity(it); @@ -125774,10 +188115,10 @@ var __webpack_modules__ = { /***/ 9617: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var toIndexedObject = __webpack_require__2(5397); - var toAbsoluteIndex = __webpack_require__2(5610); - var lengthOfArrayLike = __webpack_require__2(6198); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var toIndexedObject = __webpack_require__3(5397); + var toAbsoluteIndex = __webpack_require__3(5610); + var lengthOfArrayLike = __webpack_require__3(6198); var createMethod = function(IS_INCLUDES) { return function($this, el, fromIndex) { var O = toIndexedObject($this); @@ -125808,15 +188149,15 @@ var __webpack_modules__ = { /***/ 9631: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(9486); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(9486); } ), /***/ 9797: ( /***/ - (__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { - __webpack_require__2(4226); + (__unused_webpack_module, __unused_webpack_exports, __webpack_require__3) => { + __webpack_require__3(4226); } ), /***/ @@ -125854,19 +188195,19 @@ var __webpack_modules__ = { /***/ 9928: ( /***/ - (module2, __unused_webpack_exports, __webpack_require__2) => { - var lengthOfArrayLike = __webpack_require__2(6198); - var toIntegerOrInfinity = __webpack_require__2(1291); + (module2, __unused_webpack_exports, __webpack_require__3) => { + var lengthOfArrayLike = __webpack_require__3(6198); + var toIntegerOrInfinity = __webpack_require__3(1291); var $RangeError = RangeError; module2.exports = function(O, C, index2, value) { var len = lengthOfArrayLike(O); var relativeIndex = toIntegerOrInfinity(index2); var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex; if (actualIndex >= len || actualIndex < 0) throw new $RangeError("Incorrect index"); - var A = new C(len); + var A2 = new C(len); var k = 0; - for (; k < len; k++) A[k] = k === actualIndex ? value : O[k]; - return A; + for (; k < len; k++) A2[k] = k === actualIndex ? value : O[k]; + return A2; }; } ) @@ -126208,23 +188549,23 @@ function updateUrlHash(url2, hash2, allowRel = false) { } return ""; } -function shadow(obj2, prop, value, nonSerializable = false) { +function shadow(obj2, prop, value, nonSerializable2 = false) { Object.defineProperty(obj2, prop, { value, - enumerable: !nonSerializable, + enumerable: !nonSerializable2, configurable: true, writable: false }); return value; } var BaseException = function BaseExceptionClosure() { - function BaseException2(message2, name) { + function BaseException3(message2, name) { this.message = message2; this.name = name; } - BaseException2.prototype = new Error(); - BaseException2.constructor = BaseException2; - return BaseException2; + BaseException3.prototype = new Error(); + BaseException3.constructor = BaseException3; + return BaseException3; }(); var PasswordException = class extends BaseException { constructor(msg, code) { @@ -128208,8 +190549,8 @@ var KeyboardManager = class { if (!this.allKeys.has(event.key)) { return; } - const info2 = this.callbacks.get(this.#serialize(event)); - if (!info2) { + const info3 = this.callbacks.get(this.#serialize(event)); + if (!info3) { return; } const { @@ -128219,7 +190560,7 @@ var KeyboardManager = class { args = [], checker = null } - } = info2; + } = info3; if (checker && !checker(self2, event)) { return; } @@ -128549,9 +190890,9 @@ var AnnotationEditorUIManager = class _AnnotationEditorUIManager { editComment(editor, posX, posY, options) { this.#commentManager?.showDialog(this, editor, posX, posY, options); } - selectComment(pageIndex, uid2) { + selectComment(pageIndex, uid3) { const layer = this.#allLayers.get(pageIndex); - const editor = layer?.getEditorByUID(uid2); + const editor = layer?.getEditorByUID(uid3); editor?.toggleComment(true, true); } updateComment(editor) { @@ -129146,11 +191487,11 @@ var AnnotationEditorUIManager = class _AnnotationEditorUIManager { this.disableUserSelect(false); } } - registerEditorTypes(types2) { + registerEditorTypes(types3) { if (this.#editorTypes) { return; } - this.#editorTypes = types2; + this.#editorTypes = types3; for (const editorType of this.#editorTypes) { this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); } @@ -132592,11 +194933,11 @@ var FontLoader = class { } } async loadSystemFont({ - systemFontInfo: info2, + systemFontInfo: info3, disableFontFace, _inspectFont }) { - if (!info2 || this.#systemFonts.has(info2.loadedName)) { + if (!info3 || this.#systemFonts.has(info3.loadedName)) { return; } assert2(!disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set."); @@ -132605,15 +194946,15 @@ var FontLoader = class { loadedName, src, style - } = info2; + } = info3; const fontFace = new FontFace(loadedName, src, style); this.addNativeFontFace(fontFace); try { await fontFace.load(); this.#systemFonts.add(loadedName); - _inspectFont?.(info2); + _inspectFont?.(info3); } catch { - warn(`Cannot load system font: ${info2.baseFontName}, installing it could help to improve PDF rendering.`); + warn(`Cannot load system font: ${info3.baseFontName}, installing it could help to improve PDF rendering.`); this.removeNativeFontFace(fontFace); } return; @@ -132687,7 +195028,7 @@ var FontLoader = class { return shadow(this, "_loadTestFont", testFont); } _prepareFontLoadEvent(font, request) { - function int322(data2, offset) { + function int323(data2, offset) { return data2.charCodeAt(offset) << 24 | data2.charCodeAt(offset + 1) << 16 | data2.charCodeAt(offset + 2) << 8 | data2.charCodeAt(offset + 3) & 255; } function spliceString(s, offset, remove, insert) { @@ -132722,12 +195063,12 @@ var FontLoader = class { data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId); const CFF_CHECKSUM_OFFSET = 16; const XXXX_VALUE = 1482184792; - let checksum = int322(data, CFF_CHECKSUM_OFFSET); + let checksum = int323(data, CFF_CHECKSUM_OFFSET); for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { - checksum = checksum - XXXX_VALUE + int322(loadTestFontId, i) | 0; + checksum = checksum - XXXX_VALUE + int323(loadTestFontId, i) | 0; } if (i < loadTestFontId.length) { - checksum = checksum - XXXX_VALUE + int322(loadTestFontId + "XXX", i) | 0; + checksum = checksum - XXXX_VALUE + int323(loadTestFontId + "XXX", i) | 0; } data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum)); const url2 = `url(data:font/opentype;base64,${btoa(data)});`; @@ -132812,11 +195153,11 @@ var FontFaceObject = class { } catch (ex) { warn(`getPathGenerator - ignoring character: "${ex}".`); } - const path = new Path2D(cmds || ""); + const path2 = new Path2D(cmds || ""); if (!this.fontExtraProperties) { objs.delete(objId); } - return this.compiledGlyphs[character] = path; + return this.compiledGlyphs[character] = path2; } get black() { return this.#fontData.black; @@ -133583,25 +195924,25 @@ var DOMFilterFactory = class extends BaseFilterFactory { addHCMFilter(fgColor, bgColor) { const key = `${fgColor}-${bgColor}`; const filterName = "base"; - let info2 = this.#hcmCache.get(filterName); - if (info2?.key === key) { - return info2.url; - } - if (info2) { - info2.filter?.remove(); - info2.key = key; - info2.url = "none"; - info2.filter = null; + let info3 = this.#hcmCache.get(filterName); + if (info3?.key === key) { + return info3.url; + } + if (info3) { + info3.filter?.remove(); + info3.key = key; + info3.url = "none"; + info3.filter = null; } else { - info2 = { + info3 = { key, url: "none", filter: null }; - this.#hcmCache.set(filterName, info2); + this.#hcmCache.set(filterName, info3); } if (!fgColor || !bgColor) { - return info2.url; + return info3.url; } const fgRGB = this.#getRGB(fgColor); fgColor = Util.makeHexColor(...fgRGB); @@ -133609,7 +195950,7 @@ var DOMFilterFactory = class extends BaseFilterFactory { bgColor = Util.makeHexColor(...bgRGB); this.#defs.style.color = ""; if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) { - return info2.url; + return info3.url; } const map3 = new Array(256); for (let i = 0; i <= 255; i++) { @@ -133618,7 +195959,7 @@ var DOMFilterFactory = class extends BaseFilterFactory { } const table2 = map3.join(","); const id = `g_${this.#docId}_hcm_filter`; - const filter2 = info2.filter = this.#createFilter(id); + const filter2 = info3.filter = this.#createFilter(id); this.#addTransferMapConversion(table2, table2, table2, filter2); this.#addGrayConversion(filter2); const getSteps = (c, n) => { @@ -133631,8 +195972,8 @@ var DOMFilterFactory = class extends BaseFilterFactory { return arr.join(","); }; this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter2); - info2.url = this.#createUrl(id); - return info2.url; + info3.url = this.#createUrl(id); + return info3.url; } addAlphaFilter(map3) { let value = this.#cache.get(map3); @@ -133684,25 +196025,25 @@ var DOMFilterFactory = class extends BaseFilterFactory { } addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; - let info2 = this.#hcmCache.get(filterName); - if (info2?.key === key) { - return info2.url; - } - if (info2) { - info2.filter?.remove(); - info2.key = key; - info2.url = "none"; - info2.filter = null; + let info3 = this.#hcmCache.get(filterName); + if (info3?.key === key) { + return info3.url; + } + if (info3) { + info3.filter?.remove(); + info3.key = key; + info3.url = "none"; + info3.filter = null; } else { - info2 = { + info3 = { key, url: "none", filter: null }; - this.#hcmCache.set(filterName, info2); + this.#hcmCache.set(filterName, info3); } if (!fgColor || !bgColor) { - return info2.url; + return info3.url; } const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]); @@ -133732,11 +196073,11 @@ var DOMFilterFactory = class extends BaseFilterFactory { return arr.join(","); }; const id = `g_${this.#docId}_hcm_${filterName}_filter`; - const filter2 = info2.filter = this.#createFilter(id); + const filter2 = info3.filter = this.#createFilter(id); this.#addGrayConversion(filter2); this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter2); - info2.url = this.#createUrl(id); - return info2.url; + info3.url = this.#createUrl(id); + return info3.url; } destroy(keepHCM = false) { if (keepHCM && this.#_hcmCache?.size) { @@ -135908,47 +198249,47 @@ var CanvasGraphics = class _CanvasGraphics { this._cachedGetSinglePixelWidth = null; } constructPath(opIdx, op, data, minMax) { - let [path] = data; + let [path2] = data; if (!minMax) { - path ||= data[0] = new Path2D(); - this[op](opIdx, path); + path2 ||= data[0] = new Path2D(); + this[op](opIdx, path2); return; } if (this.dependencyTracker !== null) { const outerExtraSize = op === OPS.stroke ? this.current.lineWidth / 2 : 0; this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, this.ctx, minMax[0] - outerExtraSize, minMax[2] + outerExtraSize, minMax[1] - outerExtraSize, minMax[3] + outerExtraSize).recordDependencies(opIdx, ["transform"]); } - if (!(path instanceof Path2D)) { + if (!(path2 instanceof Path2D)) { const path2d = data[0] = new Path2D(); - for (let i = 0, ii = path.length; i < ii; ) { - switch (path[i++]) { + for (let i = 0, ii = path2.length; i < ii; ) { + switch (path2[i++]) { case DrawOPS.moveTo: - path2d.moveTo(path[i++], path[i++]); + path2d.moveTo(path2[i++], path2[i++]); break; case DrawOPS.lineTo: - path2d.lineTo(path[i++], path[i++]); + path2d.lineTo(path2[i++], path2[i++]); break; case DrawOPS.curveTo: - path2d.bezierCurveTo(path[i++], path[i++], path[i++], path[i++], path[i++], path[i++]); + path2d.bezierCurveTo(path2[i++], path2[i++], path2[i++], path2[i++], path2[i++], path2[i++]); break; case DrawOPS.closePath: path2d.closePath(); break; default: - warn(`Unrecognized drawing path operator: ${path[i - 1]}`); + warn(`Unrecognized drawing path operator: ${path2[i - 1]}`); break; } } - path = path2d; + path2 = path2d; } Util.axialAlignedBoundingBox(minMax, getCurrentTransform(this.ctx), this.current.minMax); - this[op](opIdx, path); + this[op](opIdx, path2); this._pathStartIdx = opIdx; } closePath(opIdx) { this.ctx.closePath(); } - stroke(opIdx, path, consumePath = true) { + stroke(opIdx, path2, consumePath = true) { const ctx = this.ctx; const strokeColor = this.current.strokeColor; ctx.globalAlpha = this.current.strokeAlpha; @@ -135959,25 +198300,25 @@ var CanvasGraphics = class _CanvasGraphics { ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx); if (baseTransform) { const newPath = new Path2D(); - newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); - path = newPath; + newPath.addPath(path2, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path2 = newPath; } - this.rescaleAndStroke(path, false); + this.rescaleAndStroke(path2, false); ctx.restore(); } else { - this.rescaleAndStroke(path, true); + this.rescaleAndStroke(path2, true); } } this.dependencyTracker?.recordDependencies(opIdx, Dependencies.stroke); if (consumePath) { - this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx))); + this.consumePath(opIdx, path2, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx))); } ctx.globalAlpha = this.current.fillAlpha; } - closeStroke(opIdx, path) { - this.stroke(opIdx, path); + closeStroke(opIdx, path2) { + this.stroke(opIdx, path2); } - fill(opIdx, path, consumePath = true) { + fill(opIdx, path2, consumePath = true) { const ctx = this.ctx; const fillColor = this.current.fillColor; const isPatternFill = this.current.patternFill; @@ -135989,18 +198330,18 @@ var CanvasGraphics = class _CanvasGraphics { ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx); if (baseTransform) { const newPath = new Path2D(); - newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); - path = newPath; + newPath.addPath(path2, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path2 = newPath; } needRestore = true; } const intersect2 = this.current.getClippedPathBoundingBox(); if (this.contentVisible && intersect2 !== null) { if (this.pendingEOFill) { - ctx.fill(path, "evenodd"); + ctx.fill(path2, "evenodd"); this.pendingEOFill = false; } else { - ctx.fill(path); + ctx.fill(path2); } } this.dependencyTracker?.recordDependencies(opIdx, Dependencies.fill); @@ -136009,34 +198350,34 @@ var CanvasGraphics = class _CanvasGraphics { this.dependencyTracker?.restore(opIdx); } if (consumePath) { - this.consumePath(opIdx, path, intersect2); + this.consumePath(opIdx, path2, intersect2); } } - eoFill(opIdx, path) { + eoFill(opIdx, path2) { this.pendingEOFill = true; - this.fill(opIdx, path); + this.fill(opIdx, path2); } - fillStroke(opIdx, path) { - this.fill(opIdx, path, false); - this.stroke(opIdx, path, false); - this.consumePath(opIdx, path); + fillStroke(opIdx, path2) { + this.fill(opIdx, path2, false); + this.stroke(opIdx, path2, false); + this.consumePath(opIdx, path2); } - eoFillStroke(opIdx, path) { + eoFillStroke(opIdx, path2) { this.pendingEOFill = true; - this.fillStroke(opIdx, path); + this.fillStroke(opIdx, path2); } - closeFillStroke(opIdx, path) { - this.fillStroke(opIdx, path); + closeFillStroke(opIdx, path2) { + this.fillStroke(opIdx, path2); } - closeEOFillStroke(opIdx, path) { + closeEOFillStroke(opIdx, path2) { this.pendingEOFill = true; - this.fillStroke(opIdx, path); + this.fillStroke(opIdx, path2); } - endPath(opIdx, path) { - this.consumePath(opIdx, path); + endPath(opIdx, path2) { + this.consumePath(opIdx, path2); } - rawFillPath(opIdx, path) { - this.ctx.fill(path); + rawFillPath(opIdx, path2) { + this.ctx.fill(path2); this.dependencyTracker?.recordDependencies(opIdx, Dependencies.rawFillPath).recordOperation(opIdx); } clip(opIdx) { @@ -136074,12 +198415,12 @@ var CanvasGraphics = class _CanvasGraphics { x, y, fontSize, - path + path: path2 } of paths) { - if (!path) { + if (!path2) { continue; } - newPath.addPath(path, new DOMMatrix(transform2).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize)); + newPath.addPath(path2, new DOMMatrix(transform2).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize)); } ctx.clip(newPath); } @@ -136172,9 +198513,9 @@ var CanvasGraphics = class _CanvasGraphics { this.moveText(opIdx, 0, this.current.leading); this.dependencyTracker?.recordIncrementalData("moveText", this.dependencyTracker.getSimpleIndex("leading") ?? opIdx); } - #getScaledPath(path, currentTransform, transform2) { + #getScaledPath(path2, currentTransform, transform2) { const newPath = new Path2D(); - newPath.addPath(path, new DOMMatrix(transform2).invertSelf().multiplySelf(currentTransform)); + newPath.addPath(path2, new DOMMatrix(transform2).invertSelf().multiplySelf(currentTransform)); return newPath; } paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) { @@ -136187,11 +198528,11 @@ var CanvasGraphics = class _CanvasGraphics { const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG); const patternFill = current.patternFill && !font.missingFile; const patternStroke = current.patternStroke && !font.missingFile; - let path; + let path2; if ((font.disableFontFace || isAddToPathSet || patternFill || patternStroke) && !font.missingFile) { - path = font.getPathGenerator(this.commonObjs, character); + path2 = font.getPathGenerator(this.commonObjs, character); } - if (path && (font.disableFontFace || patternFill || patternStroke)) { + if (path2 && (font.disableFontFace || patternFill || patternStroke)) { ctx.save(); ctx.translate(x, y); ctx.scale(fontSize, -fontSize); @@ -136201,10 +198542,10 @@ var CanvasGraphics = class _CanvasGraphics { if (patternFillTransform) { currentTransform = ctx.getTransform(); ctx.setTransform(...patternFillTransform); - const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform); + const scaledPath = this.#getScaledPath(path2, currentTransform, patternFillTransform); ctx.fill(scaledPath); } else { - ctx.fill(path); + ctx.fill(path2); } } if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { @@ -136221,10 +198562,10 @@ var CanvasGraphics = class _CanvasGraphics { const transf = Util.transform([a, b2, c, d, 0, 0], invPatternTransform); Util.singularValueDecompose2dScale(transf, XY); ctx.lineWidth *= Math.max(XY[0], XY[1]) / fontSize; - ctx.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform)); + ctx.stroke(this.#getScaledPath(path2, currentTransform, patternStrokeTransform)); } else { ctx.lineWidth /= fontSize; - ctx.stroke(path); + ctx.stroke(path2); } } ctx.restore(); @@ -136247,7 +198588,7 @@ var CanvasGraphics = class _CanvasGraphics { x, y, fontSize, - path + path: path2 }); this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y); } @@ -136340,13 +198681,13 @@ var CanvasGraphics = class _CanvasGraphics { } ctx.lineWidth = lineWidth; if (font.isInvalidPDFjsFont) { - const chars = []; + const chars2 = []; let width = 0; for (const glyph of glyphs) { - chars.push(glyph.unicode); + chars2.push(glyph.unicode); width += glyph.width; } - const joinedChars = chars.join(""); + const joinedChars = chars2.join(""); ctx.fillText(joinedChars, 0, 0); if (this.dependencyTracker !== null) { const measure = ctx.measureText(joinedChars); @@ -136653,9 +198994,9 @@ var CanvasGraphics = class _CanvasGraphics { const [x0, y0, x1, y1] = group2.bbox; clip.rect(x0, y0, x1 - x0, y1 - y0); if (group2.matrix) { - const path = new Path2D(); - path.addPath(clip, new DOMMatrix(group2.matrix)); - clip = path; + const path2 = new Path2D(); + path2.addPath(clip, new DOMMatrix(group2.matrix)); + clip = path2; } groupCtx.clip(clip); if (group2.smask) { @@ -136999,7 +199340,7 @@ var CanvasGraphics = class _CanvasGraphics { } endCompat(opIdx) { } - consumePath(opIdx, path, clipBox) { + consumePath(opIdx, path2, clipBox) { const isEmpty2 = this.current.isEmptyClip(); if (this.pendingClip) { this.current.updateClipFromPath(); @@ -137011,9 +199352,9 @@ var CanvasGraphics = class _CanvasGraphics { if (this.pendingClip) { if (!isEmpty2) { if (this.pendingClip === EO_CLIP) { - ctx.clip(path, "evenodd"); + ctx.clip(path2, "evenodd"); } else { - ctx.clip(path); + ctx.clip(path2); } } this.pendingClip = null; @@ -137086,7 +199427,7 @@ var CanvasGraphics = class _CanvasGraphics { } return this._cachedScaleForStroking; } - rescaleAndStroke(path, saveRestore) { + rescaleAndStroke(path2, saveRestore) { const { ctx, current: { @@ -137096,7 +199437,7 @@ var CanvasGraphics = class _CanvasGraphics { const [scaleX, scaleY] = this.getScaleForStroking(); if (scaleX === scaleY) { ctx.lineWidth = (lineWidth || 1) * scaleX; - ctx.stroke(path); + ctx.stroke(path2); return; } const dashes = ctx.getLineDash(); @@ -137107,7 +199448,7 @@ var CanvasGraphics = class _CanvasGraphics { SCALE_MATRIX.a = 1 / scaleX; SCALE_MATRIX.d = 1 / scaleY; const newPath = new Path2D(); - newPath.addPath(path, SCALE_MATRIX); + newPath.addPath(path2, SCALE_MATRIX); if (dashes.length > 0) { const scale = Math.max(scaleX, scaleY); ctx.setLineDash(dashes.map((x) => x / scale)); @@ -137138,12 +199479,12 @@ var CssFontInfo = class _CssFontInfo { #view; #decoder; static strings = ["fontFamily", "fontWeight", "italicAngle"]; - static write(info2) { + static write(info3) { const encoder2 = new TextEncoder(); const encodedStrings = {}; let stringsLength = 0; for (const prop of _CssFontInfo.strings) { - const encoded = encoder2.encode(info2[prop]); + const encoded = encoder2.encode(info3[prop]); encodedStrings[prop] = encoded; stringsLength += 4 + encoded.length; } @@ -137190,27 +199531,27 @@ var SystemFontInfo = class _SystemFontInfo { #view; #decoder; static strings = ["css", "loadedName", "baseFontName", "src"]; - static write(info2) { + static write(info3) { const encoder2 = new TextEncoder(); const encodedStrings = {}; let stringsLength = 0; for (const prop of _SystemFontInfo.strings) { - const encoded = encoder2.encode(info2[prop]); + const encoded = encoder2.encode(info3[prop]); encodedStrings[prop] = encoded; stringsLength += 4 + encoded.length; } stringsLength += 4; let encodedStyleStyle, encodedStyleWeight, lengthEstimate = 1 + stringsLength; - if (info2.style) { - encodedStyleStyle = encoder2.encode(info2.style.style); - encodedStyleWeight = encoder2.encode(info2.style.weight); + if (info3.style) { + encodedStyleStyle = encoder2.encode(info3.style.style); + encodedStyleWeight = encoder2.encode(info3.style.weight); lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length; } const buffer2 = new ArrayBuffer(lengthEstimate); const data = new Uint8Array(buffer2); const view = new DataView(buffer2); let offset = 0; - view.setUint8(offset++, info2.guessFallback ? 1 : 0); + view.setUint8(offset++, info3.guessFallback ? 1 : 0); view.setUint32(offset, 0); offset += 4; stringsLength = 0; @@ -137223,7 +199564,7 @@ var SystemFontInfo = class _SystemFontInfo { offset += 4 + length; } view.setUint32(offset - stringsLength - 4, stringsLength); - if (info2.style) { + if (info3.style) { view.setUint32(offset, encodedStyleStyle.length); data.set(encodedStyleStyle, offset + 4); offset += 4 + encodedStyleStyle.length; @@ -139605,7 +201946,7 @@ function getDocument(src = {}) { const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null; const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : 2 ** 16; let worker = src.worker instanceof PDFWorker ? src.worker : null; - const verbosity2 = src.verbosity; + const verbosity3 = src.verbosity; const docBaseUrl = typeof src.docBaseUrl === "string" && !isDataScheme(src.docBaseUrl) ? src.docBaseUrl : null; const cMapUrl = getFactoryUrlProp(src.cMapUrl); const cMapPacked = src.cMapPacked !== false; @@ -139617,7 +201958,7 @@ function getDocument(src = {}) { const WasmFactory = src.WasmFactory || (isNodeJS ? NodeWasmFactory : DOMWasmFactory); const ignoreErrors = src.stopAtErrors !== true; const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1; - const isEvalSupported2 = src.isEvalSupported !== false; + const isEvalSupported3 = src.isEvalSupported !== false; const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS; const isImageDecoderSupported = typeof src.isImageDecoderSupported === "boolean" ? src.isImageDecoderSupported : !isNodeJS && (util_FeatureTest.platform.isFirefox || !globalThis.chrome); const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1; @@ -139637,7 +201978,7 @@ function getDocument(src = {}) { const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !isNodeJS && !disableFontFace; const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : !!(CMapReaderFactory === DOMCMapReaderFactory && StandardFontDataFactory === DOMStandardFontDataFactory && WasmFactory === DOMWasmFactory && cMapUrl && standardFontDataUrl && wasmUrl && isValidFetchUrl(cMapUrl, document.baseURI) && isValidFetchUrl(standardFontDataUrl, document.baseURI) && isValidFetchUrl(wasmUrl, document.baseURI)); const styleElement = null; - setVerbosityLevel(verbosity2); + setVerbosityLevel(verbosity3); const transportFactory = { canvasFactory: new CanvasFactory({ ownerDocument, @@ -139660,7 +202001,7 @@ function getDocument(src = {}) { }; if (!worker) { worker = PDFWorker.create({ - verbosity: verbosity2, + verbosity: verbosity3, port: GlobalWorkerOptions.workerPort }); task._worker = worker; @@ -139679,7 +202020,7 @@ function getDocument(src = {}) { maxImageSize, disableFontFace, ignoreErrors, - isEvalSupported: isEvalSupported2, + isEvalSupported: isEvalSupported3, isOffscreenCanvasSupported, isImageDecoderSupported, canvasMaxAreaInBytes, @@ -139894,8 +202235,8 @@ var PDFDocumentProxy = class { getAttachments() { return this._transport.getAttachments(); } - getAnnotationsByType(types2, pageIndexesToSkip) { - return this._transport.getAnnotationsByType(types2, pageIndexesToSkip); + getAnnotationsByType(types3, pageIndexesToSkip) { + return this._transport.getAnnotationsByType(types3, pageIndexesToSkip); } getJSActions() { return this._transport.getDocJSActions(); @@ -140440,11 +202781,11 @@ var PDFWorker = class _PDFWorker { constructor({ name = null, port = null, - verbosity: verbosity2 = getVerbosityLevel() + verbosity: verbosity3 = getVerbosityLevel() } = {}) { this.name = name; this.destroyed = false; - this.verbosity = verbosity2; + this.verbosity = verbosity3; if (port) { if (_PDFWorker.#workerPorts.has(port)) { throw new Error("Cannot use more than one PDFWorker per port."); @@ -140550,7 +202891,7 @@ var PDFWorker = class _PDFWorker { warn("Setting up fake worker."); _PDFWorker.#isWorkerDisabled = true; } - _PDFWorker._setupFakeWorkerGlobal.then((WorkerMessageHandler) => { + _PDFWorker._setupFakeWorkerGlobal.then((WorkerMessageHandler2) => { if (this.destroyed) { this.#capability.reject(new Error("Worker was destroyed")); return; @@ -140559,7 +202900,7 @@ var PDFWorker = class _PDFWorker { this.#port = port; const id = `fake${_PDFWorker.#fakeWorkerId++}`; const workerHandler = new MessageHandler(id + "_worker", id, port); - WorkerMessageHandler.setup(workerHandler, port); + WorkerMessageHandler2.setup(workerHandler, port); this.#messageHandler = new MessageHandler(id, id + "_worker", port); this.#resolve(); }).catch((reason) => { @@ -141071,9 +203412,9 @@ var WorkerTransport = class { getAttachments() { return this.messageHandler.sendWithPromise("GetAttachments", null); } - getAnnotationsByType(types2, pageIndexesToSkip) { + getAnnotationsByType(types3, pageIndexesToSkip) { return this.messageHandler.sendWithPromise("GetAnnotationsByType", { - types: types2, + types: types3, pageIndexesToSkip }); } @@ -142814,13 +205155,13 @@ var WidgetAnnotationElement = class extends AnnotationElement { style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment]; } } - _setRequired(element, isRequired) { - if (isRequired) { + _setRequired(element, isRequired2) { + if (isRequired2) { element.setAttribute("required", true); } else { element.removeAttribute("required"); } - element.setAttribute("aria-required", isRequired); + element.setAttribute("aria-required", isRequired2); } }; var TextWidgetAnnotationElement = class extends WidgetAnnotationElement { @@ -145369,9 +207710,9 @@ var FreeTextEditor = class _FreeTextEditor extends AnnotationEditor { editorDivPaste(event) { const clipboardData = event.clipboardData || window.clipboardData; const { - types: types2 + types: types3 } = clipboardData; - if (types2.length === 1 && types2[0] === "text/plain") { + if (types3.length === 1 && types3[0] === "text/plain") { return; } event.preventDefault(); @@ -147231,7 +209572,7 @@ var DrawingEditor = class _DrawingEditor extends AnnotationEditor { } return p1; } - static getDefaultDrawingOptions(_options) { + static getDefaultDrawingOptions(_options2) { unreachable("Not implemented"); } static get typesMap() { @@ -148650,11 +210991,11 @@ var InkEditor = class _InkEditor extends DrawingEditor { }; var ContourDrawOutline = class extends InkDrawOutline { toSVGPath() { - let path = super.toSVGPath(); - if (!path.endsWith("Z")) { - path += "Z"; + let path2 = super.toSVGPath(); + if (!path2.endsWith("Z")) { + path2 += "Z"; } - return path; + return path2; } }; var BASE_HEADER_LENGTH = 8; @@ -148704,15 +211045,15 @@ var SignatureExtractor = class { } static #findContours(buf, width, height, threshold) { const N = buf.length; - const types2 = new Int32Array(N); + const types3 = new Int32Array(N); for (let i = 0; i < N; i++) { - types2[i] = buf[i] <= threshold ? 1 : 0; + types3[i] = buf[i] <= threshold ? 1 : 0; } for (let i = 1; i < height - 1; i++) { - types2[i * width] = types2[i * width + width - 1] = 0; + types3[i * width] = types3[i * width + width - 1] = 0; } for (let i = 0; i < width; i++) { - types2[i] = types2[width * height - 1 - i] = 0; + types3[i] = types3[width * height - 1 - i] = 0; } let nbd = 1; let lnbd; @@ -148721,16 +211062,16 @@ var SignatureExtractor = class { lnbd = 1; for (let j = 1; j < width - 1; j++) { const ij = i * width + j; - const pix = types2[ij]; + const pix = types3[ij]; if (pix === 0) { continue; } let i2 = i; let j2 = j; - if (pix === 1 && types2[ij - 1] === 0) { + if (pix === 1 && types3[ij - 1] === 0) { nbd += 1; j2 -= 1; - } else if (pix >= 1 && types2[ij + 1] === 0) { + } else if (pix >= 1 && types3[ij + 1] === 0) { nbd += 1; j2 += 1; if (pix > 1) { @@ -148765,11 +211106,11 @@ var SignatureExtractor = class { } else { contour.parent = isHole ? lnbd : contour0.parent; } - const k = this.#clockwiseNonZero(types2, width, i, j, i2, j2, 0); + const k = this.#clockwiseNonZero(types3, width, i, j, i2, j2, 0); if (k === -1) { - types2[ij] = -nbd; - if (types2[ij] !== 1) { - lnbd = Math.abs(types2[ij]); + types3[ij] = -nbd; + if (types3[ij] !== 1) { + lnbd = Math.abs(types3[ij]); } continue; } @@ -148782,21 +211123,21 @@ var SignatureExtractor = class { let i3 = i; let j3 = j; while (true) { - const kk = this.#counterClockwiseNonZero(types2, width, i3, j3, i2, j2, 1); + const kk = this.#counterClockwiseNonZero(types3, width, i3, j3, i2, j2, 1); shiftI = this.#neighborIdToIndex[2 * kk]; shiftJ = this.#neighborIdToIndex[2 * kk + 1]; const i4 = i3 + shiftI; const j4 = j3 + shiftJ; points.push(j4, i4); const ij3 = i3 * width + j3; - if (types2[ij3 + 1] === 0) { - types2[ij3] = -nbd; - } else if (types2[ij3] === 1) { - types2[ij3] = nbd; + if (types3[ij3 + 1] === 0) { + types3[ij3] = -nbd; + } else if (types3[ij3] === 1) { + types3[ij3] = nbd; } if (i4 === i && j4 === j && i3 === i1 && j3 === j1) { - if (types2[ij] !== 1) { - lnbd = Math.abs(types2[ij]); + if (types3[ij] !== 1) { + lnbd = Math.abs(types3[ij]); } break; } else { @@ -150773,9 +213114,9 @@ var AnnotationEditorLayer = class _AnnotationEditorLayer { mustExec: false }); } - getEditorByUID(uid2) { + getEditorByUID(uid3) { for (const editor of this.#editors.values()) { - if (editor.uid === uid2) { + if (editor.uid === uid3) { return editor; } } @@ -151130,13 +213471,13 @@ var DrawLayer = class _DrawLayer { const root2 = this.#createSVG(); const defs = _DrawLayer._svgFactory.createElement("defs"); root2.append(defs); - const path = _DrawLayer._svgFactory.createElement("path"); - defs.append(path); + const path2 = _DrawLayer._svgFactory.createElement("path"); + defs.append(path2); const pathId = `path_p${this.pageIndex}_${id}`; - path.setAttribute("id", pathId); - path.setAttribute("vector-effect", "non-scaling-stroke"); + path2.setAttribute("id", pathId); + path2.setAttribute("vector-effect", "non-scaling-stroke"); if (isPathUpdatable) { - this.#toUpdate.set(id, path); + this.#toUpdate.set(id, path2); } const clipPathId = hasClip ? this.#createClipPath(defs, pathId) : null; const use = _DrawLayer._svgFactory.createElement("use"); @@ -151154,11 +213495,11 @@ var DrawLayer = class _DrawLayer { const root2 = this.#createSVG(); const defs = _DrawLayer._svgFactory.createElement("defs"); root2.append(defs); - const path = _DrawLayer._svgFactory.createElement("path"); - defs.append(path); + const path2 = _DrawLayer._svgFactory.createElement("path"); + defs.append(path2); const pathId = `path_p${this.pageIndex}_${id}`; - path.setAttribute("id", pathId); - path.setAttribute("vector-effect", "non-scaling-stroke"); + path2.setAttribute("id", pathId); + path2.setAttribute("vector-effect", "non-scaling-stroke"); let maskId; if (mustRemoveSelfIntersections) { const mask = _DrawLayer._svgFactory.createElement("mask"); @@ -151205,7 +213546,7 @@ var DrawLayer = class _DrawLayer { root: root2, bbox, rootClass, - path + path: path2 } = properties; const element = typeof elementOrId === "number" ? this.#mapping.get(elementOrId) : elementOrId; if (!element) { @@ -151225,10 +213566,10 @@ var DrawLayer = class _DrawLayer { classList.toggle(className, value); } } - if (path) { + if (path2) { const defs = element.firstChild; const pathElement = defs.firstChild; - this.#updateProperties(pathElement, path); + this.#updateProperties(pathElement, path2); } } updateParent(id, layer) { @@ -152326,12 +214667,12 @@ var PathGeometry; PathGeometry2[PathGeometry2["rectangle"] = 3] = "rectangle"; })(PathGeometry || (PathGeometry = {})); var DrawOPS2; -(function(DrawOPS3) { - DrawOPS3[DrawOPS3["moveTo"] = 0] = "moveTo"; - DrawOPS3[DrawOPS3["lineTo"] = 1] = "lineTo"; - DrawOPS3[DrawOPS3["curveTo"] = 2] = "curveTo"; - DrawOPS3[DrawOPS3["closePath"] = 3] = "closePath"; - DrawOPS3[DrawOPS3["rectangle"] = 4] = "rectangle"; +(function(DrawOPS4) { + DrawOPS4[DrawOPS4["moveTo"] = 0] = "moveTo"; + DrawOPS4[DrawOPS4["lineTo"] = 1] = "lineTo"; + DrawOPS4[DrawOPS4["curveTo"] = 2] = "curveTo"; + DrawOPS4[DrawOPS4["closePath"] = 3] = "closePath"; + DrawOPS4[DrawOPS4["rectangle"] = 4] = "rectangle"; })(DrawOPS2 || (DrawOPS2 = {})); // node_modules/.pnpm/pdf-parse@2.4.5/node_modules/pdf-parse/dist/pdf-parse/esm/ScreenshotResult.js @@ -152397,8 +214738,8 @@ var PDFParse = class { } // biome-ignore-start lint/suspicious/noExplicitAny: unsupported underline type static get isNodeJS() { - const isNodeJS2 = typeof process === "object" && `${process}` === "[object process]" && !process.versions.nw && !(process.versions.electron && typeof process.type !== "undefined" && process.type !== "browser"); - return isNodeJS2; + const isNodeJS3 = typeof process === "object" && `${process}` === "[object process]" && !process.versions.nw && !(process.versions.electron && typeof process.type !== "undefined" && process.type !== "browser"); + return isNodeJS3; } static setWorker(workerSrc) { if (typeof globalThis.pdfjs === "undefined") { @@ -152421,8 +214762,8 @@ var PDFParse = class { async getInfo(params = {}) { const doc = await this.load(); const result2 = new InfoResult(doc.numPages); - const { info: info2, metadata } = await doc.getMetadata(); - result2.info = info2; + const { info: info3, metadata } = await doc.getMetadata(); + result2.info = info3; result2.metadata = metadata; result2.fingerprints = doc.fingerprints; result2.outline = await doc.getOutline(); @@ -153070,8 +215411,35 @@ ${pageNumber} } }; +// node_modules/.pnpm/pdf-parse@2.4.5/node_modules/pdf-parse/dist/worker/esm/index.js +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { Canvas, createCanvas, DOMMatrix as DOMMatrix2, ImageData as ImageData2, Path2D as Path2D2 } from "@napi-rs/canvas"; +var pdf_worker_min_default = "data:text/javascript;base64,LyoqCiAqIEBsaWNzdGFydCBUaGUgZm9sbG93aW5nIGlzIHRoZSBlbnRpcmUgbGljZW5zZSBub3RpY2UgZm9yIHRoZQogKiBKYXZhU2NyaXB0IGNvZGUgaW4gdGhpcyBwYWdlCiAqCiAqIENvcHlyaWdodCAyMDI0IE1vemlsbGEgRm91bmRhdGlvbgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgogKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBAbGljZW5kIFRoZSBhYm92ZSBpcyB0aGUgZW50aXJlIGxpY2Vuc2Ugbm90aWNlIGZvciB0aGUKICogSmF2YVNjcmlwdCBjb2RlIGluIHRoaXMgcGFnZQogKi8KLyoqCiAqIHBkZmpzVmVyc2lvbiA9IDUuNC4yOTYKICogcGRmanNCdWlsZCA9IGY1NmRjODYwMQogKi92YXIgZT17MzQ6KGUsdCxyKT0+e3ZhciBhPXIoNDkwMSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiJvYmplY3QiPT10eXBlb2YgZT9udWxsIT09ZTphKGUpfX0sODE6KGUsdCxyKT0+e3ZhciBhPXIoOTU2NSksbj1yKDkzMDYpLGk9cig4NTUxKSxzPXIoNjgyMyksbz1yKDg1MSksYz1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9YXJndW1lbnRzLmxlbmd0aDwyP28oZSk6dDtpZihuKHIpKXJldHVybiBpKGEocixlKSk7dGhyb3cgbmV3IGMocyhlKSsiIGlzIG5vdCBpdGVyYWJsZSIpfX0sMTE2OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig5NTY1KSxpPXIoMjY1Mikscz1yKDkzMDYpLG89cig4NTUxKSxjPXIoMTc2NyksbD1yKDk1MzkpLGg9cig0NTQ5KSgiZmluZCIsVHlwZUVycm9yKTthKHt0YXJnZXQ6Ikl0ZXJhdG9yIixwcm90bzohMCxyZWFsOiEwLGZvcmNlZDpofSx7ZmluZDpmdW5jdGlvbiBmaW5kKGUpe28odGhpcyk7dHJ5e3MoZSl9Y2F0Y2goZSl7bCh0aGlzLCJ0aHJvdyIsZSl9aWYoaClyZXR1cm4gbihoLHRoaXMsZSk7dmFyIHQ9Yyh0aGlzKSxyPTA7cmV0dXJuIGkodCxmdW5jdGlvbih0LGEpe2lmKGUodCxyKyspKXJldHVybiBhKHQpfSx7SVNfUkVDT1JEOiEwLElOVEVSUlVQVEVEOiEwfSkucmVzdWx0fX0pfSwyODM6KGUsdCxyKT0+e3ZhciBhPXIoOTUwNCksbj1yKDkwMzkpLGk9cig0OTAxKSxzPXIoOTI5Nyksbz1yKDM3MjQpLGM9cigzNTApLkNPTkZJR1VSQUJMRSxsPXIoMzcwNiksaD1yKDExODEpLHU9aC5lbmZvcmNlLGQ9aC5nZXQsZj1TdHJpbmcsZz1PYmplY3QuZGVmaW5lUHJvcGVydHkscD1hKCIiLnNsaWNlKSxtPWEoIiIucmVwbGFjZSksYj1hKFtdLmpvaW4pLHk9byYmIW4oZnVuY3Rpb24oKXtyZXR1cm4gOCE9PWcoZnVuY3Rpb24oKXt9LCJsZW5ndGgiLHt2YWx1ZTo4fSkubGVuZ3RofSksdz1TdHJpbmcoU3RyaW5nKS5zcGxpdCgiU3RyaW5nIikseD1lLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIpeyJTeW1ib2woIj09PXAoZih0KSwwLDcpJiYodD0iWyIrbShmKHQpLC9eU3ltYm9sXCgoW14pXSopXCkuKiQvLCIkMSIpKyJdIik7ciYmci5nZXR0ZXImJih0PSJnZXQgIit0KTtyJiZyLnNldHRlciYmKHQ9InNldCAiK3QpOyghcyhlLCJuYW1lIil8fGMmJmUubmFtZSE9PXQpJiYobz9nKGUsIm5hbWUiLHt2YWx1ZTp0LGNvbmZpZ3VyYWJsZTohMH0pOmUubmFtZT10KTt5JiZyJiZzKHIsImFyaXR5IikmJmUubGVuZ3RoIT09ci5hcml0eSYmZyhlLCJsZW5ndGgiLHt2YWx1ZTpyLmFyaXR5fSk7dHJ5e3ImJnMociwiY29uc3RydWN0b3IiKSYmci5jb25zdHJ1Y3Rvcj9vJiZnKGUsInByb3RvdHlwZSIse3dyaXRhYmxlOiExfSk6ZS5wcm90b3R5cGUmJihlLnByb3RvdHlwZT12b2lkIDApfWNhdGNoKGUpe312YXIgYT11KGUpO3MoYSwic291cmNlIil8fChhLnNvdXJjZT1iKHcsInN0cmluZyI9PXR5cGVvZiB0P3Q6IiIpKTtyZXR1cm4gZX07RnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nPXgoZnVuY3Rpb24gdG9TdHJpbmcoKXtyZXR1cm4gaSh0aGlzKSYmZCh0aGlzKS5zb3VyY2V8fGwodGhpcyl9LCJ0b1N0cmluZyIpfSwzNTA6KGUsdCxyKT0+e3ZhciBhPXIoMzcyNCksbj1yKDkyOTcpLGk9RnVuY3Rpb24ucHJvdG90eXBlLHM9YSYmT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcixvPW4oaSwibmFtZSIpLGM9byYmInNvbWV0aGluZyI9PT1mdW5jdGlvbiBzb21ldGhpbmcoKXt9Lm5hbWUsbD1vJiYoIWF8fGEmJnMoaSwibmFtZSIpLmNvbmZpZ3VyYWJsZSk7ZS5leHBvcnRzPXtFWElTVFM6byxQUk9QRVI6YyxDT05GSUdVUkFCTEU6bH19LDM5NzooZSx0LHIpPT57dmFyIGE9cig3NzUxKTtlLmV4cG9ydHM9YSgiZG9jdW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiKX0sNDIxOmU9PntlLmV4cG9ydHM9e319LDQ1NjooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNDU3NiksaT1yKDk1MDQpLHM9cig0MTU0KSxvPXIoNTE2OSksYz1pKDEuMS50b1N0cmluZyksbD1uLlVpbnQ4QXJyYXksaD0hbHx8IWwucHJvdG90eXBlLnRvSGV4fHwhZnVuY3Rpb24oKXt0cnl7cmV0dXJuImZmZmZmZmZmZmZmZmZmZmYiPT09bmV3IGwoWzI1NSwyNTUsMjU1LDI1NSwyNTUsMjU1LDI1NSwyNTVdKS50b0hleCgpfWNhdGNoKGUpe3JldHVybiExfX0oKTtsJiZhKHt0YXJnZXQ6IlVpbnQ4QXJyYXkiLHByb3RvOiEwLGZvcmNlZDpofSx7dG9IZXg6ZnVuY3Rpb24gdG9IZXgoKXtzKHRoaXMpO28odGhpcy5idWZmZXIpO2Zvcih2YXIgZT0iIix0PTAscj10aGlzLmxlbmd0aDt0PHI7dCsrKXt2YXIgYT1jKHRoaXNbdF0sMTYpO2UrPTE9PT1hLmxlbmd0aD8iMCIrYTphfXJldHVybiBlfX0pfSw1MDc6KGUsdCxyKT0+e3ZhciBhPXIoOTU2NSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyKXtmb3IodmFyIG4saSxzPXI/ZTplLml0ZXJhdG9yLG89ZS5uZXh0OyEobj1hKG8scykpLmRvbmU7KWlmKHZvaWQgMCE9PShpPXQobi52YWx1ZSkpKXJldHVybiBpfX0sNTMxOihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig5NTY1KSxpPXIoOTMwNikscz1yKDg1NTEpLG89cigxNzY3KSxjPXIoODY0NiksbD1yKDk0NjIpLGg9cig5NTM5KSx1PXIoNjM5NSksZD1yKDY4NCksZj1yKDQ1NDkpLGc9IXUmJiFkKCJmbGF0TWFwIixmdW5jdGlvbigpe30pLHA9IXUmJiFnJiZmKCJmbGF0TWFwIixUeXBlRXJyb3IpLG09dXx8Z3x8cCxiPWwoZnVuY3Rpb24oKXtmb3IodmFyIGUsdCxyPXRoaXMuaXRlcmF0b3IsYT10aGlzLm1hcHBlcjs7KXtpZih0PXRoaXMuaW5uZXIpdHJ5e2lmKCEoZT1zKG4odC5uZXh0LHQuaXRlcmF0b3IpKSkuZG9uZSlyZXR1cm4gZS52YWx1ZTt0aGlzLmlubmVyPW51bGx9Y2F0Y2goZSl7aChyLCJ0aHJvdyIsZSl9ZT1zKG4odGhpcy5uZXh0LHIpKTtpZih0aGlzLmRvbmU9ISFlLmRvbmUpcmV0dXJuO3RyeXt0aGlzLmlubmVyPWMoYShlLnZhbHVlLHRoaXMuY291bnRlcisrKSwhMSl9Y2F0Y2goZSl7aChyLCJ0aHJvdyIsZSl9fX0pO2Eoe3RhcmdldDoiSXRlcmF0b3IiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOm19LHtmbGF0TWFwOmZ1bmN0aW9uIGZsYXRNYXAoZSl7cyh0aGlzKTt0cnl7aShlKX1jYXRjaChlKXtoKHRoaXMsInRocm93IixlKX1yZXR1cm4gcD9uKHAsdGhpcyxlKTpuZXcgYihvKHRoaXMpLHttYXBwZXI6ZSxpbm5lcjpudWxsfSl9fSl9LDYxNjooZSx0LHIpPT57dmFyIGE9cig5MDM5KTtlLmV4cG9ydHM9IWEoZnVuY3Rpb24oKXt2YXIgZT1mdW5jdGlvbigpe30uYmluZCgpO3JldHVybiJmdW5jdGlvbiIhPXR5cGVvZiBlfHxlLmhhc093blByb3BlcnR5KCJwcm90b3R5cGUiKX0pfSw2NTU6KGUsdCxyKT0+e3ZhciBhPXIoNjk1NSksbj1TdHJpbmc7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKCJTeW1ib2wiPT09YShlKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY29udmVydCBhIFN5bWJvbCB2YWx1ZSB0byBhIHN0cmluZyIpO3JldHVybiBuKGUpfX0sNjc5OihlLHQscik9Pnt2YXIgYT1yKDE2MjUpLG49VHlwZUVycm9yO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe2lmKGEodCxlKSlyZXR1cm4gZTt0aHJvdyBuZXcgbigiSW5jb3JyZWN0IGludm9jYXRpb24iKX19LDY4NDplPT57ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9ImZ1bmN0aW9uIj09dHlwZW9mIEl0ZXJhdG9yJiZJdGVyYXRvci5wcm90b3R5cGVbZV07aWYocil0cnl7ci5jYWxsKHtuZXh0Om51bGx9LHQpLm5leHQoKX1jYXRjaChlKXtyZXR1cm4hMH19fSw3NDE6ZT0+e3ZhciB0PU1hdGguY2VpbCxyPU1hdGguZmxvb3I7ZS5leHBvcnRzPU1hdGgudHJ1bmN8fGZ1bmN0aW9uIHRydW5jKGUpe3ZhciBhPStlO3JldHVybihhPjA/cjp0KShhKX19LDc1NzooZSx0LHIpPT57dmFyIGE9cig3NzUxKSxuPXIoNDkwMSksaT1yKDE2MjUpLHM9cig3MDQwKSxvPU9iamVjdDtlLmV4cG9ydHM9cz9mdW5jdGlvbihlKXtyZXR1cm4ic3ltYm9sIj09dHlwZW9mIGV9OmZ1bmN0aW9uKGUpe3ZhciB0PWEoIlN5bWJvbCIpO3JldHVybiBuKHQpJiZpKHQucHJvdG90eXBlLG8oZSkpfX0sODUxOihlLHQscik9Pnt2YXIgYT1yKDY5NTUpLG49cig1OTY2KSxpPXIoNDExNykscz1yKDYyNjkpLG89cig4MjI3KSgiaXRlcmF0b3IiKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYoIWkoZSkpcmV0dXJuIG4oZSxvKXx8bihlLCJAQGl0ZXJhdG9yIil8fHNbYShlKV19fSw5NDQ6ZT0+e3ZhciB0PVR5cGVFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7dmFyIHI9ZSYmZS5hbHBoYWJldDtpZih2b2lkIDA9PT1yfHwiYmFzZTY0Ij09PXJ8fCJiYXNlNjR1cmwiPT09cilyZXR1cm4gcnx8ImJhc2U2NCI7dGhyb3cgbmV3IHQoIkluY29ycmVjdCBgYWxwaGFiZXRgIG9wdGlvbiIpfX0sMTA3MjooZSx0LHIpPT57dmFyIGE9cigxODI4KSxuPXIoODcyNyk7ZS5leHBvcnRzPU9iamVjdC5rZXlzfHxmdW5jdGlvbiBrZXlzKGUpe3JldHVybiBhKGUsbil9fSwxMTAzOmU9PntlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7dHJ5e3JldHVybntlcnJvcjohMSx2YWx1ZTplKCl9fWNhdGNoKGUpe3JldHVybntlcnJvcjohMCx2YWx1ZTplfX19fSwxMTA4OihlLHQscik9Pnt2YXIgYT1yKDY5NTUpO2UuZXhwb3J0cz1mdW5jdGlvbihlKXt2YXIgdD1hKGUpO3JldHVybiJCaWdJbnQ2NEFycmF5Ij09PXR8fCJCaWdVaW50NjRBcnJheSI9PT10fX0sMTE0ODooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoOTU2NSksaT1yKDI2NTIpLHM9cig5MzA2KSxvPXIoODU1MSksYz1yKDE3NjcpLGw9cig5NTM5KSxoPXIoNDU0OSkoImV2ZXJ5IixUeXBlRXJyb3IpO2Eoe3RhcmdldDoiSXRlcmF0b3IiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOmh9LHtldmVyeTpmdW5jdGlvbiBldmVyeShlKXtvKHRoaXMpO3RyeXtzKGUpfWNhdGNoKGUpe2wodGhpcywidGhyb3ciLGUpfWlmKGgpcmV0dXJuIG4oaCx0aGlzLGUpO3ZhciB0PWModGhpcykscj0wO3JldHVybiFpKHQsZnVuY3Rpb24odCxhKXtpZighZSh0LHIrKykpcmV0dXJuIGEoKX0se0lTX1JFQ09SRDohMCxJTlRFUlJVUFRFRDohMH0pLnN0b3BwZWR9fSl9LDExODE6KGUsdCxyKT0+e3ZhciBhLG4saSxzPXIoODYyMiksbz1yKDQ1NzYpLGM9cigzNCksbD1yKDY2OTkpLGg9cig5Mjk3KSx1PXIoNzYyOSksZD1yKDYxMTkpLGY9cig0MjEpLGc9Ik9iamVjdCBhbHJlYWR5IGluaXRpYWxpemVkIixwPW8uVHlwZUVycm9yLG09by5XZWFrTWFwO2lmKHN8fHUuc3RhdGUpe3ZhciBiPXUuc3RhdGV8fCh1LnN0YXRlPW5ldyBtKTtiLmdldD1iLmdldDtiLmhhcz1iLmhhcztiLnNldD1iLnNldDthPWZ1bmN0aW9uKGUsdCl7aWYoYi5oYXMoZSkpdGhyb3cgbmV3IHAoZyk7dC5mYWNhZGU9ZTtiLnNldChlLHQpO3JldHVybiB0fTtuPWZ1bmN0aW9uKGUpe3JldHVybiBiLmdldChlKXx8e319O2k9ZnVuY3Rpb24oZSl7cmV0dXJuIGIuaGFzKGUpfX1lbHNle3ZhciB5PWQoInN0YXRlIik7Zlt5XT0hMDthPWZ1bmN0aW9uKGUsdCl7aWYoaChlLHkpKXRocm93IG5ldyBwKGcpO3QuZmFjYWRlPWU7bChlLHksdCk7cmV0dXJuIHR9O249ZnVuY3Rpb24oZSl7cmV0dXJuIGgoZSx5KT9lW3ldOnt9fTtpPWZ1bmN0aW9uKGUpe3JldHVybiBoKGUseSl9fWUuZXhwb3J0cz17c2V0OmEsZ2V0Om4saGFzOmksZW5mb3JjZTpmdW5jdGlvbihlKXtyZXR1cm4gaShlKT9uKGUpOmEoZSx7fSl9LGdldHRlckZvcjpmdW5jdGlvbihlKXtyZXR1cm4gZnVuY3Rpb24odCl7dmFyIHI7aWYoIWModCl8fChyPW4odCkpLnR5cGUhPT1lKXRocm93IG5ldyBwKCJJbmNvbXBhdGlibGUgcmVjZWl2ZXIsICIrZSsiIHJlcXVpcmVkIik7cmV0dXJuIHJ9fX19LDEyOTE6KGUsdCxyKT0+e3ZhciBhPXIoNzQxKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7dmFyIHQ9K2U7cmV0dXJuIHQhPXR8fDA9PT10PzA6YSh0KX19LDEzODU6KGUsdCxyKT0+e3ZhciBhPXIoOTUzOSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyKXtmb3IodmFyIG49ZS5sZW5ndGgtMTtuPj0wO24tLSlpZih2b2lkIDAhPT1lW25dKXRyeXtyPWEoZVtuXS5pdGVyYXRvcix0LHIpfWNhdGNoKGUpe3Q9InRocm93IjtyPWV9aWYoInRocm93Ij09PXQpdGhyb3cgcjtyZXR1cm4gcn19LDE1NDg6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDkwMzkpLGk9cig5NTE5KSxzPXIoNDIxNSksbz1hLnN0cnVjdHVyZWRDbG9uZTtlLmV4cG9ydHM9ISFvJiYhbihmdW5jdGlvbigpe2lmKCJERU5PIj09PXMmJmk+OTJ8fCJOT0RFIj09PXMmJmk+OTR8fCJCUk9XU0VSIj09PXMmJmk+OTcpcmV0dXJuITE7dmFyIGU9bmV3IEFycmF5QnVmZmVyKDgpLHQ9byhlLHt0cmFuc2ZlcjpbZV19KTtyZXR1cm4gMCE9PWUuYnl0ZUxlbmd0aHx8OCE9PXQuYnl0ZUxlbmd0aH0pfSwxNTQ5OihlLHQscik9PntyKDY2MzIpfSwxNjI1OihlLHQscik9Pnt2YXIgYT1yKDk1MDQpO2UuZXhwb3J0cz1hKHt9LmlzUHJvdG90eXBlT2YpfSwxNjg5OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig0NTc2KSxpPXIoODc0NSkscz1yKDc2ODApLG89cig2MDQzKSxjPXIoOTMwNiksbD1yKDExMDMpLGg9bi5Qcm9taXNlLHU9ITE7YSh7dGFyZ2V0OiJQcm9taXNlIixzdGF0OiEwLGZvcmNlZDohaHx8IWgudHJ5fHxsKGZ1bmN0aW9uKCl7aC50cnkoZnVuY3Rpb24oZSl7dT04PT09ZX0sOCl9KS5lcnJvcnx8IXV9LHt0cnk6ZnVuY3Rpb24oZSl7dmFyIHQ9YXJndW1lbnRzLmxlbmd0aD4xP3MoYXJndW1lbnRzLDEpOltdLHI9by5mKHRoaXMpLGE9bChmdW5jdGlvbigpe3JldHVybiBpKGMoZSksdm9pZCAwLHQpfSk7KGEuZXJyb3I/ci5yZWplY3Q6ci5yZXNvbHZlKShhLnZhbHVlKTtyZXR1cm4gci5wcm9taXNlfX0pfSwxNjk4OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig0MjA0KSxpPXIoOTgzNSk7YSh7dGFyZ2V0OiJTZXQiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOiFyKDQ5MTYpKCJ1bmlvbiIpfHwhaSgidW5pb24iKX0se3VuaW9uOm59KX0sMTcwMTooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoOTU2NSksaT1yKDkzMDYpLHM9cig4NTUxKSxvPXIoMTc2NyksYz1yKDk0NjIpLGw9cig2MzE5KSxoPXIoOTUzOSksdT1yKDY4NCksZD1yKDQ1NDkpLGY9cig2Mzk1KSxnPSFmJiYhdSgibWFwIixmdW5jdGlvbigpe30pLHA9IWYmJiFnJiZkKCJtYXAiLFR5cGVFcnJvciksbT1mfHxnfHxwLGI9YyhmdW5jdGlvbigpe3ZhciBlPXRoaXMuaXRlcmF0b3IsdD1zKG4odGhpcy5uZXh0LGUpKTtpZighKHRoaXMuZG9uZT0hIXQuZG9uZSkpcmV0dXJuIGwoZSx0aGlzLm1hcHBlcixbdC52YWx1ZSx0aGlzLmNvdW50ZXIrK10sITApfSk7YSh7dGFyZ2V0OiJJdGVyYXRvciIscHJvdG86ITAscmVhbDohMCxmb3JjZWQ6bX0se21hcDpmdW5jdGlvbiBtYXAoZSl7cyh0aGlzKTt0cnl7aShlKX1jYXRjaChlKXtoKHRoaXMsInRocm93IixlKX1yZXR1cm4gcD9uKHAsdGhpcyxlKTpuZXcgYihvKHRoaXMpLHttYXBwZXI6ZX0pfX0pfSwxNzY3OmU9PntlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7cmV0dXJue2l0ZXJhdG9yOmUsbmV4dDplLm5leHQsZG9uZTohMX19fSwxODA2OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig4NTUxKSxpPXIoMjY1Mikscz1yKDE3NjcpLG89W10ucHVzaDthKHt0YXJnZXQ6Ikl0ZXJhdG9yIixwcm90bzohMCxyZWFsOiEwfSx7dG9BcnJheTpmdW5jdGlvbiB0b0FycmF5KCl7dmFyIGU9W107aShzKG4odGhpcykpLG8se3RoYXQ6ZSxJU19SRUNPUkQ6ITB9KTtyZXR1cm4gZX19KX0sMTgyODooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPXIoOTI5NyksaT1yKDUzOTcpLHM9cig5NjE3KS5pbmRleE9mLG89cig0MjEpLGM9YShbXS5wdXNoKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXt2YXIgcixhPWkoZSksbD0wLGg9W107Zm9yKHIgaW4gYSkhbihvLHIpJiZuKGEscikmJmMoaCxyKTtmb3IoO3QubGVuZ3RoPmw7KW4oYSxyPXRbbCsrXSkmJih+cyhoLHIpfHxjKGgscikpO3JldHVybiBofX0sMjEwNjooZSx0LHIpPT57dmFyIGE9cigyODMpLG49cig0OTEzKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIpe3IuZ2V0JiZhKHIuZ2V0LHQse2dldHRlcjohMH0pO3Iuc2V0JiZhKHIuc2V0LHQse3NldHRlcjohMH0pO3JldHVybiBuLmYoZSx0LHIpfX0sMjE0MDooZSx0LHIpPT57dmFyIGE9e307YVtyKDgyMjcpKCJ0b1N0cmluZ1RhZyIpXT0ieiI7ZS5leHBvcnRzPSJbb2JqZWN0IHpdIj09PVN0cmluZyhhKX0sMjE5NTooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPWEoe30udG9TdHJpbmcpLGk9YSgiIi5zbGljZSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBpKG4oZSksOCwtMSl9fSwyMjExOihlLHQscik9Pnt2YXIgYT1yKDkwMzkpO2UuZXhwb3J0cz0hYShmdW5jdGlvbigpe2Z1bmN0aW9uIEYoKXt9Ri5wcm90b3R5cGUuY29uc3RydWN0b3I9bnVsbDtyZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBGKSE9PUYucHJvdG90eXBlfSl9LDIzMDM6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDk1MDQpLGk9YS5VaW50OEFycmF5LHM9YS5TeW50YXhFcnJvcixvPWEucGFyc2VJbnQsYz1NYXRoLm1pbixsPS9bXlxkYS1mXS9pLGg9bihsLmV4ZWMpLHU9bigiIi5zbGljZSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9ZS5sZW5ndGg7aWYociUyIT0wKXRocm93IG5ldyBzKCJTdHJpbmcgc2hvdWxkIGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGNoYXJhY3RlcnMiKTtmb3IodmFyIGE9dD9jKHQubGVuZ3RoLHIvMik6ci8yLG49dHx8bmV3IGkoYSksZD0wLGY9MDtmPGE7KXt2YXIgZz11KGUsZCxkKz0yKTtpZihoKGwsZykpdGhyb3cgbmV3IHMoIlN0cmluZyBzaG91bGQgb25seSBjb250YWluIGhleCBjaGFyYWN0ZXJzIik7bltmKytdPW8oZywxNil9cmV0dXJue2J5dGVzOm4scmVhZDpkfX19LDIzNjA6KGUsdCxyKT0+e3ZhciBhLG49cig4NTUxKSxpPXIoNjgwMSkscz1yKDg3MjcpLG89cig0MjEpLGM9cigzOTcpLGw9cig0MDU1KSxoPXIoNjExOSksdT0icHJvdG90eXBlIixkPSJzY3JpcHQiLGY9aCgiSUVfUFJPVE8iKSxFbXB0eUNvbnN0cnVjdG9yPWZ1bmN0aW9uKCl7fSxzY3JpcHRUYWc9ZnVuY3Rpb24oZSl7cmV0dXJuIjwiK2QrIj4iK2UrIjwvIitkKyI+In0sTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWD1mdW5jdGlvbihlKXtlLndyaXRlKHNjcmlwdFRhZygiIikpO2UuY2xvc2UoKTt2YXIgdD1lLnBhcmVudFdpbmRvdy5PYmplY3Q7ZT1udWxsO3JldHVybiB0fSxOdWxsUHJvdG9PYmplY3Q9ZnVuY3Rpb24oKXt0cnl7YT1uZXcgQWN0aXZlWE9iamVjdCgiaHRtbGZpbGUiKX1jYXRjaChlKXt9TnVsbFByb3RvT2JqZWN0PSJ1bmRlZmluZWQiIT10eXBlb2YgZG9jdW1lbnQ/ZG9jdW1lbnQuZG9tYWluJiZhP051bGxQcm90b09iamVjdFZpYUFjdGl2ZVgoYSk6ZnVuY3Rpb24oKXt2YXIgZSx0PWwoImlmcmFtZSIpLHI9ImphdmEiK2QrIjoiO3Quc3R5bGUuZGlzcGxheT0ibm9uZSI7Yy5hcHBlbmRDaGlsZCh0KTt0LnNyYz1TdHJpbmcocik7KGU9dC5jb250ZW50V2luZG93LmRvY3VtZW50KS5vcGVuKCk7ZS53cml0ZShzY3JpcHRUYWcoImRvY3VtZW50LkY9T2JqZWN0IikpO2UuY2xvc2UoKTtyZXR1cm4gZS5GfSgpOk51bGxQcm90b09iamVjdFZpYUFjdGl2ZVgoYSk7Zm9yKHZhciBlPXMubGVuZ3RoO2UtLTspZGVsZXRlIE51bGxQcm90b09iamVjdFt1XVtzW2VdXTtyZXR1cm4gTnVsbFByb3RvT2JqZWN0KCl9O29bZl09ITA7ZS5leHBvcnRzPU9iamVjdC5jcmVhdGV8fGZ1bmN0aW9uIGNyZWF0ZShlLHQpe3ZhciByO2lmKG51bGwhPT1lKXtFbXB0eUNvbnN0cnVjdG9yW3VdPW4oZSk7cj1uZXcgRW1wdHlDb25zdHJ1Y3RvcjtFbXB0eUNvbnN0cnVjdG9yW3VdPW51bGw7cltmXT1lfWVsc2Ugcj1OdWxsUHJvdG9PYmplY3QoKTtyZXR1cm4gdm9pZCAwPT09dD9yOmkuZihyLHQpfX0sMjQ3NTooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoODUyNyk7YSh7dGFyZ2V0OiJTZXQiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOiFyKDQ5MTYpKCJpc1N1cGVyc2V0T2YiLGZ1bmN0aW9uKGUpe3JldHVybiFlfSl9LHtpc1N1cGVyc2V0T2Y6bn0pfSwyNDg5OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig5NTY1KSxpPXIoOTMwNikscz1yKDg1NTEpLG89cigxNzY3KSxjPXIoOTQ2MiksbD1yKDYzMTkpLGg9cig2Mzk1KSx1PXIoOTUzOSksZD1yKDY4NCksZj1yKDQ1NDkpLGc9IWgmJiFkKCJmaWx0ZXIiLGZ1bmN0aW9uKCl7fSkscD0haCYmIWcmJmYoImZpbHRlciIsVHlwZUVycm9yKSxtPWh8fGd8fHAsYj1jKGZ1bmN0aW9uKCl7Zm9yKHZhciBlLHQscj10aGlzLml0ZXJhdG9yLGE9dGhpcy5wcmVkaWNhdGUsaT10aGlzLm5leHQ7Oyl7ZT1zKG4oaSxyKSk7aWYodGhpcy5kb25lPSEhZS5kb25lKXJldHVybjt0PWUudmFsdWU7aWYobChyLGEsW3QsdGhpcy5jb3VudGVyKytdLCEwKSlyZXR1cm4gdH19KTthKHt0YXJnZXQ6Ikl0ZXJhdG9yIixwcm90bzohMCxyZWFsOiEwLGZvcmNlZDptfSx7ZmlsdGVyOmZ1bmN0aW9uIGZpbHRlcihlKXtzKHRoaXMpO3RyeXtpKGUpfWNhdGNoKGUpe3UodGhpcywidGhyb3ciLGUpfXJldHVybiBwP24ocCx0aGlzLGUpOm5ldyBiKG8odGhpcykse3ByZWRpY2F0ZTplfSl9fSl9LDI1Mjk6ZT0+e2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe3JldHVybnt2YWx1ZTplLGRvbmU6dH19fSwyNjAzOihlLHQscik9Pnt2YXIgYT1yKDY1NSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIHZvaWQgMD09PWU/YXJndW1lbnRzLmxlbmd0aDwyPyIiOnQ6YShlKX19LDI2NTI6KGUsdCxyKT0+e3ZhciBhPXIoNjA4MCksbj1yKDk1NjUpLGk9cig4NTUxKSxzPXIoNjgyMyksbz1yKDQyMDkpLGM9cig2MTk4KSxsPXIoMTYyNSksaD1yKDgxKSx1PXIoODUxKSxkPXIoOTUzOSksZj1UeXBlRXJyb3IsUmVzdWx0PWZ1bmN0aW9uKGUsdCl7dGhpcy5zdG9wcGVkPWU7dGhpcy5yZXN1bHQ9dH0sZz1SZXN1bHQucHJvdG90eXBlO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQscil7dmFyIHAsbSxiLHksdyx4LFMsaz1yJiZyLnRoYXQsQz0hKCFyfHwhci5BU19FTlRSSUVTKSx2PSEoIXJ8fCFyLklTX1JFQ09SRCksVD0hKCFyfHwhci5JU19JVEVSQVRPUiksTz0hKCFyfHwhci5JTlRFUlJVUFRFRCksTT1hKHQsayksc3RvcD1mdW5jdGlvbihlKXtwJiZkKHAsIm5vcm1hbCIpO3JldHVybiBuZXcgUmVzdWx0KCEwLGUpfSxjYWxsRm49ZnVuY3Rpb24oZSl7aWYoQyl7aShlKTtyZXR1cm4gTz9NKGVbMF0sZVsxXSxzdG9wKTpNKGVbMF0sZVsxXSl9cmV0dXJuIE8/TShlLHN0b3ApOk0oZSl9O2lmKHYpcD1lLml0ZXJhdG9yO2Vsc2UgaWYoVClwPWU7ZWxzZXtpZighKG09dShlKSkpdGhyb3cgbmV3IGYocyhlKSsiIGlzIG5vdCBpdGVyYWJsZSIpO2lmKG8obSkpe2ZvcihiPTAseT1jKGUpO3k+YjtiKyspaWYoKHc9Y2FsbEZuKGVbYl0pKSYmbChnLHcpKXJldHVybiB3O3JldHVybiBuZXcgUmVzdWx0KCExKX1wPWgoZSxtKX14PXY/ZS5uZXh0OnAubmV4dDtmb3IoOyEoUz1uKHgscCkpLmRvbmU7KXt0cnl7dz1jYWxsRm4oUy52YWx1ZSl9Y2F0Y2goZSl7ZChwLCJ0aHJvdyIsZSl9aWYoIm9iamVjdCI9PXR5cGVvZiB3JiZ3JiZsKGcsdykpcmV0dXJuIHd9cmV0dXJuIG5ldyBSZXN1bHQoITEpfX0sMjc3NzooZSx0LHIpPT57dmFyIGE9cig5NTY1KSxuPXIoMzQpLGk9cig3NTcpLHM9cig1OTY2KSxvPXIoNDI3MCksYz1yKDgyMjcpLGw9VHlwZUVycm9yLGg9YygidG9QcmltaXRpdmUiKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXtpZighbihlKXx8aShlKSlyZXR1cm4gZTt2YXIgcixjPXMoZSxoKTtpZihjKXt2b2lkIDA9PT10JiYodD0iZGVmYXVsdCIpO3I9YShjLGUsdCk7aWYoIW4ocil8fGkocikpcmV0dXJuIHI7dGhyb3cgbmV3IGwoIkNhbid0IGNvbnZlcnQgb2JqZWN0IHRvIHByaW1pdGl2ZSB2YWx1ZSIpfXZvaWQgMD09PXQmJih0PSJudW1iZXIiKTtyZXR1cm4gbyhlLHQpfX0sMjc4NzooZSx0LHIpPT57dmFyIGE9cig5Mjk3KSxuPXIoNDkwMSksaT1yKDg5ODEpLHM9cig2MTE5KSxvPXIoMjIxMSksYz1zKCJJRV9QUk9UTyIpLGw9T2JqZWN0LGg9bC5wcm90b3R5cGU7ZS5leHBvcnRzPW8/bC5nZXRQcm90b3R5cGVPZjpmdW5jdGlvbihlKXt2YXIgdD1pKGUpO2lmKGEodCxjKSlyZXR1cm4gdFtjXTt2YXIgcj10LmNvbnN0cnVjdG9yO3JldHVybiBuKHIpJiZ0IGluc3RhbmNlb2Ygcj9yLnByb3RvdHlwZTp0IGluc3RhbmNlb2YgbD9oOm51bGx9fSwyNzk2OihlLHQscik9Pnt2YXIgYT1yKDkwMzkpLG49cig0OTAxKSxpPS8jfFwucHJvdG90eXBlXC4vLGlzRm9yY2VkPWZ1bmN0aW9uKGUsdCl7dmFyIHI9b1tzKGUpXTtyZXR1cm4gcj09PWx8fHIhPT1jJiYobih0KT9hKHQpOiEhdCl9LHM9aXNGb3JjZWQubm9ybWFsaXplPWZ1bmN0aW9uKGUpe3JldHVybiBTdHJpbmcoZSkucmVwbGFjZShpLCIuIikudG9Mb3dlckNhc2UoKX0sbz1pc0ZvcmNlZC5kYXRhPXt9LGM9aXNGb3JjZWQuTkFUSVZFPSJOIixsPWlzRm9yY2VkLlBPTFlGSUxMPSJQIjtlLmV4cG9ydHM9aXNGb3JjZWR9LDI4MDQ6ZT0+e3ZhciB0PSJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSIscj10KyIrLyIsYT10KyItXyIsaW52ZXJzZT1mdW5jdGlvbihlKXtmb3IodmFyIHQ9e30scj0wO3I8NjQ7cisrKXRbZS5jaGFyQXQocildPXI7cmV0dXJuIHR9O2UuZXhwb3J0cz17aTJjOnIsYzJpOmludmVyc2UociksaTJjVXJsOmEsYzJpVXJsOmludmVyc2UoYSl9fSwyODEyOmU9Pnt2YXIgdD1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUscil7aWYoZTxyKXRocm93IG5ldyB0KCJOb3QgZW5vdWdoIGFyZ3VtZW50cyIpO3JldHVybiBlfX0sMjgzOTooZSx0LHIpPT57dmFyIGE9cig0NTc2KS5uYXZpZ2F0b3Isbj1hJiZhLnVzZXJBZ2VudDtlLmV4cG9ydHM9bj9TdHJpbmcobik6IiJ9LDI5Njc6KGUsdCxyKT0+e3ZhciBhPXIoNjcwNiksbj1yKDM0KSxpPXIoNzc1MCkscz1yKDM1MDYpO2UuZXhwb3J0cz1PYmplY3Quc2V0UHJvdG90eXBlT2Z8fCgiX19wcm90b19fImlue30/ZnVuY3Rpb24oKXt2YXIgZSx0PSExLHI9e307dHJ5eyhlPWEoT2JqZWN0LnByb3RvdHlwZSwiX19wcm90b19fIiwic2V0IikpKHIsW10pO3Q9ciBpbnN0YW5jZW9mIEFycmF5fWNhdGNoKGUpe31yZXR1cm4gZnVuY3Rpb24gc2V0UHJvdG90eXBlT2YocixhKXtpKHIpO3MoYSk7aWYoIW4ocikpcmV0dXJuIHI7dD9lKHIsYSk6ci5fX3Byb3RvX189YTtyZXR1cm4gcn19KCk6dm9pZCAwKX0sMzA2ODooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoOTUwNCksaT1yKDI2NTIpLHM9UmFuZ2VFcnJvcixvPVR5cGVFcnJvcixjPTEvMCxsPU1hdGguYWJzLGg9TWF0aC5wb3csdT1uKFtdLnB1c2gpLGQ9aCgyLDEwMjMpLGY9aCgyLDUzKS0xLGc9TnVtYmVyLk1BWF9WQUxVRSxwPWgoMiw5NzEpLG09e30sYj17fSx5PXt9LHc9e30seD17fSx0d29zdW09ZnVuY3Rpb24oZSx0KXt2YXIgcj1lK3Q7cmV0dXJue2hpOnIsbG86dC0oci1lKX19O2Eoe3RhcmdldDoiTWF0aCIsc3RhdDohMH0se3N1bVByZWNpc2U6ZnVuY3Rpb24gc3VtUHJlY2lzZShlKXt2YXIgdD1bXSxyPTAsYT13O2koZSxmdW5jdGlvbihlKXtpZigrK3I+PWYpdGhyb3cgbmV3IHMoIk1heGltdW0gYWxsb3dlZCBpbmRleCBleGNlZWRlZCIpO2lmKCJudW1iZXIiIT10eXBlb2YgZSl0aHJvdyBuZXcgbygiVmFsdWUgaXMgbm90IGEgbnVtYmVyIik7aWYoYSE9PW0paWYoZSE9ZSlhPW07ZWxzZSBpZihlPT09YylhPWE9PT1iP206eTtlbHNlIGlmKGU9PT0tMS8wKWE9YT09PXk/bTpiO2Vsc2UgaWYoISgwPT09ZSYmMS9lIT09Y3x8YSE9PXcmJmEhPT14KSl7YT14O3UodCxlKX19KTtzd2l0Y2goYSl7Y2FzZSBtOnJldHVybiBOYU47Y2FzZSBiOnJldHVybi0xLzA7Y2FzZSB5OnJldHVybiBjO2Nhc2UgdzpyZXR1cm4tMH1mb3IodmFyIG4saCxTLGssQyx2LFQ9W10sTz0wLE09MDtNPHQubGVuZ3RoO00rKyl7bj10W01dO2Zvcih2YXIgRD0wLFI9MDtSPFQubGVuZ3RoO1IrKyl7aD1UW1JdO2lmKGwobik8bChoKSl7dj1uO249aDtoPXZ9az0oUz10d29zdW0obixoKSkuaGk7Qz1TLmxvO2lmKGwoayk9PT1jKXt2YXIgRT1rPT09Yz8xOi0xO08rPUU7aWYobChuPW4tRSpkLUUqZCk8bChoKSl7dj1uO249aDtoPXZ9az0oUz10d29zdW0obixoKSkuaGk7Qz1TLmxvfTAhPT1DJiYoVFtEKytdPUMpO249a31ULmxlbmd0aD1EOzAhPT1uJiZ1KFQsbil9dmFyIE49VC5sZW5ndGgtMTtrPTA7Qz0wO2lmKDAhPT1PKXt2YXIgXz1OPj0wP1RbTl06MDtOLS07aWYobChPKT4xfHxPPjAmJl8+MHx8TzwwJiZfPDApcmV0dXJuIE8+MD9jOi0xLzA7az0oUz10d29zdW0oTypkLF8vMikpLmhpO0M9Uy5sbztDKj0yO2lmKGwoMiprKT09PWMpcmV0dXJuIGs+MD9rPT09ZCYmQz09PS1wLzImJk4+PTAmJlRbTl08MD9nOmM6az09PS1kJiZDPT09cC8yJiZOPj0wJiZUW05dPjA/LWc6LTEvMDtpZigwIT09Qyl7VFsrK05dPUM7Qz0wfWsqPTJ9Zm9yKDtOPj0wOyl7az0oUz10d29zdW0oayxUW04tLV0pKS5oaTtpZigwIT09KEM9Uy5sbykpYnJlYWt9Tj49MCYmKEM8MCYmVFtOXTwwfHxDPjAmJlRbTl0+MCkmJihoPTIqQyk9PT0obj1rK2gpLWsmJihrPW4pO3JldHVybiBrfX0pfSwzMTY3OihlLHQscik9Pnt2YXIgYT1yKDQ5MDEpLG49cigzNCksaT1yKDI5NjcpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQscil7dmFyIHMsbztpJiZhKHM9dC5jb25zdHJ1Y3RvcikmJnMhPT1yJiZuKG89cy5wcm90b3R5cGUpJiZvIT09ci5wcm90b3R5cGUmJmkoZSxvKTtyZXR1cm4gZX19LDMyMzg6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDc4MTEpLGk9cig3Mzk0KSxzPWEuRGF0YVZpZXc7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKCFufHwwIT09aShlKSlyZXR1cm4hMTt0cnl7bmV3IHMoZSk7cmV0dXJuITF9Y2F0Y2goZSl7cmV0dXJuITB9fX0sMzM5MjooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPTAsaT1NYXRoLnJhbmRvbSgpLHM9YSgxLjEudG9TdHJpbmcpO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4iU3ltYm9sKCIrKHZvaWQgMD09PWU/IiI6ZSkrIilfIitzKCsrbitpLDM2KX19LDM0NDA6KGUsdCxyKT0+e3ZhciBhPXIoNzA4MCksbj1yKDQ0MDIpLGk9cig5Mjg2KSxzPXIoNTE3MCksbz1yKDM3ODkpLGM9cig4NDY5KSxsPXIoNTA3KSxoPW4uaGFzLHU9bi5yZW1vdmU7ZS5leHBvcnRzPWZ1bmN0aW9uIGRpZmZlcmVuY2UoZSl7dmFyIHQ9YSh0aGlzKSxyPW8oZSksbj1pKHQpO3ModCk8PXIuc2l6ZT9jKHQsZnVuY3Rpb24oZSl7ci5pbmNsdWRlcyhlKSYmdShuLGUpfSk6bChyLmdldEl0ZXJhdG9yKCksZnVuY3Rpb24oZSl7aChuLGUpJiZ1KG4sZSl9KTtyZXR1cm4gbn19LDM0NjM6ZT0+e3ZhciB0PVR5cGVFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYoInN0cmluZyI9PXR5cGVvZiBlKXJldHVybiBlO3Rocm93IG5ldyB0KCJBcmd1bWVudCBpcyBub3QgYSBzdHJpbmciKX19LDM1MDY6KGUsdCxyKT0+e3ZhciBhPXIoMzkyNSksbj1TdHJpbmcsaT1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKGEoZSkpcmV0dXJuIGU7dGhyb3cgbmV3IGkoIkNhbid0IHNldCAiK24oZSkrIiBhcyBhIHByb3RvdHlwZSIpfX0sMzU3OTooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoOTU2NSksaT1yKDI2NTIpLHM9cig5MzA2KSxvPXIoODU1MSksYz1yKDE3NjcpLGw9cig5NTM5KSxoPXIoNDU0OSkoInNvbWUiLFR5cGVFcnJvcik7YSh7dGFyZ2V0OiJJdGVyYXRvciIscHJvdG86ITAscmVhbDohMCxmb3JjZWQ6aH0se3NvbWU6ZnVuY3Rpb24gc29tZShlKXtvKHRoaXMpO3RyeXtzKGUpfWNhdGNoKGUpe2wodGhpcywidGhyb3ciLGUpfWlmKGgpcmV0dXJuIG4oaCx0aGlzLGUpO3ZhciB0PWModGhpcykscj0wO3JldHVybiBpKHQsZnVuY3Rpb24odCxhKXtpZihlKHQscisrKSlyZXR1cm4gYSgpfSx7SVNfUkVDT1JEOiEwLElOVEVSUlVQVEVEOiEwfSkuc3RvcHBlZH19KX0sMzYxMTooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNDU3NiksaT1yKDIxMDYpLHM9cigzNzI0KSxvPVR5cGVFcnJvcixjPU9iamVjdC5kZWZpbmVQcm9wZXJ0eSxsPW4uc2VsZiE9PW47dHJ5e2lmKHMpe3ZhciBoPU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iobiwic2VsZiIpOyFsJiZoJiZoLmdldCYmaC5lbnVtZXJhYmxlfHxpKG4sInNlbGYiLHtnZXQ6ZnVuY3Rpb24gc2VsZigpe3JldHVybiBufSxzZXQ6ZnVuY3Rpb24gc2VsZihlKXtpZih0aGlzIT09bil0aHJvdyBuZXcgbygiSWxsZWdhbCBpbnZvY2F0aW9uIik7YyhuLCJzZWxmIix7dmFsdWU6ZSx3cml0YWJsZTohMCxjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMH0pfSxjb25maWd1cmFibGU6ITAsZW51bWVyYWJsZTohMH0pfWVsc2UgYSh7Z2xvYmFsOiEwLHNpbXBsZTohMCxmb3JjZWQ6bH0se3NlbGY6bn0pfWNhdGNoKGUpe319LDM2NTA6KGUsdCxyKT0+e3ZhciBhPXIoNzA4MCksbj1yKDQ0MDIpLGk9cig5Mjg2KSxzPXIoMzc4OSksbz1yKDUwNyksYz1uLmFkZCxsPW4uaGFzLGg9bi5yZW1vdmU7ZS5leHBvcnRzPWZ1bmN0aW9uIHN5bW1ldHJpY0RpZmZlcmVuY2UoZSl7dmFyIHQ9YSh0aGlzKSxyPXMoZSkuZ2V0SXRlcmF0b3IoKSxuPWkodCk7byhyLGZ1bmN0aW9uKGUpe2wodCxlKT9oKG4sZSk6YyhuLGUpfSk7cmV0dXJuIG59fSwzNzA2OihlLHQscik9Pnt2YXIgYT1yKDk1MDQpLG49cig0OTAxKSxpPXIoNzYyOSkscz1hKEZ1bmN0aW9uLnRvU3RyaW5nKTtuKGkuaW5zcGVjdFNvdXJjZSl8fChpLmluc3BlY3RTb3VyY2U9ZnVuY3Rpb24oZSl7cmV0dXJuIHMoZSl9KTtlLmV4cG9ydHM9aS5pbnNwZWN0U291cmNlfSwzNzE3OihlLHQpPT57dC5mPU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHN9LDM3MjQ6KGUsdCxyKT0+e3ZhciBhPXIoOTAzOSk7ZS5leHBvcnRzPSFhKGZ1bmN0aW9uKCl7cmV0dXJuIDchPT1PYmplY3QuZGVmaW5lUHJvcGVydHkoe30sMSx7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIDd9fSlbMV19KX0sMzc4OTooZSx0LHIpPT57dmFyIGE9cig5MzA2KSxuPXIoODU1MSksaT1yKDk1NjUpLHM9cigxMjkxKSxvPXIoMTc2NyksYz0iSW52YWxpZCBzaXplIixsPVJhbmdlRXJyb3IsaD1UeXBlRXJyb3IsdT1NYXRoLm1heCxTZXRSZWNvcmQ9ZnVuY3Rpb24oZSx0KXt0aGlzLnNldD1lO3RoaXMuc2l6ZT11KHQsMCk7dGhpcy5oYXM9YShlLmhhcyk7dGhpcy5rZXlzPWEoZS5rZXlzKX07U2V0UmVjb3JkLnByb3RvdHlwZT17Z2V0SXRlcmF0b3I6ZnVuY3Rpb24oKXtyZXR1cm4gbyhuKGkodGhpcy5rZXlzLHRoaXMuc2V0KSkpfSxpbmNsdWRlczpmdW5jdGlvbihlKXtyZXR1cm4gaSh0aGlzLmhhcyx0aGlzLnNldCxlKX19O2UuZXhwb3J0cz1mdW5jdGlvbihlKXtuKGUpO3ZhciB0PStlLnNpemU7aWYodCE9dCl0aHJvdyBuZXcgaChjKTt2YXIgcj1zKHQpO2lmKHI8MCl0aHJvdyBuZXcgbChjKTtyZXR1cm4gbmV3IFNldFJlY29yZChlLHIpfX0sMzgzODooZSx0LHIpPT57dmFyIGE9cig3MDgwKSxuPXIoNTE3MCksaT1yKDg0NjkpLHM9cigzNzg5KTtlLmV4cG9ydHM9ZnVuY3Rpb24gaXNTdWJzZXRPZihlKXt2YXIgdD1hKHRoaXMpLHI9cyhlKTtyZXR1cm4hKG4odCk+ci5zaXplKSYmITEhPT1pKHQsZnVuY3Rpb24oZSl7aWYoIXIuaW5jbHVkZXMoZSkpcmV0dXJuITF9LCEwKX19LDM4NTM6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDQ0NDkpO2Eoe3RhcmdldDoiU2V0Iixwcm90bzohMCxyZWFsOiEwLGZvcmNlZDohcig0OTE2KSgiaXNEaXNqb2ludEZyb20iLGZ1bmN0aW9uKGUpe3JldHVybiFlfSl9LHtpc0Rpc2pvaW50RnJvbTpufSl9LDM5MjU6KGUsdCxyKT0+e3ZhciBhPXIoMzQpO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4gYShlKXx8bnVsbD09PWV9fSwzOTcyOihlLHQscik9Pnt2YXIgYT1yKDM0KSxuPVN0cmluZyxpPVR5cGVFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYodm9pZCAwPT09ZXx8YShlKSlyZXR1cm4gZTt0aHJvdyBuZXcgaShuKGUpKyIgaXMgbm90IGFuIG9iamVjdCBvciB1bmRlZmluZWQiKX19LDQwNTU6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDM0KSxpPWEuZG9jdW1lbnQscz1uKGkpJiZuKGkuY3JlYXRlRWxlbWVudCk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBzP2kuY3JlYXRlRWxlbWVudChlKTp7fX19LDQxMTQ6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDg5ODEpLGk9cig2MTk4KSxzPXIoNDUyNyksbz1yKDY4MzcpO2Eoe3RhcmdldDoiQXJyYXkiLHByb3RvOiEwLGFyaXR5OjEsZm9yY2VkOnIoOTAzOSkoZnVuY3Rpb24oKXtyZXR1cm4gNDI5NDk2NzI5NyE9PVtdLnB1c2guY2FsbCh7bGVuZ3RoOjQyOTQ5NjcyOTZ9LDEpfSl8fCFmdW5jdGlvbigpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkoW10sImxlbmd0aCIse3dyaXRhYmxlOiExfSkucHVzaCgpfWNhdGNoKGUpe3JldHVybiBlIGluc3RhbmNlb2YgVHlwZUVycm9yfX0oKX0se3B1c2g6ZnVuY3Rpb24gcHVzaChlKXt2YXIgdD1uKHRoaXMpLHI9aSh0KSxhPWFyZ3VtZW50cy5sZW5ndGg7byhyK2EpO2Zvcih2YXIgYz0wO2M8YTtjKyspe3Rbcl09YXJndW1lbnRzW2NdO3IrK31zKHQscik7cmV0dXJuIHJ9fSl9LDQxMTc6ZT0+e2UuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4gbnVsbD09ZX19LDQxNTQ6KGUsdCxyKT0+e3ZhciBhPXIoNjk1NSksbj1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKCJVaW50OEFycmF5Ij09PWEoZSkpcmV0dXJuIGU7dGhyb3cgbmV3IG4oIkFyZ3VtZW50IGlzIG5vdCBhbiBVaW50OEFycmF5Iil9fSw0MjA0OihlLHQscik9Pnt2YXIgYT1yKDcwODApLG49cig0NDAyKS5hZGQsaT1yKDkyODYpLHM9cigzNzg5KSxvPXIoNTA3KTtlLmV4cG9ydHM9ZnVuY3Rpb24gdW5pb24oZSl7dmFyIHQ9YSh0aGlzKSxyPXMoZSkuZ2V0SXRlcmF0b3IoKSxjPWkodCk7byhyLGZ1bmN0aW9uKGUpe24oYyxlKX0pO3JldHVybiBjfX0sNDIwOTooZSx0LHIpPT57dmFyIGE9cig4MjI3KSxuPXIoNjI2OSksaT1hKCJpdGVyYXRvciIpLHM9QXJyYXkucHJvdG90eXBlO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4gdm9pZCAwIT09ZSYmKG4uQXJyYXk9PT1lfHxzW2ldPT09ZSl9fSw0MjE1OihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cigyODM5KSxpPXIoMjE5NSksdXNlckFnZW50U3RhcnRzV2l0aD1mdW5jdGlvbihlKXtyZXR1cm4gbi5zbGljZSgwLGUubGVuZ3RoKT09PWV9O2UuZXhwb3J0cz11c2VyQWdlbnRTdGFydHNXaXRoKCJCdW4vIik/IkJVTiI6dXNlckFnZW50U3RhcnRzV2l0aCgiQ2xvdWRmbGFyZS1Xb3JrZXJzIik/IkNMT1VERkxBUkUiOnVzZXJBZ2VudFN0YXJ0c1dpdGgoIkRlbm8vIik/IkRFTk8iOnVzZXJBZ2VudFN0YXJ0c1dpdGgoIk5vZGUuanMvIik/Ik5PREUiOmEuQnVuJiYic3RyaW5nIj09dHlwZW9mIEJ1bi52ZXJzaW9uPyJCVU4iOmEuRGVubyYmIm9iamVjdCI9PXR5cGVvZiBEZW5vLnZlcnNpb24/IkRFTk8iOiJwcm9jZXNzIj09PWkoYS5wcm9jZXNzKT8iTk9ERSI6YS53aW5kb3cmJmEuZG9jdW1lbnQ/IkJST1dTRVIiOiJSRVNUIn0sNDIyNjooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNDU3NiksaT1yKDM0NjMpLHM9cig0MTU0KSxvPXIoNTE2OSksYz1yKDIzMDMpO24uVWludDhBcnJheSYmYSh7dGFyZ2V0OiJVaW50OEFycmF5Iixwcm90bzohMH0se3NldEZyb21IZXg6ZnVuY3Rpb24gc2V0RnJvbUhleChlKXtzKHRoaXMpO2koZSk7byh0aGlzLmJ1ZmZlcik7dmFyIHQ9YyhlLHRoaXMpLnJlYWQ7cmV0dXJue3JlYWQ6dCx3cml0dGVuOnQvMn19fSl9LDQyMzU6KGUsdCxyKT0+e3IoMzA2OCl9LDQyNzA6KGUsdCxyKT0+e3ZhciBhPXIoOTU2NSksbj1yKDQ5MDEpLGk9cigzNCkscz1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7dmFyIHIsbztpZigic3RyaW5nIj09PXQmJm4ocj1lLnRvU3RyaW5nKSYmIWkobz1hKHIsZSkpKXJldHVybiBvO2lmKG4ocj1lLnZhbHVlT2YpJiYhaShvPWEocixlKSkpcmV0dXJuIG87aWYoInN0cmluZyIhPT10JiZuKHI9ZS50b1N0cmluZykmJiFpKG89YShyLGUpKSlyZXR1cm4gbzt0aHJvdyBuZXcgcygiQ2FuJ3QgY29udmVydCBvYmplY3QgdG8gcHJpbWl0aXZlIHZhbHVlIil9fSw0Mzc2OihlLHQscik9Pnt2YXIgYT1yKDIxOTUpO2UuZXhwb3J0cz1BcnJheS5pc0FycmF5fHxmdW5jdGlvbiBpc0FycmF5KGUpe3JldHVybiJBcnJheSI9PT1hKGUpfX0sNDQwMjooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPVNldC5wcm90b3R5cGU7ZS5leHBvcnRzPXtTZXQsYWRkOmEobi5hZGQpLGhhczphKG4uaGFzKSxyZW1vdmU6YShuLmRlbGV0ZSkscHJvdG86bn19LDQ0NDk6KGUsdCxyKT0+e3ZhciBhPXIoNzA4MCksbj1yKDQ0MDIpLmhhcyxpPXIoNTE3MCkscz1yKDM3ODkpLG89cig4NDY5KSxjPXIoNTA3KSxsPXIoOTUzOSk7ZS5leHBvcnRzPWZ1bmN0aW9uIGlzRGlzam9pbnRGcm9tKGUpe3ZhciB0PWEodGhpcykscj1zKGUpO2lmKGkodCk8PXIuc2l6ZSlyZXR1cm4hMSE9PW8odCxmdW5jdGlvbihlKXtpZihyLmluY2x1ZGVzKGUpKXJldHVybiExfSwhMCk7dmFyIGg9ci5nZXRJdGVyYXRvcigpO3JldHVybiExIT09YyhoLGZ1bmN0aW9uKGUpe2lmKG4odCxlKSlyZXR1cm4gbChoLCJub3JtYWwiLCExKX0pfX0sNDQ4MzooZSx0LHIpPT57dmFyIGEsbixpLHMsbz1yKDQ1NzYpLGM9cig5NDI5KSxsPXIoMTU0OCksaD1vLnN0cnVjdHVyZWRDbG9uZSx1PW8uQXJyYXlCdWZmZXIsZD1vLk1lc3NhZ2VDaGFubmVsLGY9ITE7aWYobClmPWZ1bmN0aW9uKGUpe2goZSx7dHJhbnNmZXI6W2VdfSl9O2Vsc2UgaWYodSl0cnl7ZHx8KGE9Yygid29ya2VyX3RocmVhZHMiKSkmJihkPWEuTWVzc2FnZUNoYW5uZWwpO2lmKGQpe249bmV3IGQ7aT1uZXcgdSgyKTtzPWZ1bmN0aW9uKGUpe24ucG9ydDEucG9zdE1lc3NhZ2UobnVsbCxbZV0pfTtpZigyPT09aS5ieXRlTGVuZ3RoKXtzKGkpOzA9PT1pLmJ5dGVMZW5ndGgmJihmPXMpfX19Y2F0Y2goZSl7fWUuZXhwb3J0cz1mfSw0NDk1OihlLHQscik9Pnt2YXIgYT1yKDk1MTkpLG49cig5MDM5KSxpPXIoNDU3NikuU3RyaW5nO2UuZXhwb3J0cz0hIU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMmJiFuKGZ1bmN0aW9uKCl7dmFyIGU9U3ltYm9sKCJzeW1ib2wgZGV0ZWN0aW9uIik7cmV0dXJuIWkoZSl8fCEoT2JqZWN0KGUpaW5zdGFuY2VvZiBTeW1ib2wpfHwhU3ltYm9sLnNoYW0mJmEmJmE8NDF9KX0sNDUyNzooZSx0LHIpPT57dmFyIGE9cigzNzI0KSxuPXIoNDM3NiksaT1UeXBlRXJyb3Iscz1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLG89YSYmIWZ1bmN0aW9uKCl7aWYodm9pZCAwIT09dGhpcylyZXR1cm4hMDt0cnl7T2JqZWN0LmRlZmluZVByb3BlcnR5KFtdLCJsZW5ndGgiLHt3cml0YWJsZTohMX0pLmxlbmd0aD0xfWNhdGNoKGUpe3JldHVybiBlIGluc3RhbmNlb2YgVHlwZUVycm9yfX0oKTtlLmV4cG9ydHM9bz9mdW5jdGlvbihlLHQpe2lmKG4oZSkmJiFzKGUsImxlbmd0aCIpLndyaXRhYmxlKXRocm93IG5ldyBpKCJDYW5ub3Qgc2V0IHJlYWQgb25seSAubGVuZ3RoIik7cmV0dXJuIGUubGVuZ3RoPXR9OmZ1bmN0aW9uKGUsdCl7cmV0dXJuIGUubGVuZ3RoPXR9fSw0NTQ5OihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe3ZhciByPWEuSXRlcmF0b3Isbj1yJiZyLnByb3RvdHlwZSxpPW4mJm5bZV0scz0hMTtpZihpKXRyeXtpLmNhbGwoe25leHQ6ZnVuY3Rpb24oKXtyZXR1cm57ZG9uZTohMH19LHJldHVybjpmdW5jdGlvbigpe3M9ITB9fSwtMSl9Y2F0Y2goZSl7ZSBpbnN0YW5jZW9mIHR8fChzPSExKX1pZighcylyZXR1cm4gaX19LDQ1NzY6ZnVuY3Rpb24oZSl7dmFyIGNoZWNrPWZ1bmN0aW9uKGUpe3JldHVybiBlJiZlLk1hdGg9PT1NYXRoJiZlfTtlLmV4cG9ydHM9Y2hlY2soIm9iamVjdCI9PXR5cGVvZiBnbG9iYWxUaGlzJiZnbG9iYWxUaGlzKXx8Y2hlY2soIm9iamVjdCI9PXR5cGVvZiB3aW5kb3cmJndpbmRvdyl8fGNoZWNrKCJvYmplY3QiPT10eXBlb2Ygc2VsZiYmc2VsZil8fGNoZWNrKCJvYmplY3QiPT10eXBlb2YgZ2xvYmFsJiZnbG9iYWwpfHxjaGVjaygib2JqZWN0Ij09dHlwZW9mIHRoaXMmJnRoaXMpfHxmdW5jdGlvbigpe3JldHVybiB0aGlzfSgpfHxGdW5jdGlvbigicmV0dXJuIHRoaXMiKSgpfSw0NjAzOihlLHQscik9Pnt2YXIgYT1yKDY4NDApLG49cig5NTA0KSxpPXIoNjU1KSxzPXIoMjgxMiksbz1VUkxTZWFyY2hQYXJhbXMsYz1vLnByb3RvdHlwZSxsPW4oYy5hcHBlbmQpLGg9bihjLmRlbGV0ZSksdT1uKGMuZm9yRWFjaCksZD1uKFtdLnB1c2gpLGY9bmV3IG8oImE9MSZhPTImYj0zIik7Zi5kZWxldGUoImEiLDEpO2YuZGVsZXRlKCJiIix2b2lkIDApO2YrIiIhPSJhPTIiJiZhKGMsImRlbGV0ZSIsZnVuY3Rpb24oZSl7dmFyIHQ9YXJndW1lbnRzLmxlbmd0aCxyPXQ8Mj92b2lkIDA6YXJndW1lbnRzWzFdO2lmKHQmJnZvaWQgMD09PXIpcmV0dXJuIGgodGhpcyxlKTt2YXIgYT1bXTt1KHRoaXMsZnVuY3Rpb24oZSx0KXtkKGEse2tleTp0LHZhbHVlOmV9KX0pO3ModCwxKTtmb3IodmFyIG4sbz1pKGUpLGM9aShyKSxmPTAsZz0wLHA9ITEsbT1hLmxlbmd0aDtmPG07KXtuPWFbZisrXTtpZihwfHxuLmtleT09PW8pe3A9ITA7aCh0aGlzLG4ua2V5KX1lbHNlIGcrK31mb3IoO2c8bTspKG49YVtnKytdKS5rZXk9PT1vJiZuLnZhbHVlPT09Y3x8bCh0aGlzLG4ua2V5LG4udmFsdWUpfSx7ZW51bWVyYWJsZTohMCx1bnNhZmU6ITB9KX0sNDYyODooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNjA0Myk7YSh7dGFyZ2V0OiJQcm9taXNlIixzdGF0OiEwfSx7d2l0aFJlc29sdmVyczpmdW5jdGlvbiB3aXRoUmVzb2x2ZXJzKCl7dmFyIGU9bi5mKHRoaXMpO3JldHVybntwcm9taXNlOmUucHJvbWlzZSxyZXNvbHZlOmUucmVzb2x2ZSxyZWplY3Q6ZS5yZWplY3R9fX0pfSw0NjQ0OihlLHQscik9Pnt2YXIgYSxuLGkscz1yKDc4MTEpLG89cigzNzI0KSxjPXIoNDU3NiksbD1yKDQ5MDEpLGg9cigzNCksdT1yKDkyOTcpLGQ9cig2OTU1KSxmPXIoNjgyMyksZz1yKDY2OTkpLHA9cig2ODQwKSxtPXIoMjEwNiksYj1yKDE2MjUpLHk9cigyNzg3KSx3PXIoMjk2NykseD1yKDgyMjcpLFM9cigzMzkyKSxrPXIoMTE4MSksQz1rLmVuZm9yY2Usdj1rLmdldCxUPWMuSW50OEFycmF5LE89VCYmVC5wcm90b3R5cGUsTT1jLlVpbnQ4Q2xhbXBlZEFycmF5LEQ9TSYmTS5wcm90b3R5cGUsUj1UJiZ5KFQpLEU9TyYmeShPKSxOPU9iamVjdC5wcm90b3R5cGUsXz1jLlR5cGVFcnJvcixMPXgoInRvU3RyaW5nVGFnIiksaj1TKCJUWVBFRF9BUlJBWV9UQUciKSxVPSJUeXBlZEFycmF5Q29uc3RydWN0b3IiLHE9cyYmISF3JiYiT3BlcmEiIT09ZChjLm9wZXJhKSxYPSExLEg9e0ludDhBcnJheToxLFVpbnQ4QXJyYXk6MSxVaW50OENsYW1wZWRBcnJheToxLEludDE2QXJyYXk6MixVaW50MTZBcnJheToyLEludDMyQXJyYXk6NCxVaW50MzJBcnJheTo0LEZsb2F0MzJBcnJheTo0LEZsb2F0NjRBcnJheTo4fSxXPXtCaWdJbnQ2NEFycmF5OjgsQmlnVWludDY0QXJyYXk6OH0sZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yPWZ1bmN0aW9uKGUpe3ZhciB0PXkoZSk7aWYoaCh0KSl7dmFyIHI9dih0KTtyZXR1cm4gciYmdShyLFUpP3JbVV06Z2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yKHQpfX0saXNUeXBlZEFycmF5PWZ1bmN0aW9uKGUpe2lmKCFoKGUpKXJldHVybiExO3ZhciB0PWQoZSk7cmV0dXJuIHUoSCx0KXx8dShXLHQpfTtmb3IoYSBpbiBIKShpPShuPWNbYV0pJiZuLnByb3RvdHlwZSk/QyhpKVtVXT1uOnE9ITE7Zm9yKGEgaW4gVykoaT0obj1jW2FdKSYmbi5wcm90b3R5cGUpJiYoQyhpKVtVXT1uKTtpZighcXx8IWwoUil8fFI9PT1GdW5jdGlvbi5wcm90b3R5cGUpe1I9ZnVuY3Rpb24gVHlwZWRBcnJheSgpe3Rocm93IG5ldyBfKCJJbmNvcnJlY3QgaW52b2NhdGlvbiIpfTtpZihxKWZvcihhIGluIEgpY1thXSYmdyhjW2FdLFIpfWlmKCFxfHwhRXx8RT09PU4pe0U9Ui5wcm90b3R5cGU7aWYocSlmb3IoYSBpbiBIKWNbYV0mJncoY1thXS5wcm90b3R5cGUsRSl9cSYmeShEKSE9PUUmJncoRCxFKTtpZihvJiYhdShFLEwpKXtYPSEwO20oRSxMLHtjb25maWd1cmFibGU6ITAsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIGgodGhpcyk/dGhpc1tqXTp2b2lkIDB9fSk7Zm9yKGEgaW4gSCljW2FdJiZnKGNbYV0saixhKX1lLmV4cG9ydHM9e05BVElWRV9BUlJBWV9CVUZGRVJfVklFV1M6cSxUWVBFRF9BUlJBWV9UQUc6WCYmaixhVHlwZWRBcnJheTpmdW5jdGlvbihlKXtpZihpc1R5cGVkQXJyYXkoZSkpcmV0dXJuIGU7dGhyb3cgbmV3IF8oIlRhcmdldCBpcyBub3QgYSB0eXBlZCBhcnJheSIpfSxhVHlwZWRBcnJheUNvbnN0cnVjdG9yOmZ1bmN0aW9uKGUpe2lmKGwoZSkmJighd3x8YihSLGUpKSlyZXR1cm4gZTt0aHJvdyBuZXcgXyhmKGUpKyIgaXMgbm90IGEgdHlwZWQgYXJyYXkgY29uc3RydWN0b3IiKX0sZXhwb3J0VHlwZWRBcnJheU1ldGhvZDpmdW5jdGlvbihlLHQscixhKXtpZihvKXtpZihyKWZvcih2YXIgbiBpbiBIKXt2YXIgaT1jW25dO2lmKGkmJnUoaS5wcm90b3R5cGUsZSkpdHJ5e2RlbGV0ZSBpLnByb3RvdHlwZVtlXX1jYXRjaChyKXt0cnl7aS5wcm90b3R5cGVbZV09dH1jYXRjaChlKXt9fX1FW2VdJiYhcnx8cChFLGUscj90OnEmJk9bZV18fHQsYSl9fSxleHBvcnRUeXBlZEFycmF5U3RhdGljTWV0aG9kOmZ1bmN0aW9uKGUsdCxyKXt2YXIgYSxuO2lmKG8pe2lmKHcpe2lmKHIpZm9yKGEgaW4gSClpZigobj1jW2FdKSYmdShuLGUpKXRyeXtkZWxldGUgbltlXX1jYXRjaChlKXt9aWYoUltlXSYmIXIpcmV0dXJuO3RyeXtyZXR1cm4gcChSLGUscj90OnEmJlJbZV18fHQpfWNhdGNoKGUpe319Zm9yKGEgaW4gSCkhKG49Y1thXSl8fG5bZV0mJiFyfHxwKG4sZSx0KX19LGdldFR5cGVkQXJyYXlDb25zdHJ1Y3Rvcixpc1ZpZXc6ZnVuY3Rpb24gaXNWaWV3KGUpe2lmKCFoKGUpKXJldHVybiExO3ZhciB0PWQoZSk7cmV0dXJuIkRhdGFWaWV3Ij09PXR8fHUoSCx0KXx8dShXLHQpfSxpc1R5cGVkQXJyYXksVHlwZWRBcnJheTpSLFR5cGVkQXJyYXlQcm90b3R5cGU6RX19LDQ2NTk6KGUsdCxyKT0+e3ZhciBhPXIoMzcyNCksbj1yKDQ5MTMpLGk9cig2OTgwKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIpe2E/bi5mKGUsdCxpKDAscikpOmVbdF09cn19LDQ5MDE6ZT0+e3ZhciB0PSJvYmplY3QiPT10eXBlb2YgZG9jdW1lbnQmJmRvY3VtZW50LmFsbDtlLmV4cG9ydHM9dm9pZCAwPT09dCYmdm9pZCAwIT09dD9mdW5jdGlvbihlKXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgZXx8ZT09PXR9OmZ1bmN0aW9uKGUpe3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiBlfX0sNDkxMzooZSx0LHIpPT57dmFyIGE9cigzNzI0KSxuPXIoNTkxNyksaT1yKDg2ODYpLHM9cig4NTUxKSxvPXIoNjk2OSksYz1UeXBlRXJyb3IsbD1PYmplY3QuZGVmaW5lUHJvcGVydHksaD1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLHU9ImVudW1lcmFibGUiLGQ9ImNvbmZpZ3VyYWJsZSIsZj0id3JpdGFibGUiO3QuZj1hP2k/ZnVuY3Rpb24gZGVmaW5lUHJvcGVydHkoZSx0LHIpe3MoZSk7dD1vKHQpO3Mocik7aWYoImZ1bmN0aW9uIj09dHlwZW9mIGUmJiJwcm90b3R5cGUiPT09dCYmInZhbHVlImluIHImJmYgaW4gciYmIXJbZl0pe3ZhciBhPWgoZSx0KTtpZihhJiZhW2ZdKXtlW3RdPXIudmFsdWU7cj17Y29uZmlndXJhYmxlOmQgaW4gcj9yW2RdOmFbZF0sZW51bWVyYWJsZTp1IGluIHI/clt1XTphW3VdLHdyaXRhYmxlOiExfX19cmV0dXJuIGwoZSx0LHIpfTpsOmZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KGUsdCxyKXtzKGUpO3Q9byh0KTtzKHIpO2lmKG4pdHJ5e3JldHVybiBsKGUsdCxyKX1jYXRjaChlKXt9aWYoImdldCJpbiByfHwic2V0ImluIHIpdGhyb3cgbmV3IGMoIkFjY2Vzc29ycyBub3Qgc3VwcG9ydGVkIik7InZhbHVlImluIHImJihlW3RdPXIudmFsdWUpO3JldHVybiBlfX0sNDkxNjooZSx0LHIpPT57dmFyIGE9cig3NzUxKSxjcmVhdGVTZXRMaWtlPWZ1bmN0aW9uKGUpe3JldHVybntzaXplOmUsaGFzOmZ1bmN0aW9uKCl7cmV0dXJuITF9LGtleXM6ZnVuY3Rpb24oKXtyZXR1cm57bmV4dDpmdW5jdGlvbigpe3JldHVybntkb25lOiEwfX19fX19LGNyZWF0ZVNldExpa2VXaXRoSW5maW5pdHlTaXplPWZ1bmN0aW9uKGUpe3JldHVybntzaXplOmUsaGFzOmZ1bmN0aW9uKCl7cmV0dXJuITB9LGtleXM6ZnVuY3Rpb24oKXt0aHJvdyBuZXcgRXJyb3IoImUiKX19fTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXt2YXIgcj1hKCJTZXQiKTt0cnl7KG5ldyByKVtlXShjcmVhdGVTZXRMaWtlKDApKTt0cnl7KG5ldyByKVtlXShjcmVhdGVTZXRMaWtlKC0xKSk7cmV0dXJuITF9Y2F0Y2goYSl7aWYoIXQpcmV0dXJuITA7dHJ5eyhuZXcgcilbZV0oY3JlYXRlU2V0TGlrZVdpdGhJbmZpbml0eVNpemUoLTEvMCkpO3JldHVybiExfWNhdGNoKGEpe3ZhciBuPW5ldyByO24uYWRkKDEpO24uYWRkKDIpO3JldHVybiB0KG5bZV0oY3JlYXRlU2V0TGlrZVdpdGhJbmZpbml0eVNpemUoMS8wKSkpfX19Y2F0Y2goZSl7cmV0dXJuITF9fX0sNDk3OTooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNDU3NiksaT1yKDc3NTEpLHM9cig2OTgwKSxvPXIoNDkxMykuZixjPXIoOTI5NyksbD1yKDY3OSksaD1yKDMxNjcpLHU9cigyNjAzKSxkPXIoNTAwMiksZj1yKDg1NzQpLGc9cigzNzI0KSxwPXIoNjM5NSksbT0iRE9NRXhjZXB0aW9uIixiPWkoIkVycm9yIikseT1pKG0pLHc9ZnVuY3Rpb24gRE9NRXhjZXB0aW9uKCl7bCh0aGlzLHgpO3ZhciBlPWFyZ3VtZW50cy5sZW5ndGgsdD11KGU8MT92b2lkIDA6YXJndW1lbnRzWzBdKSxyPXUoZTwyP3ZvaWQgMDphcmd1bWVudHNbMV0sIkVycm9yIiksYT1uZXcgeSh0LHIpLG49bmV3IGIodCk7bi5uYW1lPW07byhhLCJzdGFjayIscygxLGYobi5zdGFjaywxKSkpO2goYSx0aGlzLHcpO3JldHVybiBhfSx4PXcucHJvdG90eXBlPXkucHJvdG90eXBlLFM9InN0YWNrImluIG5ldyBiKG0pLGs9InN0YWNrImluIG5ldyB5KDEsMiksQz15JiZnJiZPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG4sbSksdj0hKCFDfHxDLndyaXRhYmxlJiZDLmNvbmZpZ3VyYWJsZSksVD1TJiYhdiYmIWs7YSh7Z2xvYmFsOiEwLGNvbnN0cnVjdG9yOiEwLGZvcmNlZDpwfHxUfSx7RE9NRXhjZXB0aW9uOlQ/dzp5fSk7dmFyIE89aShtKSxNPU8ucHJvdG90eXBlO2lmKE0uY29uc3RydWN0b3IhPT1PKXtwfHxvKE0sImNvbnN0cnVjdG9yIixzKDEsTykpO2Zvcih2YXIgRCBpbiBkKWlmKGMoZCxEKSl7dmFyIFI9ZFtEXSxFPVIucztjKE8sRSl8fG8oTyxFLHMoNixSLmMpKX19fSw1MDAyOmU9PntlLmV4cG9ydHM9e0luZGV4U2l6ZUVycm9yOntzOiJJTkRFWF9TSVpFX0VSUiIsYzoxLG06MX0sRE9NU3RyaW5nU2l6ZUVycm9yOntzOiJET01TVFJJTkdfU0laRV9FUlIiLGM6MixtOjB9LEhpZXJhcmNoeVJlcXVlc3RFcnJvcjp7czoiSElFUkFSQ0hZX1JFUVVFU1RfRVJSIixjOjMsbToxfSxXcm9uZ0RvY3VtZW50RXJyb3I6e3M6IldST05HX0RPQ1VNRU5UX0VSUiIsYzo0LG06MX0sSW52YWxpZENoYXJhY3RlckVycm9yOntzOiJJTlZBTElEX0NIQVJBQ1RFUl9FUlIiLGM6NSxtOjF9LE5vRGF0YUFsbG93ZWRFcnJvcjp7czoiTk9fREFUQV9BTExPV0VEX0VSUiIsYzo2LG06MH0sTm9Nb2RpZmljYXRpb25BbGxvd2VkRXJyb3I6e3M6Ik5PX01PRElGSUNBVElPTl9BTExPV0VEX0VSUiIsYzo3LG06MX0sTm90Rm91bmRFcnJvcjp7czoiTk9UX0ZPVU5EX0VSUiIsYzo4LG06MX0sTm90U3VwcG9ydGVkRXJyb3I6e3M6Ik5PVF9TVVBQT1JURURfRVJSIixjOjksbToxfSxJblVzZUF0dHJpYnV0ZUVycm9yOntzOiJJTlVTRV9BVFRSSUJVVEVfRVJSIixjOjEwLG06MX0sSW52YWxpZFN0YXRlRXJyb3I6e3M6IklOVkFMSURfU1RBVEVfRVJSIixjOjExLG06MX0sU3ludGF4RXJyb3I6e3M6IlNZTlRBWF9FUlIiLGM6MTIsbToxfSxJbnZhbGlkTW9kaWZpY2F0aW9uRXJyb3I6e3M6IklOVkFMSURfTU9ESUZJQ0FUSU9OX0VSUiIsYzoxMyxtOjF9LE5hbWVzcGFjZUVycm9yOntzOiJOQU1FU1BBQ0VfRVJSIixjOjE0LG06MX0sSW52YWxpZEFjY2Vzc0Vycm9yOntzOiJJTlZBTElEX0FDQ0VTU19FUlIiLGM6MTUsbToxfSxWYWxpZGF0aW9uRXJyb3I6e3M6IlZBTElEQVRJT05fRVJSIixjOjE2LG06MH0sVHlwZU1pc21hdGNoRXJyb3I6e3M6IlRZUEVfTUlTTUFUQ0hfRVJSIixjOjE3LG06MX0sU2VjdXJpdHlFcnJvcjp7czoiU0VDVVJJVFlfRVJSIixjOjE4LG06MX0sTmV0d29ya0Vycm9yOntzOiJORVRXT1JLX0VSUiIsYzoxOSxtOjF9LEFib3J0RXJyb3I6e3M6IkFCT1JUX0VSUiIsYzoyMCxtOjF9LFVSTE1pc21hdGNoRXJyb3I6e3M6IlVSTF9NSVNNQVRDSF9FUlIiLGM6MjEsbToxfSxRdW90YUV4Y2VlZGVkRXJyb3I6e3M6IlFVT1RBX0VYQ0VFREVEX0VSUiIsYzoyMixtOjF9LFRpbWVvdXRFcnJvcjp7czoiVElNRU9VVF9FUlIiLGM6MjMsbToxfSxJbnZhbGlkTm9kZVR5cGVFcnJvcjp7czoiSU5WQUxJRF9OT0RFX1RZUEVfRVJSIixjOjI0LG06MX0sRGF0YUNsb25lRXJyb3I6e3M6IkRBVEFfQ0xPTkVfRVJSIixjOjI1LG06MX19fSw1MDI0OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cigzNjUwKSxpPXIoOTgzNSk7YSh7dGFyZ2V0OiJTZXQiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOiFyKDQ5MTYpKCJzeW1tZXRyaWNEaWZmZXJlbmNlIil8fCFpKCJzeW1tZXRyaWNEaWZmZXJlbmNlIil9LHtzeW1tZXRyaWNEaWZmZXJlbmNlOm59KX0sNTAzMTooZSx0LHIpPT57dmFyIGE9cig3NzUxKSxuPXIoOTUwNCksaT1yKDg0ODApLHM9cigzNzE3KSxvPXIoODU1MSksYz1uKFtdLmNvbmNhdCk7ZS5leHBvcnRzPWEoIlJlZmxlY3QiLCJvd25LZXlzIil8fGZ1bmN0aW9uIG93bktleXMoZSl7dmFyIHQ9aS5mKG8oZSkpLHI9cy5mO3JldHVybiByP2ModCxyKGUpKTp0fX0sNTE2OTooZSx0LHIpPT57dmFyIGE9cigzMjM4KSxuPVR5cGVFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYoYShlKSl0aHJvdyBuZXcgbigiQXJyYXlCdWZmZXIgaXMgZGV0YWNoZWQiKTtyZXR1cm4gZX19LDUxNzA6KGUsdCxyKT0+e3ZhciBhPXIoNjcwNiksbj1yKDQ0MDIpO2UuZXhwb3J0cz1hKG4ucHJvdG8sInNpemUiLCJnZXQiKXx8ZnVuY3Rpb24oZSl7cmV0dXJuIGUuc2l6ZX19LDUyMTM6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDQ1NzYpLGk9cig1MzcwKSxzPXIoOTE0Myksbz1uLlVpbnQ4QXJyYXksYz0hb3x8IW8uZnJvbUJhc2U2NHx8IWZ1bmN0aW9uKCl7dHJ5e28uZnJvbUJhc2U2NCgiYSIpO3JldHVybn1jYXRjaChlKXt9dHJ5e28uZnJvbUJhc2U2NCgiIixudWxsKX1jYXRjaChlKXtyZXR1cm4hMH19KCk7byYmYSh7dGFyZ2V0OiJVaW50OEFycmF5IixzdGF0OiEwLGZvcmNlZDpjfSx7ZnJvbUJhc2U2NDpmdW5jdGlvbiBmcm9tQmFzZTY0KGUpe3ZhciB0PXMoZSxhcmd1bWVudHMubGVuZ3RoPjE/YXJndW1lbnRzWzFdOnZvaWQgMCxudWxsLDkwMDcxOTkyNTQ3NDA5OTEpO3JldHVybiBpKG8sdC5ieXRlcyl9fSl9LDUzNzA6KGUsdCxyKT0+e3ZhciBhPXIoNjE5OCk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyKXtmb3IodmFyIG49MCxpPWFyZ3VtZW50cy5sZW5ndGg+Mj9yOmEodCkscz1uZXcgZShpKTtpPm47KXNbbl09dFtuKytdO3JldHVybiBzfX0sNTM5NzooZSx0LHIpPT57dmFyIGE9cig3MDU1KSxuPXIoNzc1MCk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBhKG4oZSkpfX0sNTYxMDooZSx0LHIpPT57dmFyIGE9cigxMjkxKSxuPU1hdGgubWF4LGk9TWF0aC5taW47ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7dmFyIHI9YShlKTtyZXR1cm4gcjwwP24ocit0LDApOmkocix0KX19LDU2MjM6KGUsdCxyKT0+e3IoNDU2KX0sNTYzNjooZSx0LHIpPT57dmFyIGE9cig0NTc2KSxuPXIoOTUwNCksaT1yKDY3MDYpLHM9cig3Njk2KSxvPXIoNTE2OSksYz1yKDczOTQpLGw9cig0NDgzKSxoPXIoMTU0OCksdT1hLnN0cnVjdHVyZWRDbG9uZSxkPWEuQXJyYXlCdWZmZXIsZj1hLkRhdGFWaWV3LGc9TWF0aC5taW4scD1kLnByb3RvdHlwZSxtPWYucHJvdG90eXBlLGI9bihwLnNsaWNlKSx5PWkocCwicmVzaXphYmxlIiwiZ2V0Iiksdz1pKHAsIm1heEJ5dGVMZW5ndGgiLCJnZXQiKSx4PW4obS5nZXRJbnQ4KSxTPW4obS5zZXRJbnQ4KTtlLmV4cG9ydHM9KGh8fGwpJiZmdW5jdGlvbihlLHQscil7dmFyIGEsbj1jKGUpLGk9dm9pZCAwPT09dD9uOnModCkscD0heXx8IXkoZSk7byhlKTtpZihoKXtlPXUoZSx7dHJhbnNmZXI6W2VdfSk7aWYobj09PWkmJihyfHxwKSlyZXR1cm4gZX1pZihuPj1pJiYoIXJ8fHApKWE9YihlLDAsaSk7ZWxzZXt2YXIgbT1yJiYhcCYmdz97bWF4Qnl0ZUxlbmd0aDp3KGUpfTp2b2lkIDA7YT1uZXcgZChpLG0pO2Zvcih2YXIgaz1uZXcgZihlKSxDPW5ldyBmKGEpLHY9ZyhpLG4pLFQ9MDtUPHY7VCsrKVMoQyxULHgoayxUKSl9aHx8bChlKTtyZXR1cm4gYX19LDU3NDU6KGUsdCxyKT0+e3ZhciBhPXIoNzYyOSk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIGFbZV18fChhW2VdPXR8fHt9KX19LDU3ODE6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDc3NTEpLGk9cigyODEyKSxzPXIoNjU1KSxvPXIoNzQxNiksYz1uKCJVUkwiKTthKHt0YXJnZXQ6IlVSTCIsc3RhdDohMCxmb3JjZWQ6IW99LHtwYXJzZTpmdW5jdGlvbiBwYXJzZShlKXt2YXIgdD1pKGFyZ3VtZW50cy5sZW5ndGgsMSkscj1zKGUpLGE9dDwyfHx2b2lkIDA9PT1hcmd1bWVudHNbMV0/dm9pZCAwOnMoYXJndW1lbnRzWzFdKTt0cnl7cmV0dXJuIG5ldyBjKHIsYSl9Y2F0Y2goZSl7cmV0dXJuIG51bGx9fX0pfSw1ODU0OihlLHQscik9Pnt2YXIgYT1yKDI3NzcpLG49VHlwZUVycm9yO2UuZXhwb3J0cz1mdW5jdGlvbihlKXt2YXIgdD1hKGUsIm51bWJlciIpO2lmKCJudW1iZXIiPT10eXBlb2YgdCl0aHJvdyBuZXcgbigiQ2FuJ3QgY29udmVydCBudW1iZXIgdG8gYmlnaW50Iik7cmV0dXJuIEJpZ0ludCh0KX19LDU4NzY6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDM4MzgpO2Eoe3RhcmdldDoiU2V0Iixwcm90bzohMCxyZWFsOiEwLGZvcmNlZDohcig0OTE2KSgiaXNTdWJzZXRPZiIsZnVuY3Rpb24oZSl7cmV0dXJuIGV9KX0se2lzU3Vic2V0T2Y6bn0pfSw1OTE3OihlLHQscik9Pnt2YXIgYT1yKDM3MjQpLG49cig5MDM5KSxpPXIoNDA1NSk7ZS5leHBvcnRzPSFhJiYhbihmdW5jdGlvbigpe3JldHVybiA3IT09T2JqZWN0LmRlZmluZVByb3BlcnR5KGkoImRpdiIpLCJhIix7Z2V0OmZ1bmN0aW9uKCl7cmV0dXJuIDd9fSkuYX0pfSw1OTY2OihlLHQscik9Pnt2YXIgYT1yKDkzMDYpLG49cig0MTE3KTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXt2YXIgcj1lW3RdO3JldHVybiBuKHIpP3ZvaWQgMDphKHIpfX0sNjA0MzooZSx0LHIpPT57dmFyIGE9cig5MzA2KSxuPVR5cGVFcnJvcixQcm9taXNlQ2FwYWJpbGl0eT1mdW5jdGlvbihlKXt2YXIgdCxyO3RoaXMucHJvbWlzZT1uZXcgZShmdW5jdGlvbihlLGEpe2lmKHZvaWQgMCE9PXR8fHZvaWQgMCE9PXIpdGhyb3cgbmV3IG4oIkJhZCBQcm9taXNlIGNvbnN0cnVjdG9yIik7dD1lO3I9YX0pO3RoaXMucmVzb2x2ZT1hKHQpO3RoaXMucmVqZWN0PWEocil9O2UuZXhwb3J0cy5mPWZ1bmN0aW9uKGUpe3JldHVybiBuZXcgUHJvbWlzZUNhcGFiaWxpdHkoZSl9fSw2MDgwOihlLHQscik9Pnt2YXIgYT1yKDc0NzYpLG49cig5MzA2KSxpPXIoNjE2KSxzPWEoYS5iaW5kKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXtuKGUpO3JldHVybiB2b2lkIDA9PT10P2U6aT9zKGUsdCk6ZnVuY3Rpb24oKXtyZXR1cm4gZS5hcHBseSh0LGFyZ3VtZW50cyl9fX0sNjExOTooZSx0LHIpPT57dmFyIGE9cig1NzQ1KSxuPXIoMzM5MiksaT1hKCJrZXlzIik7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBpW2VdfHwoaVtlXT1uKGUpKX19LDYxOTM6KGUsdCxyKT0+e3ZhciBhPXIoNDIxNSk7ZS5leHBvcnRzPSJOT0RFIj09PWF9LDYxOTg6KGUsdCxyKT0+e3ZhciBhPXIoODAxNCk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBhKGUubGVuZ3RoKX19LDYyNjk6ZT0+e2UuZXhwb3J0cz17fX0sNjI3OTooZSx0LHIpPT57dmFyIGE9cig2ODQwKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIpe2Zvcih2YXIgbiBpbiB0KWEoZSxuLHRbbl0scik7cmV0dXJuIGV9fSw2MzE5OihlLHQscik9Pnt2YXIgYT1yKDg1NTEpLG49cig5NTM5KTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIsaSl7dHJ5e3JldHVybiBpP3QoYShyKVswXSxyWzFdKTp0KHIpfWNhdGNoKHQpe24oZSwidGhyb3ciLHQpfX19LDYzOTU6ZT0+e2UuZXhwb3J0cz0hMX0sNjUxODooZSx0LHIpPT57dmFyIGE9cig0NTc2KSxuPXIoNzM0NykuZixpPXIoNjY5OSkscz1yKDY4NDApLG89cig5NDMzKSxjPXIoNzc0MCksbD1yKDI3OTYpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe3ZhciByLGgsdSxkLGYsZz1lLnRhcmdldCxwPWUuZ2xvYmFsLG09ZS5zdGF0O2lmKHI9cD9hOm0/YVtnXXx8byhnLHt9KTphW2ddJiZhW2ddLnByb3RvdHlwZSlmb3IoaCBpbiB0KXtkPXRbaF07dT1lLmRvbnRDYWxsR2V0U2V0PyhmPW4ocixoKSkmJmYudmFsdWU6cltoXTtpZighbChwP2g6ZysobT8iLiI6IiMiKStoLGUuZm9yY2VkKSYmdm9pZCAwIT09dSl7aWYodHlwZW9mIGQ9PXR5cGVvZiB1KWNvbnRpbnVlO2MoZCx1KX0oZS5zaGFtfHx1JiZ1LnNoYW0pJiZpKGQsInNoYW0iLCEwKTtzKHIsaCxkLGUpfX19LDY1NzM6KGUsdCxyKT0+e3ZhciBhPXIoMzcyNCksbj1yKDIxMDYpLGk9cigzMjM4KSxzPUFycmF5QnVmZmVyLnByb3RvdHlwZTthJiYhKCJkZXRhY2hlZCJpbiBzKSYmbihzLCJkZXRhY2hlZCIse2NvbmZpZ3VyYWJsZTohMCxnZXQ6ZnVuY3Rpb24gZGV0YWNoZWQoKXtyZXR1cm4gaSh0aGlzKX19KX0sNjYzMjooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoNDU3NiksaT1yKDkxNDMpLHM9cig0MTU0KSxvPW4uVWludDhBcnJheSxjPSFvfHwhby5wcm90b3R5cGUuc2V0RnJvbUJhc2U2NHx8IWZ1bmN0aW9uKCl7dmFyIGU9bmV3IG8oWzI1NSwyNTUsMjU1LDI1NSwyNTVdKTt0cnl7ZS5zZXRGcm9tQmFzZTY0KCIiLG51bGwpO3JldHVybn1jYXRjaChlKXt9dHJ5e2Uuc2V0RnJvbUJhc2U2NCgiYSIpO3JldHVybn1jYXRjaChlKXt9dHJ5e2Uuc2V0RnJvbUJhc2U2NCgiTWpZeVpnPT09Iil9Y2F0Y2godCl7cmV0dXJuIDUwPT09ZVswXSYmNTQ9PT1lWzFdJiY1MD09PWVbMl0mJjI1NT09PWVbM10mJjI1NT09PWVbNF19fSgpO28mJmEoe3RhcmdldDoiVWludDhBcnJheSIscHJvdG86ITAsZm9yY2VkOmN9LHtzZXRGcm9tQmFzZTY0OmZ1bmN0aW9uIHNldEZyb21CYXNlNjQoZSl7cyh0aGlzKTt2YXIgdD1pKGUsYXJndW1lbnRzLmxlbmd0aD4xP2FyZ3VtZW50c1sxXTp2b2lkIDAsdGhpcyx0aGlzLmxlbmd0aCk7cmV0dXJue3JlYWQ6dC5yZWFkLHdyaXR0ZW46dC53cml0dGVufX19KX0sNjY5OTooZSx0LHIpPT57dmFyIGE9cigzNzI0KSxuPXIoNDkxMyksaT1yKDY5ODApO2UuZXhwb3J0cz1hP2Z1bmN0aW9uKGUsdCxyKXtyZXR1cm4gbi5mKGUsdCxpKDEscikpfTpmdW5jdGlvbihlLHQscil7ZVt0XT1yO3JldHVybiBlfX0sNjcwNjooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPXIoOTMwNik7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyKXt0cnl7cmV0dXJuIGEobihPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGUsdClbcl0pKX1jYXRjaChlKXt9fX0sNjgwMTooZSx0LHIpPT57dmFyIGE9cigzNzI0KSxuPXIoODY4NiksaT1yKDQ5MTMpLHM9cig4NTUxKSxvPXIoNTM5NyksYz1yKDEwNzIpO3QuZj1hJiYhbj9PYmplY3QuZGVmaW5lUHJvcGVydGllczpmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKGUsdCl7cyhlKTtmb3IodmFyIHIsYT1vKHQpLG49Yyh0KSxsPW4ubGVuZ3RoLGg9MDtsPmg7KWkuZihlLHI9bltoKytdLGFbcl0pO3JldHVybiBlfX0sNjgyMzplPT57dmFyIHQ9U3RyaW5nO2UuZXhwb3J0cz1mdW5jdGlvbihlKXt0cnl7cmV0dXJuIHQoZSl9Y2F0Y2goZSl7cmV0dXJuIk9iamVjdCJ9fX0sNjgzNzplPT57dmFyIHQ9VHlwZUVycm9yO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtpZihlPjkwMDcxOTkyNTQ3NDA5OTEpdGhyb3cgdCgiTWF4aW11bSBhbGxvd2VkIGluZGV4IGV4Y2VlZGVkIik7cmV0dXJuIGV9fSw2ODQwOihlLHQscik9Pnt2YXIgYT1yKDQ5MDEpLG49cig0OTEzKSxpPXIoMjgzKSxzPXIoOTQzMyk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyLG8pe298fChvPXt9KTt2YXIgYz1vLmVudW1lcmFibGUsbD12b2lkIDAhPT1vLm5hbWU/by5uYW1lOnQ7YShyKSYmaShyLGwsbyk7aWYoby5nbG9iYWwpYz9lW3RdPXI6cyh0LHIpO2Vsc2V7dHJ5e28udW5zYWZlP2VbdF0mJihjPSEwKTpkZWxldGUgZVt0XX1jYXRjaChlKXt9Yz9lW3RdPXI6bi5mKGUsdCx7dmFsdWU6cixlbnVtZXJhYmxlOiExLGNvbmZpZ3VyYWJsZTohby5ub25Db25maWd1cmFibGUsd3JpdGFibGU6IW8ubm9uV3JpdGFibGV9KX1yZXR1cm4gZX19LDY5NTU6KGUsdCxyKT0+e3ZhciBhPXIoMjE0MCksbj1yKDQ5MDEpLGk9cigyMTk1KSxzPXIoODIyNykoInRvU3RyaW5nVGFnIiksbz1PYmplY3QsYz0iQXJndW1lbnRzIj09PWkoZnVuY3Rpb24oKXtyZXR1cm4gYXJndW1lbnRzfSgpKTtlLmV4cG9ydHM9YT9pOmZ1bmN0aW9uKGUpe3ZhciB0LHIsYTtyZXR1cm4gdm9pZCAwPT09ZT8iVW5kZWZpbmVkIjpudWxsPT09ZT8iTnVsbCI6InN0cmluZyI9PXR5cGVvZihyPWZ1bmN0aW9uKGUsdCl7dHJ5e3JldHVybiBlW3RdfWNhdGNoKGUpe319KHQ9byhlKSxzKSk/cjpjP2kodCk6Ik9iamVjdCI9PT0oYT1pKHQpKSYmbih0LmNhbGxlZSk/IkFyZ3VtZW50cyI6YX19LDY5Njk6KGUsdCxyKT0+e3ZhciBhPXIoMjc3Nyksbj1yKDc1Nyk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3ZhciB0PWEoZSwic3RyaW5nIik7cmV0dXJuIG4odCk/dDp0KyIifX0sNjk4MDplPT57ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7cmV0dXJue2VudW1lcmFibGU6ISgxJmUpLGNvbmZpZ3VyYWJsZTohKDImZSksd3JpdGFibGU6ISg0JmUpLHZhbHVlOnR9fX0sNzA0MDooZSx0LHIpPT57dmFyIGE9cig0NDk1KTtlLmV4cG9ydHM9YSYmIVN5bWJvbC5zaGFtJiYic3ltYm9sIj09dHlwZW9mIFN5bWJvbC5pdGVyYXRvcn0sNzA1NTooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPXIoOTAzOSksaT1yKDIxOTUpLHM9T2JqZWN0LG89YSgiIi5zcGxpdCk7ZS5leHBvcnRzPW4oZnVuY3Rpb24oKXtyZXR1cm4hcygieiIpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApfSk/ZnVuY3Rpb24oZSl7cmV0dXJuIlN0cmluZyI9PT1pKGUpP28oZSwiIik6cyhlKX06c30sNzA4MDooZSx0LHIpPT57dmFyIGE9cig0NDAyKS5oYXM7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2EoZSk7cmV0dXJuIGV9fSw3MzQ3OihlLHQscik9Pnt2YXIgYT1yKDM3MjQpLG49cig5NTY1KSxpPXIoODc3Mykscz1yKDY5ODApLG89cig1Mzk3KSxjPXIoNjk2OSksbD1yKDkyOTcpLGg9cig1OTE3KSx1PU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7dC5mPWE/dTpmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSx0KXtlPW8oZSk7dD1jKHQpO2lmKGgpdHJ5e3JldHVybiB1KGUsdCl9Y2F0Y2goZSl7fWlmKGwoZSx0KSlyZXR1cm4gcyghbihpLmYsZSx0KSxlW3RdKX19LDczOTQ6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDY3MDYpLGk9cigyMTk1KSxzPWEuQXJyYXlCdWZmZXIsbz1hLlR5cGVFcnJvcjtlLmV4cG9ydHM9cyYmbihzLnByb3RvdHlwZSwiYnl0ZUxlbmd0aCIsImdldCIpfHxmdW5jdGlvbihlKXtpZigiQXJyYXlCdWZmZXIiIT09aShlKSl0aHJvdyBuZXcgbygiQXJyYXlCdWZmZXIgZXhwZWN0ZWQiKTtyZXR1cm4gZS5ieXRlTGVuZ3RofX0sNzQxNjooZSx0LHIpPT57dmFyIGE9cig5MDM5KSxuPXIoODIyNyksaT1yKDM3MjQpLHM9cig2Mzk1KSxvPW4oIml0ZXJhdG9yIik7ZS5leHBvcnRzPSFhKGZ1bmN0aW9uKCl7dmFyIGU9bmV3IFVSTCgiYj9hPTEmYj0yJmM9MyIsImh0dHBzOi8vYSIpLHQ9ZS5zZWFyY2hQYXJhbXMscj1uZXcgVVJMU2VhcmNoUGFyYW1zKCJhPTEmYT0yJmI9MyIpLGE9IiI7ZS5wYXRobmFtZT0iYyUyMGQiO3QuZm9yRWFjaChmdW5jdGlvbihlLHIpe3QuZGVsZXRlKCJiIik7YSs9citlfSk7ci5kZWxldGUoImEiLDIpO3IuZGVsZXRlKCJiIix2b2lkIDApO3JldHVybiBzJiYoIWUudG9KU09OfHwhci5oYXMoImEiLDEpfHxyLmhhcygiYSIsMil8fCFyLmhhcygiYSIsdm9pZCAwKXx8ci5oYXMoImIiKSl8fCF0LnNpemUmJihzfHwhaSl8fCF0LnNvcnR8fCJodHRwczovL2EvYyUyMGQ/YT0xJmM9MyIhPT1lLmhyZWZ8fCIzIiE9PXQuZ2V0KCJjIil8fCJhPTEiIT09U3RyaW5nKG5ldyBVUkxTZWFyY2hQYXJhbXMoIj9hPTEiKSl8fCF0W29dfHwiYSIhPT1uZXcgVVJMKCJodHRwczovL2FAYiIpLnVzZXJuYW1lfHwiYiIhPT1uZXcgVVJMU2VhcmNoUGFyYW1zKG5ldyBVUkxTZWFyY2hQYXJhbXMoImE9YiIpKS5nZXQoImEiKXx8InhuLS1lMWF5YmMiIT09bmV3IFVSTCgiaHR0cHM6Ly/RgtC10YHRgiIpLmhvc3R8fCIjJUQwJUIxIiE9PW5ldyBVUkwoImh0dHBzOi8vYSPQsSIpLmhhc2h8fCJhMWMzIiE9PWF8fCJ4IiE9PW5ldyBVUkwoImh0dHBzOi8veCIsdm9pZCAwKS5ob3N0fSl9LDc0NzY6KGUsdCxyKT0+e3ZhciBhPXIoMjE5NSksbj1yKDk1MDQpO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtpZigiRnVuY3Rpb24iPT09YShlKSlyZXR1cm4gbihlKX19LDc1NjY6KGUsdCxyKT0+e3ZhciBhPXIoNjg0MCksbj1yKDk1MDQpLGk9cig2NTUpLHM9cigyODEyKSxvPVVSTFNlYXJjaFBhcmFtcyxjPW8ucHJvdG90eXBlLGw9bihjLmdldEFsbCksaD1uKGMuaGFzKSx1PW5ldyBvKCJhPTEiKTshdS5oYXMoImEiLDIpJiZ1LmhhcygiYSIsdm9pZCAwKXx8YShjLCJoYXMiLGZ1bmN0aW9uIGhhcyhlKXt2YXIgdD1hcmd1bWVudHMubGVuZ3RoLHI9dDwyP3ZvaWQgMDphcmd1bWVudHNbMV07aWYodCYmdm9pZCAwPT09cilyZXR1cm4gaCh0aGlzLGUpO3ZhciBhPWwodGhpcyxlKTtzKHQsMSk7Zm9yKHZhciBuPWkociksbz0wO288YS5sZW5ndGg7KWlmKGFbbysrXT09PW4pcmV0dXJuITA7cmV0dXJuITF9LHtlbnVtZXJhYmxlOiEwLHVuc2FmZTohMH0pfSw3NTg4OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig5NTY1KSxpPXIoMjY1Mikscz1yKDkzMDYpLG89cig4NTUxKSxjPXIoMTc2NyksbD1yKDk1MzkpLGg9cig0NTQ5KSgiZm9yRWFjaCIsVHlwZUVycm9yKTthKHt0YXJnZXQ6Ikl0ZXJhdG9yIixwcm90bzohMCxyZWFsOiEwLGZvcmNlZDpofSx7Zm9yRWFjaDpmdW5jdGlvbiBmb3JFYWNoKGUpe28odGhpcyk7dHJ5e3MoZSl9Y2F0Y2goZSl7bCh0aGlzLCJ0aHJvdyIsZSl9aWYoaClyZXR1cm4gbihoLHRoaXMsZSk7dmFyIHQ9Yyh0aGlzKSxyPTA7aSh0LGZ1bmN0aW9uKHQpe2UodCxyKyspfSx7SVNfUkVDT1JEOiEwfSl9fSl9LDc1OTQ6KGUsdCxyKT0+e3ZhciBhPXIoNDU3Niksbj1yKDkwMzkpLGk9YS5SZWdFeHAscz0hbihmdW5jdGlvbigpe3ZhciBlPSEwO3RyeXtpKCIuIiwiZCIpfWNhdGNoKHQpe2U9ITF9dmFyIHQ9e30scj0iIixhPWU/ImRnaW1zeSI6ImdpbXN5IixhZGRHZXR0ZXI9ZnVuY3Rpb24oZSxhKXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxlLHtnZXQ6ZnVuY3Rpb24oKXtyKz1hO3JldHVybiEwfX0pfSxuPXtkb3RBbGw6InMiLGdsb2JhbDoiZyIsaWdub3JlQ2FzZToiaSIsbXVsdGlsaW5lOiJtIixzdGlja3k6InkifTtlJiYobi5oYXNJbmRpY2VzPSJkIik7Zm9yKHZhciBzIGluIG4pYWRkR2V0dGVyKHMsbltzXSk7cmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoaS5wcm90b3R5cGUsImZsYWdzIikuZ2V0LmNhbGwodCkhPT1hfHxyIT09YX0pO2UuZXhwb3J0cz17Y29ycmVjdDpzfX0sNzYyOTooZSx0LHIpPT57dmFyIGE9cig2Mzk1KSxuPXIoNDU3NiksaT1yKDk0MzMpLHM9Il9fY29yZS1qc19zaGFyZWRfXyIsbz1lLmV4cG9ydHM9bltzXXx8aShzLHt9KTsoby52ZXJzaW9uc3x8KG8udmVyc2lvbnM9W10pKS5wdXNoKHt2ZXJzaW9uOiIzLjQ1LjEiLG1vZGU6YT8icHVyZSI6Imdsb2JhbCIsY29weXJpZ2h0OiLCqSAyMDE0LTIwMjUgRGVuaXMgUHVzaGthcmV2ICh6bG9pcm9jay5ydSkiLGxpY2Vuc2U6Imh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2Jsb2IvdjMuNDUuMS9MSUNFTlNFIixzb3VyY2U6Imh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzIn0pfSw3NjQyOihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cigzNDQwKSxpPXIoOTAzOSk7YSh7dGFyZ2V0OiJTZXQiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOiFyKDQ5MTYpKCJkaWZmZXJlbmNlIixmdW5jdGlvbihlKXtyZXR1cm4gMD09PWUuc2l6ZX0pfHxpKGZ1bmN0aW9uKCl7dmFyIGU9e3NpemU6MSxoYXM6ZnVuY3Rpb24oKXtyZXR1cm4hMH0sa2V5czpmdW5jdGlvbigpe3ZhciBlPTA7cmV0dXJue25leHQ6ZnVuY3Rpb24oKXt2YXIgcj1lKys+MTt0LmhhcygxKSYmdC5jbGVhcigpO3JldHVybntkb25lOnIsdmFsdWU6Mn19fX19LHQ9bmV3IFNldChbMSwyLDMsNF0pO3JldHVybiAzIT09dC5kaWZmZXJlbmNlKGUpLnNpemV9KX0se2RpZmZlcmVuY2U6bn0pfSw3NjU3OihlLHQscik9Pnt2YXIgYSxuLGkscz1yKDkwMzkpLG89cig0OTAxKSxjPXIoMzQpLGw9cigyMzYwKSxoPXIoMjc4NyksdT1yKDY4NDApLGQ9cig4MjI3KSxmPXIoNjM5NSksZz1kKCJpdGVyYXRvciIpLHA9ITE7W10ua2V5cyYmKCJuZXh0ImluKGk9W10ua2V5cygpKT8obj1oKGgoaSkpKSE9PU9iamVjdC5wcm90b3R5cGUmJihhPW4pOnA9ITApOyFjKGEpfHxzKGZ1bmN0aW9uKCl7dmFyIGU9e307cmV0dXJuIGFbZ10uY2FsbChlKSE9PWV9KT9hPXt9OmYmJihhPWwoYSkpO28oYVtnXSl8fHUoYSxnLGZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9KTtlLmV4cG9ydHM9e0l0ZXJhdG9yUHJvdG90eXBlOmEsQlVHR1lfU0FGQVJJX0lURVJBVE9SUzpwfX0sNzY4MDooZSx0LHIpPT57dmFyIGE9cig5NTA0KTtlLmV4cG9ydHM9YShbXS5zbGljZSl9LDc2OTY6KGUsdCxyKT0+e3ZhciBhPXIoMTI5MSksbj1yKDgwMTQpLGk9UmFuZ2VFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYodm9pZCAwPT09ZSlyZXR1cm4gMDt2YXIgdD1hKGUpLHI9bih0KTtpZih0IT09cil0aHJvdyBuZXcgaSgiV3JvbmcgbGVuZ3RoIG9yIGluZGV4Iik7cmV0dXJuIHJ9fSw3NzQwOihlLHQscik9Pnt2YXIgYT1yKDkyOTcpLG49cig1MDMxKSxpPXIoNzM0Nykscz1yKDQ5MTMpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQscil7Zm9yKHZhciBvPW4odCksYz1zLmYsbD1pLmYsaD0wO2g8by5sZW5ndGg7aCsrKXt2YXIgdT1vW2hdO2EoZSx1KXx8ciYmYShyLHUpfHxjKGUsdSxsKHQsdSkpfX19LDc3NTA6KGUsdCxyKT0+e3ZhciBhPXIoNDExNyksbj1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKGEoZSkpdGhyb3cgbmV3IG4oIkNhbid0IGNhbGwgbWV0aG9kIG9uICIrZSk7cmV0dXJuIGV9fSw3NzUxOihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cig0OTAxKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gYXJndW1lbnRzLmxlbmd0aDwyPyhyPWFbZV0sbihyKT9yOnZvaWQgMCk6YVtlXSYmYVtlXVt0XTt2YXIgcn19LDc4MTE6ZT0+e2UuZXhwb3J0cz0idW5kZWZpbmVkIiE9dHlwZW9mIEFycmF5QnVmZmVyJiYidW5kZWZpbmVkIiE9dHlwZW9mIERhdGFWaWV3fSw3OTM2OihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig1NjM2KTtuJiZhKHt0YXJnZXQ6IkFycmF5QnVmZmVyIixwcm90bzohMH0se3RyYW5zZmVyVG9GaXhlZExlbmd0aDpmdW5jdGlvbiB0cmFuc2ZlclRvRml4ZWRMZW5ndGgoKXtyZXR1cm4gbih0aGlzLGFyZ3VtZW50cy5sZW5ndGg/YXJndW1lbnRzWzBdOnZvaWQgMCwhMSl9fSl9LDc5Nzk6KGUsdCxyKT0+e3ZhciBhPXIoODU1MSk7ZS5leHBvcnRzPWZ1bmN0aW9uKCl7dmFyIGU9YSh0aGlzKSx0PSIiO2UuaGFzSW5kaWNlcyYmKHQrPSJkIik7ZS5nbG9iYWwmJih0Kz0iZyIpO2UuaWdub3JlQ2FzZSYmKHQrPSJpIik7ZS5tdWx0aWxpbmUmJih0Kz0ibSIpO2UuZG90QWxsJiYodCs9InMiKTtlLnVuaWNvZGUmJih0Kz0idSIpO2UudW5pY29kZVNldHMmJih0Kz0idiIpO2Uuc3RpY2t5JiYodCs9InkiKTtyZXR1cm4gdH19LDgwMDQ6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDkwMzkpLGk9cig4NzUwKTthKHt0YXJnZXQ6IlNldCIscHJvdG86ITAscmVhbDohMCxmb3JjZWQ6IXIoNDkxNikoImludGVyc2VjdGlvbiIsZnVuY3Rpb24oZSl7cmV0dXJuIDI9PT1lLnNpemUmJmUuaGFzKDEpJiZlLmhhcygyKX0pfHxuKGZ1bmN0aW9uKCl7cmV0dXJuIjMsMiIhPT1TdHJpbmcoQXJyYXkuZnJvbShuZXcgU2V0KFsxLDIsM10pLmludGVyc2VjdGlvbihuZXcgU2V0KFszLDJdKSkpKX0pfSx7aW50ZXJzZWN0aW9uOml9KX0sODAxNDooZSx0LHIpPT57dmFyIGE9cigxMjkxKSxuPU1hdGgubWluO2UuZXhwb3J0cz1mdW5jdGlvbihlKXt2YXIgdD1hKGUpO3JldHVybiB0PjA/bih0LDkwMDcxOTkyNTQ3NDA5OTEpOjB9fSw4MTAwOihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig1NjM2KTtuJiZhKHt0YXJnZXQ6IkFycmF5QnVmZmVyIixwcm90bzohMH0se3RyYW5zZmVyOmZ1bmN0aW9uIHRyYW5zZmVyKCl7cmV0dXJuIG4odGhpcyxhcmd1bWVudHMubGVuZ3RoP2FyZ3VtZW50c1swXTp2b2lkIDAsITApfX0pfSw4MTExOihlLHQscik9Pnt2YXIgYT1yKDY1MTgpLG49cig0NTc2KSxpPXIoNjc5KSxzPXIoODU1MSksbz1yKDQ5MDEpLGM9cigyNzg3KSxsPXIoMjEwNiksaD1yKDQ2NTkpLHU9cig5MDM5KSxkPXIoOTI5NyksZj1yKDgyMjcpLGc9cig3NjU3KS5JdGVyYXRvclByb3RvdHlwZSxwPXIoMzcyNCksbT1yKDYzOTUpLGI9ImNvbnN0cnVjdG9yIix5PSJJdGVyYXRvciIsdz1mKCJ0b1N0cmluZ1RhZyIpLHg9VHlwZUVycm9yLFM9blt5XSxrPW18fCFvKFMpfHxTLnByb3RvdHlwZSE9PWd8fCF1KGZ1bmN0aW9uKCl7Uyh7fSl9KSxDPWZ1bmN0aW9uIEl0ZXJhdG9yKCl7aSh0aGlzLGcpO2lmKGModGhpcyk9PT1nKXRocm93IG5ldyB4KCJBYnN0cmFjdCBjbGFzcyBJdGVyYXRvciBub3QgZGlyZWN0bHkgY29uc3RydWN0YWJsZSIpfSxkZWZpbmVJdGVyYXRvclByb3RvdHlwZUFjY2Vzc29yPWZ1bmN0aW9uKGUsdCl7cD9sKGcsZSx7Y29uZmlndXJhYmxlOiEwLGdldDpmdW5jdGlvbigpe3JldHVybiB0fSxzZXQ6ZnVuY3Rpb24odCl7cyh0aGlzKTtpZih0aGlzPT09Zyl0aHJvdyBuZXcgeCgiWW91IGNhbid0IHJlZGVmaW5lIHRoaXMgcHJvcGVydHkiKTtkKHRoaXMsZSk/dGhpc1tlXT10OmgodGhpcyxlLHQpfX0pOmdbZV09dH07ZChnLHcpfHxkZWZpbmVJdGVyYXRvclByb3RvdHlwZUFjY2Vzc29yKHcseSk7IWsmJmQoZyxiKSYmZ1tiXSE9PU9iamVjdHx8ZGVmaW5lSXRlcmF0b3JQcm90b3R5cGVBY2Nlc3NvcihiLEMpO0MucHJvdG90eXBlPWc7YSh7Z2xvYmFsOiEwLGNvbnN0cnVjdG9yOiEwLGZvcmNlZDprfSx7SXRlcmF0b3I6Q30pfSw4MjI3OihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cig1NzQ1KSxpPXIoOTI5Nykscz1yKDMzOTIpLG89cig0NDk1KSxjPXIoNzA0MCksbD1hLlN5bWJvbCxoPW4oIndrcyIpLHU9Yz9sLmZvcnx8bDpsJiZsLndpdGhvdXRTZXR0ZXJ8fHM7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2koaCxlKXx8KGhbZV09byYmaShsLGUpP2xbZV06dSgiU3ltYm9sLiIrZSkpO3JldHVybiBoW2VdfX0sODIzNzooZSx0LHIpPT57dmFyIGE9cig2NTE4KSxuPXIoMjY1MiksaT1yKDkzMDYpLHM9cig4NTUxKSxvPXIoMTc2NyksYz1yKDk1MzkpLGw9cig0NTQ5KSxoPXIoODc0NSksdT1yKDkwMzkpLGQ9VHlwZUVycm9yLGY9dShmdW5jdGlvbigpe1tdLmtleXMoKS5yZWR1Y2UoZnVuY3Rpb24oKXt9LHZvaWQgMCl9KSxnPSFmJiZsKCJyZWR1Y2UiLGQpO2Eoe3RhcmdldDoiSXRlcmF0b3IiLHByb3RvOiEwLHJlYWw6ITAsZm9yY2VkOmZ8fGd9LHtyZWR1Y2U6ZnVuY3Rpb24gcmVkdWNlKGUpe3ModGhpcyk7dHJ5e2koZSl9Y2F0Y2goZSl7Yyh0aGlzLCJ0aHJvdyIsZSl9dmFyIHQ9YXJndW1lbnRzLmxlbmd0aDwyLHI9dD92b2lkIDA6YXJndW1lbnRzWzFdO2lmKGcpcmV0dXJuIGgoZyx0aGlzLHQ/W2VdOltlLHJdKTt2YXIgYT1vKHRoaXMpLGw9MDtuKGEsZnVuY3Rpb24oYSl7aWYodCl7dD0hMTtyPWF9ZWxzZSByPWUocixhLGwpO2wrK30se0lTX1JFQ09SRDohMH0pO2lmKHQpdGhyb3cgbmV3IGQoIlJlZHVjZSBvZiBlbXB0eSBpdGVyYXRvciB3aXRoIG5vIGluaXRpYWwgdmFsdWUiKTtyZXR1cm4gcn19KX0sODQ2OTooZSx0LHIpPT57dmFyIGE9cig5NTA0KSxuPXIoNTA3KSxpPXIoNDQwMikscz1pLlNldCxvPWkucHJvdG8sYz1hKG8uZm9yRWFjaCksbD1hKG8ua2V5cyksaD1sKG5ldyBzKS5uZXh0O2UuZXhwb3J0cz1mdW5jdGlvbihlLHQscil7cmV0dXJuIHI/bih7aXRlcmF0b3I6bChlKSxuZXh0Omh9LHQpOmMoZSx0KX19LDg0ODA6KGUsdCxyKT0+e3ZhciBhPXIoMTgyOCksbj1yKDg3MjcpLmNvbmNhdCgibGVuZ3RoIiwicHJvdG90eXBlIik7dC5mPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzfHxmdW5jdGlvbiBnZXRPd25Qcm9wZXJ0eU5hbWVzKGUpe3JldHVybiBhKGUsbil9fSw4NTI3OihlLHQscik9Pnt2YXIgYT1yKDcwODApLG49cig0NDAyKS5oYXMsaT1yKDUxNzApLHM9cigzNzg5KSxvPXIoNTA3KSxjPXIoOTUzOSk7ZS5leHBvcnRzPWZ1bmN0aW9uIGlzU3VwZXJzZXRPZihlKXt2YXIgdD1hKHRoaXMpLHI9cyhlKTtpZihpKHQpPHIuc2l6ZSlyZXR1cm4hMTt2YXIgbD1yLmdldEl0ZXJhdG9yKCk7cmV0dXJuITEhPT1vKGwsZnVuY3Rpb24oZSl7aWYoIW4odCxlKSlyZXR1cm4gYyhsLCJub3JtYWwiLCExKX0pfX0sODU1MTooZSx0LHIpPT57dmFyIGE9cigzNCksbj1TdHJpbmcsaT1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKGEoZSkpcmV0dXJuIGU7dGhyb3cgbmV3IGkobihlKSsiIGlzIG5vdCBhbiBvYmplY3QiKX19LDg1NzQ6KGUsdCxyKT0+e3ZhciBhPXIoOTUwNCksbj1FcnJvcixpPWEoIiIucmVwbGFjZSkscz1TdHJpbmcobmV3IG4oInp4Y2FzZCIpLnN0YWNrKSxvPS9cblxzKmF0IFteOl0qOlteXG5dKi8sYz1vLnRlc3Qocyk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7aWYoYyYmInN0cmluZyI9PXR5cGVvZiBlJiYhbi5wcmVwYXJlU3RhY2tUcmFjZSlmb3IoO3QtLTspZT1pKGUsbywiIik7cmV0dXJuIGV9fSw4NjIyOihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cig0OTAxKSxpPWEuV2Vha01hcDtlLmV4cG9ydHM9bihpKSYmL25hdGl2ZSBjb2RlLy50ZXN0KFN0cmluZyhpKSl9LDg2NDY6KGUsdCxyKT0+e3ZhciBhPXIoOTU2NSksbj1yKDg1NTEpLGk9cigxNzY3KSxzPXIoODUxKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXt0JiYic3RyaW5nIj09dHlwZW9mIGV8fG4oZSk7dmFyIHI9cyhlKTtyZXR1cm4gaShuKHZvaWQgMCE9PXI/YShyLGUpOmUpKX19LDg2ODY6KGUsdCxyKT0+e3ZhciBhPXIoMzcyNCksbj1yKDkwMzkpO2UuZXhwb3J0cz1hJiZuKGZ1bmN0aW9uKCl7cmV0dXJuIDQyIT09T2JqZWN0LmRlZmluZVByb3BlcnR5KGZ1bmN0aW9uKCl7fSwicHJvdG90eXBlIix7dmFsdWU6NDIsd3JpdGFibGU6ITF9KS5wcm90b3R5cGV9KX0sODcyMTooZSx0LHIpPT57dmFyIGE9cigzNzI0KSxuPXIoOTUwNCksaT1yKDIxMDYpLHM9VVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZSxvPW4ocy5mb3JFYWNoKTthJiYhKCJzaXplImluIHMpJiZpKHMsInNpemUiLHtnZXQ6ZnVuY3Rpb24gc2l6ZSgpe3ZhciBlPTA7byh0aGlzLGZ1bmN0aW9uKCl7ZSsrfSk7cmV0dXJuIGV9LGNvbmZpZ3VyYWJsZTohMCxlbnVtZXJhYmxlOiEwfSl9LDg3Mjc6ZT0+e2UuZXhwb3J0cz1bImNvbnN0cnVjdG9yIiwiaGFzT3duUHJvcGVydHkiLCJpc1Byb3RvdHlwZU9mIiwicHJvcGVydHlJc0VudW1lcmFibGUiLCJ0b0xvY2FsZVN0cmluZyIsInRvU3RyaW5nIiwidmFsdWVPZiJdfSw4NzQ1OihlLHQscik9Pnt2YXIgYT1yKDYxNiksbj1GdW5jdGlvbi5wcm90b3R5cGUsaT1uLmFwcGx5LHM9bi5jYWxsO2UuZXhwb3J0cz0ib2JqZWN0Ij09dHlwZW9mIFJlZmxlY3QmJlJlZmxlY3QuYXBwbHl8fChhP3MuYmluZChpKTpmdW5jdGlvbigpe3JldHVybiBzLmFwcGx5KGksYXJndW1lbnRzKX0pfSw4NzUwOihlLHQscik9Pnt2YXIgYT1yKDcwODApLG49cig0NDAyKSxpPXIoNTE3MCkscz1yKDM3ODkpLG89cig4NDY5KSxjPXIoNTA3KSxsPW4uU2V0LGg9bi5hZGQsdT1uLmhhcztlLmV4cG9ydHM9ZnVuY3Rpb24gaW50ZXJzZWN0aW9uKGUpe3ZhciB0PWEodGhpcykscj1zKGUpLG49bmV3IGw7aSh0KT5yLnNpemU/YyhyLmdldEl0ZXJhdG9yKCksZnVuY3Rpb24oZSl7dSh0LGUpJiZoKG4sZSl9KTpvKHQsZnVuY3Rpb24oZSl7ci5pbmNsdWRlcyhlKSYmaChuLGUpfSk7cmV0dXJuIG59fSw4NzczOihlLHQpPT57dmFyIHI9e30ucHJvcGVydHlJc0VudW1lcmFibGUsYT1PYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yLG49YSYmIXIuY2FsbCh7MToyfSwxKTt0LmY9bj9mdW5jdGlvbiBwcm9wZXJ0eUlzRW51bWVyYWJsZShlKXt2YXIgdD1hKHRoaXMsZSk7cmV0dXJuISF0JiZ0LmVudW1lcmFibGV9OnJ9LDg5ODE6KGUsdCxyKT0+e3ZhciBhPXIoNzc1MCksbj1PYmplY3Q7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBuKGEoZSkpfX0sOTAzOTplPT57ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3RyeXtyZXR1cm4hIWUoKX1jYXRjaChlKXtyZXR1cm4hMH19fSw5MTQzOihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cig5NTA0KSxpPXIoMzk3Mikscz1yKDM0NjMpLG89cig5Mjk3KSxjPXIoMjgwNCksbD1yKDk0NCksaD1yKDUxNjkpLHU9Yy5jMmksZD1jLmMyaVVybCxmPWEuU3ludGF4RXJyb3IsZz1hLlR5cGVFcnJvcixwPW4oIiIuY2hhckF0KSxza2lwQXNjaWlXaGl0ZXNwYWNlPWZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByPWUubGVuZ3RoO3Q8cjt0Kyspe3ZhciBhPXAoZSx0KTtpZigiICIhPT1hJiYiXHQiIT09YSYmIlxuIiE9PWEmJiJcZiIhPT1hJiYiXHIiIT09YSlicmVha31yZXR1cm4gdH0sZGVjb2RlQmFzZTY0Q2h1bms9ZnVuY3Rpb24oZSx0LHIpe3ZhciBhPWUubGVuZ3RoO2E8NCYmKGUrPTI9PT1hPyJBQSI6IkEiKTt2YXIgbj0odFtwKGUsMCldPDwxOCkrKHRbcChlLDEpXTw8MTIpKyh0W3AoZSwyKV08PDYpK3RbcChlLDMpXSxpPVtuPj4xNiYyNTUsbj4+OCYyNTUsMjU1Jm5dO2lmKDI9PT1hKXtpZihyJiYwIT09aVsxXSl0aHJvdyBuZXcgZigiRXh0cmEgYml0cyIpO3JldHVybltpWzBdXX1pZigzPT09YSl7aWYociYmMCE9PWlbMl0pdGhyb3cgbmV3IGYoIkV4dHJhIGJpdHMiKTtyZXR1cm5baVswXSxpWzFdXX1yZXR1cm4gaX0sd3JpdGVCeXRlcz1mdW5jdGlvbihlLHQscil7Zm9yKHZhciBhPXQubGVuZ3RoLG49MDtuPGE7bisrKWVbcituXT10W25dO3JldHVybiByK2F9O2UuZXhwb3J0cz1mdW5jdGlvbihlLHQscixhKXtzKGUpO2kodCk7dmFyIG49ImJhc2U2NCI9PT1sKHQpP3U6ZCxjPXQ/dC5sYXN0Q2h1bmtIYW5kbGluZzp2b2lkIDA7dm9pZCAwPT09YyYmKGM9Imxvb3NlIik7aWYoImxvb3NlIiE9PWMmJiJzdHJpY3QiIT09YyYmInN0b3AtYmVmb3JlLXBhcnRpYWwiIT09Yyl0aHJvdyBuZXcgZygiSW5jb3JyZWN0IGBsYXN0Q2h1bmtIYW5kbGluZ2Agb3B0aW9uIik7ciYmaChyLmJ1ZmZlcik7dmFyIG09ZS5sZW5ndGgsYj1yfHxbXSx5PTAsdz0wLHg9IiIsUz0wO2lmKGEpZm9yKDs7KXtpZigoUz1za2lwQXNjaWlXaGl0ZXNwYWNlKGUsUykpPT09bSl7aWYoeC5sZW5ndGg+MCl7aWYoInN0b3AtYmVmb3JlLXBhcnRpYWwiPT09YylicmVhaztpZigibG9vc2UiIT09Yyl0aHJvdyBuZXcgZigiTWlzc2luZyBwYWRkaW5nIik7aWYoMT09PXgubGVuZ3RoKXRocm93IG5ldyBmKCJNYWxmb3JtZWQgcGFkZGluZzogZXhhY3RseSBvbmUgYWRkaXRpb25hbCBjaGFyYWN0ZXIiKTt5PXdyaXRlQnl0ZXMoYixkZWNvZGVCYXNlNjRDaHVuayh4LG4sITEpLHkpfXc9bTticmVha312YXIgaz1wKGUsUyk7KytTO2lmKCI9Ij09PWspe2lmKHgubGVuZ3RoPDIpdGhyb3cgbmV3IGYoIlBhZGRpbmcgaXMgdG9vIGVhcmx5Iik7Uz1za2lwQXNjaWlXaGl0ZXNwYWNlKGUsUyk7aWYoMj09PXgubGVuZ3RoKXtpZihTPT09bSl7aWYoInN0b3AtYmVmb3JlLXBhcnRpYWwiPT09YylicmVhazt0aHJvdyBuZXcgZigiTWFsZm9ybWVkIHBhZGRpbmc6IG9ubHkgb25lID0iKX1pZigiPSI9PT1wKGUsUykpeysrUztTPXNraXBBc2NpaVdoaXRlc3BhY2UoZSxTKX19aWYoUzxtKXRocm93IG5ldyBmKCJVbmV4cGVjdGVkIGNoYXJhY3RlciBhZnRlciBwYWRkaW5nIik7eT13cml0ZUJ5dGVzKGIsZGVjb2RlQmFzZTY0Q2h1bmsoeCxuLCJzdHJpY3QiPT09YykseSk7dz1tO2JyZWFrfWlmKCFvKG4saykpdGhyb3cgbmV3IGYoIlVuZXhwZWN0ZWQgY2hhcmFjdGVyIik7dmFyIEM9YS15O2lmKDE9PT1DJiYyPT09eC5sZW5ndGh8fDI9PT1DJiYzPT09eC5sZW5ndGgpYnJlYWs7aWYoND09PSh4Kz1rKS5sZW5ndGgpe3k9d3JpdGVCeXRlcyhiLGRlY29kZUJhc2U2NENodW5rKHgsbiwhMSkseSk7eD0iIjt3PVM7aWYoeT09PWEpYnJlYWt9fXJldHVybntieXRlczpiLHJlYWQ6dyx3cml0dGVuOnl9fX0sOTI4NjooZSx0LHIpPT57dmFyIGE9cig0NDAyKSxuPXIoODQ2OSksaT1hLlNldCxzPWEuYWRkO2UuZXhwb3J0cz1mdW5jdGlvbihlKXt2YXIgdD1uZXcgaTtuKGUsZnVuY3Rpb24oZSl7cyh0LGUpfSk7cmV0dXJuIHR9fSw5Mjk3OihlLHQscik9Pnt2YXIgYT1yKDk1MDQpLG49cig4OTgxKSxpPWEoe30uaGFzT3duUHJvcGVydHkpO2UuZXhwb3J0cz1PYmplY3QuaGFzT3dufHxmdW5jdGlvbiBoYXNPd24oZSx0KXtyZXR1cm4gaShuKGUpLHQpfX0sOTMwNjooZSx0LHIpPT57dmFyIGE9cig0OTAxKSxuPXIoNjgyMyksaT1UeXBlRXJyb3I7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKGEoZSkpcmV0dXJuIGU7dGhyb3cgbmV3IGkobihlKSsiIGlzIG5vdCBhIGZ1bmN0aW9uIil9fSw5NDI5OihlLHQscik9Pnt2YXIgYT1yKDQ1NzYpLG49cig2MTkzKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYobil7dHJ5e3JldHVybiBhLnByb2Nlc3MuZ2V0QnVpbHRpbk1vZHVsZShlKX1jYXRjaChlKXt9dHJ5e3JldHVybiBGdW5jdGlvbigncmV0dXJuIHJlcXVpcmUoIicrZSsnIiknKSgpfWNhdGNoKGUpe319fX0sOTQzMjooZSx0LHIpPT57cig1MjEzKX0sOTQzMzooZSx0LHIpPT57dmFyIGE9cig0NTc2KSxuPU9iamVjdC5kZWZpbmVQcm9wZXJ0eTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXt0cnl7bihhLGUse3ZhbHVlOnQsY29uZmlndXJhYmxlOiEwLHdyaXRhYmxlOiEwfSl9Y2F0Y2gocil7YVtlXT10fXJldHVybiB0fX0sOTQ2MjooZSx0LHIpPT57dmFyIGE9cig5NTY1KSxuPXIoMjM2MCksaT1yKDY2OTkpLHM9cig2Mjc5KSxvPXIoODIyNyksYz1yKDExODEpLGw9cig1OTY2KSxoPXIoNzY1NykuSXRlcmF0b3JQcm90b3R5cGUsdT1yKDI1MjkpLGQ9cig5NTM5KSxmPXIoMTM4NSksZz1vKCJ0b1N0cmluZ1RhZyIpLHA9Ikl0ZXJhdG9ySGVscGVyIixtPSJXcmFwRm9yVmFsaWRJdGVyYXRvciIsYj0ibm9ybWFsIix5PSJ0aHJvdyIsdz1jLnNldCxjcmVhdGVJdGVyYXRvclByb3h5UHJvdG90eXBlPWZ1bmN0aW9uKGUpe3ZhciB0PWMuZ2V0dGVyRm9yKGU/bTpwKTtyZXR1cm4gcyhuKGgpLHtuZXh0OmZ1bmN0aW9uIG5leHQoKXt2YXIgcj10KHRoaXMpO2lmKGUpcmV0dXJuIHIubmV4dEhhbmRsZXIoKTtpZihyLmRvbmUpcmV0dXJuIHUodm9pZCAwLCEwKTt0cnl7dmFyIGE9ci5uZXh0SGFuZGxlcigpO3JldHVybiByLnJldHVybkhhbmRsZXJSZXN1bHQ/YTp1KGEsci5kb25lKX1jYXRjaChlKXtyLmRvbmU9ITA7dGhyb3cgZX19LHJldHVybjpmdW5jdGlvbigpe3ZhciByPXQodGhpcyksbj1yLml0ZXJhdG9yO3IuZG9uZT0hMDtpZihlKXt2YXIgaT1sKG4sInJldHVybiIpO3JldHVybiBpP2EoaSxuKTp1KHZvaWQgMCwhMCl9aWYoci5pbm5lcil0cnl7ZChyLmlubmVyLml0ZXJhdG9yLGIpfWNhdGNoKGUpe3JldHVybiBkKG4seSxlKX1pZihyLm9wZW5JdGVycyl0cnl7ZihyLm9wZW5JdGVycyxiKX1jYXRjaChlKXtyZXR1cm4gZChuLHksZSl9biYmZChuLGIpO3JldHVybiB1KHZvaWQgMCwhMCl9fSl9LHg9Y3JlYXRlSXRlcmF0b3JQcm94eVByb3RvdHlwZSghMCksUz1jcmVhdGVJdGVyYXRvclByb3h5UHJvdG90eXBlKCExKTtpKFMsZywiSXRlcmF0b3IgSGVscGVyIik7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCxyKXt2YXIgYT1mdW5jdGlvbiBJdGVyYXRvcihhLG4pe2lmKG4pe24uaXRlcmF0b3I9YS5pdGVyYXRvcjtuLm5leHQ9YS5uZXh0fWVsc2Ugbj1hO24udHlwZT10P206cDtuLnJldHVybkhhbmRsZXJSZXN1bHQ9ISFyO24ubmV4dEhhbmRsZXI9ZTtuLmNvdW50ZXI9MDtuLmRvbmU9ITE7dyh0aGlzLG4pfTthLnByb3RvdHlwZT10P3g6UztyZXR1cm4gYX19LDk0Nzk6KGUsdCxyKT0+e3ZhciBhPXIoMzcyNCksbj1yKDIxMDYpLGk9cig3NTk0KSxzPXIoNzk3OSk7aWYoYSYmIWkuY29ycmVjdCl7bihSZWdFeHAucHJvdG90eXBlLCJmbGFncyIse2NvbmZpZ3VyYWJsZTohMCxnZXQ6c30pO2kuY29ycmVjdD0hMH19LDk0ODY6KGUsdCxyKT0+e3ZhciBhPXIoNjUxOCksbj1yKDQ1NzYpLGk9cig5NTA0KSxzPXIoMzk3Miksbz1yKDQxNTQpLGM9cig1MTY5KSxsPXIoMjgwNCksaD1yKDk0NCksdT1sLmkyYyxkPWwuaTJjVXJsLGY9aSgiIi5jaGFyQXQpLGc9bi5VaW50OEFycmF5LHA9IWd8fCFnLnByb3RvdHlwZS50b0Jhc2U2NHx8IWZ1bmN0aW9uKCl7dHJ5eyhuZXcgZykudG9CYXNlNjQobnVsbCl9Y2F0Y2goZSl7cmV0dXJuITB9fSgpO2cmJmEoe3RhcmdldDoiVWludDhBcnJheSIscHJvdG86ITAsZm9yY2VkOnB9LHt0b0Jhc2U2NDpmdW5jdGlvbiB0b0Jhc2U2NCgpe3ZhciBlPW8odGhpcyksdD1hcmd1bWVudHMubGVuZ3RoP3MoYXJndW1lbnRzWzBdKTp2b2lkIDAscj0iYmFzZTY0Ij09PWgodCk/dTpkLGE9ISF0JiYhIXQub21pdFBhZGRpbmc7Yyh0aGlzLmJ1ZmZlcik7Zm9yKHZhciBuLGk9IiIsbD0wLGc9ZS5sZW5ndGgsYXQ9ZnVuY3Rpb24oZSl7cmV0dXJuIGYocixuPj42KmUmNjMpfTtsKzI8ZztsKz0zKXtuPShlW2xdPDwxNikrKGVbbCsxXTw8OCkrZVtsKzJdO2krPWF0KDMpK2F0KDIpK2F0KDEpK2F0KDApfWlmKGwrMj09PWcpe249KGVbbF08PDE2KSsoZVtsKzFdPDw4KTtpKz1hdCgzKSthdCgyKSthdCgxKSsoYT8iIjoiPSIpfWVsc2UgaWYobCsxPT09Zyl7bj1lW2xdPDwxNjtpKz1hdCgzKSthdCgyKSsoYT8iIjoiPT0iKX1yZXR1cm4gaX19KX0sOTUwNDooZSx0LHIpPT57dmFyIGE9cig2MTYpLG49RnVuY3Rpb24ucHJvdG90eXBlLGk9bi5jYWxsLHM9YSYmbi5iaW5kLmJpbmQoaSxpKTtlLmV4cG9ydHM9YT9zOmZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBpLmFwcGx5KGUsYXJndW1lbnRzKX19fSw5NTE5OihlLHQscik9Pnt2YXIgYSxuLGk9cig0NTc2KSxzPXIoMjgzOSksbz1pLnByb2Nlc3MsYz1pLkRlbm8sbD1vJiZvLnZlcnNpb25zfHxjJiZjLnZlcnNpb24saD1sJiZsLnY4O2gmJihuPShhPWguc3BsaXQoIi4iKSlbMF0+MCYmYVswXTw0PzE6KyhhWzBdK2FbMV0pKTshbiYmcyYmKCEoYT1zLm1hdGNoKC9FZGdlXC8oXGQrKS8pKXx8YVsxXT49NzQpJiYoYT1zLm1hdGNoKC9DaHJvbWVcLyhcZCspLykpJiYobj0rYVsxXSk7ZS5leHBvcnRzPW59LDk1Mzk6KGUsdCxyKT0+e3ZhciBhPXIoOTU2NSksbj1yKDg1NTEpLGk9cig1OTY2KTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIpe3ZhciBzLG87bihlKTt0cnl7aWYoIShzPWkoZSwicmV0dXJuIikpKXtpZigidGhyb3ciPT09dCl0aHJvdyByO3JldHVybiByfXM9YShzLGUpfWNhdGNoKGUpe289ITA7cz1lfWlmKCJ0aHJvdyI9PT10KXRocm93IHI7aWYobyl0aHJvdyBzO24ocyk7cmV0dXJuIHJ9fSw5NTY1OihlLHQscik9Pnt2YXIgYT1yKDYxNiksbj1GdW5jdGlvbi5wcm90b3R5cGUuY2FsbDtlLmV4cG9ydHM9YT9uLmJpbmQobik6ZnVuY3Rpb24oKXtyZXR1cm4gbi5hcHBseShuLGFyZ3VtZW50cyl9fSw5NTc3OihlLHQscik9Pnt2YXIgYT1yKDk5MjgpLG49cig0NjQ0KSxpPXIoMTEwOCkscz1yKDEyOTEpLG89cig1ODU0KSxjPW4uYVR5cGVkQXJyYXksbD1uLmdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvcixoPW4uZXhwb3J0VHlwZWRBcnJheU1ldGhvZCx1PWZ1bmN0aW9uKCl7dHJ5e25ldyBJbnQ4QXJyYXkoMSkud2l0aCgyLHt2YWx1ZU9mOmZ1bmN0aW9uKCl7dGhyb3cgOH19KX1jYXRjaChlKXtyZXR1cm4gOD09PWV9fSgpLGQ9dSYmZnVuY3Rpb24oKXt0cnl7bmV3IEludDhBcnJheSgxKS53aXRoKC0uNSwxKX1jYXRjaChlKXtyZXR1cm4hMH19KCk7aCgid2l0aCIse3dpdGg6ZnVuY3Rpb24oZSx0KXt2YXIgcj1jKHRoaXMpLG49cyhlKSxoPWkocik/byh0KTordDtyZXR1cm4gYShyLGwociksbixoKX19LndpdGgsIXV8fGQpfSw5NjE3OihlLHQscik9Pnt2YXIgYT1yKDUzOTcpLG49cig1NjEwKSxpPXIoNjE5OCksY3JlYXRlTWV0aG9kPWZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbih0LHIscyl7dmFyIG89YSh0KSxjPWkobyk7aWYoMD09PWMpcmV0dXJuIWUmJi0xO3ZhciBsLGg9bihzLGMpO2lmKGUmJnIhPXIpe2Zvcig7Yz5oOylpZigobD1vW2grK10pIT1sKXJldHVybiEwfWVsc2UgZm9yKDtjPmg7aCsrKWlmKChlfHxoIGluIG8pJiZvW2hdPT09cilyZXR1cm4gZXx8aHx8MDtyZXR1cm4hZSYmLTF9fTtlLmV4cG9ydHM9e2luY2x1ZGVzOmNyZWF0ZU1ldGhvZCghMCksaW5kZXhPZjpjcmVhdGVNZXRob2QoITEpfX0sOTYzMTooZSx0LHIpPT57cig5NDg2KX0sOTc5NzooZSx0LHIpPT57cig0MjI2KX0sOTgzNTplPT57ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3RyeXt2YXIgdD1uZXcgU2V0LHI9e3NpemU6MCxoYXM6ZnVuY3Rpb24oKXtyZXR1cm4hMH0sa2V5czpmdW5jdGlvbigpe3JldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIm5leHQiLHtnZXQ6ZnVuY3Rpb24oKXt0LmNsZWFyKCk7dC5hZGQoNCk7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJue2RvbmU6ITB9fX19KX19LGE9dFtlXShyKTtyZXR1cm4gMT09PWEuc2l6ZSYmND09PWEudmFsdWVzKCkubmV4dCgpLnZhbHVlfWNhdGNoKGUpe3JldHVybiExfX19LDk5Mjg6KGUsdCxyKT0+e3ZhciBhPXIoNjE5OCksbj1yKDEyOTEpLGk9UmFuZ2VFcnJvcjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LHIscyl7dmFyIG89YShlKSxjPW4ociksbD1jPDA/bytjOmM7aWYobD49b3x8bDwwKXRocm93IG5ldyBpKCJJbmNvcnJlY3QgaW5kZXgiKTtmb3IodmFyIGg9bmV3IHQobyksdT0wO3U8bzt1KyspaFt1XT11PT09bD9zOmVbdV07cmV0dXJuIGh9fX0sdD17fTtmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKHIpe3ZhciBhPXRbcl07aWYodm9pZCAwIT09YSlyZXR1cm4gYS5leHBvcnRzO3ZhciBuPXRbcl09e2V4cG9ydHM6e319O2Vbcl0uY2FsbChuLmV4cG9ydHMsbixuLmV4cG9ydHMsX193ZWJwYWNrX3JlcXVpcmVfXyk7cmV0dXJuIG4uZXhwb3J0c31fX3dlYnBhY2tfcmVxdWlyZV9fLmQ9KGUsdCk9Pntmb3IodmFyIHIgaW4gdClfX3dlYnBhY2tfcmVxdWlyZV9fLm8odCxyKSYmIV9fd2VicGFja19yZXF1aXJlX18ubyhlLHIpJiZPYmplY3QuZGVmaW5lUHJvcGVydHkoZSxyLHtlbnVtZXJhYmxlOiEwLGdldDp0W3JdfSl9O19fd2VicGFja19yZXF1aXJlX18ubz0oZSx0KT0+T2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGUsdCk7X193ZWJwYWNrX3JlcXVpcmVfXyg0MTE0KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDY1NzMpLF9fd2VicGFja19yZXF1aXJlX18oODEwMCksX193ZWJwYWNrX3JlcXVpcmVfXyg3OTM2KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDgxMTEpLF9fd2VicGFja19yZXF1aXJlX18oMjQ4OSksX193ZWJwYWNrX3JlcXVpcmVfXygxNzAxKSxfX3dlYnBhY2tfcmVxdWlyZV9fKDM1NzkpLF9fd2VicGFja19yZXF1aXJlX18oNDYyOCksX193ZWJwYWNrX3JlcXVpcmVfXyg3NjQyKSxfX3dlYnBhY2tfcmVxdWlyZV9fKDgwMDQpLF9fd2VicGFja19yZXF1aXJlX18oMzg1MyksX193ZWJwYWNrX3JlcXVpcmVfXyg1ODc2KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDI0NzUpLF9fd2VicGFja19yZXF1aXJlX18oNTAyNCksX193ZWJwYWNrX3JlcXVpcmVfXygxNjk4KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NzcpLF9fd2VicGFja19yZXF1aXJlX18oMTU0OSksX193ZWJwYWNrX3JlcXVpcmVfXyg5Nzk3KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDk2MzEpLF9fd2VicGFja19yZXF1aXJlX18oNTYyMyksX193ZWJwYWNrX3JlcXVpcmVfXygzNjExKSxfX3dlYnBhY2tfcmVxdWlyZV9fKDgyMzcpLF9fd2VicGFja19yZXF1aXJlX18oMTY4OSksX193ZWJwYWNrX3JlcXVpcmVfXyg0MjM1KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDk0MzIpLF9fd2VicGFja19yZXF1aXJlX18oNDk3OSksX193ZWJwYWNrX3JlcXVpcmVfXyg1NzgxKTtjb25zdCByPSEoIm9iamVjdCIhPXR5cGVvZiBwcm9jZXNzfHxwcm9jZXNzKyIiIT0iW29iamVjdCBwcm9jZXNzXSJ8fHByb2Nlc3MudmVyc2lvbnMubnd8fHByb2Nlc3MudmVyc2lvbnMuZWxlY3Ryb24mJnByb2Nlc3MudHlwZSYmImJyb3dzZXIiIT09cHJvY2Vzcy50eXBlKSxhPVsuMDAxLDAsMCwuMDAxLDAsMF0sbj0xLjM1LGk9LjM1LHM9LjI1OTI1OTI1OTI1OTI1OTI0LG89MSxjPTIsbD00LGg9OCx1PTE2LGQ9NjQsZj0xMjgsZz0yNTYscD0icGRmanNfaW50ZXJuYWxfZWRpdG9yXyIsbT0zLGI9OSx5PTEzLHc9MTUseD0xMDEsUz17UFJJTlQ6NCxNT0RJRllfQ09OVEVOVFM6OCxDT1BZOjE2LE1PRElGWV9BTk5PVEFUSU9OUzozMixGSUxMX0lOVEVSQUNUSVZFX0ZPUk1TOjI1NixDT1BZX0ZPUl9BQ0NFU1NJQklMSVRZOjUxMixBU1NFTUJMRToxMDI0LFBSSU5UX0hJR0hfUVVBTElUWToyMDQ4fSxrPTAsQz00LHY9MSxUPTIsTz0zLE09e1RFWFQ6MSxMSU5LOjIsRlJFRVRFWFQ6MyxMSU5FOjQsU1FVQVJFOjUsQ0lSQ0xFOjYsUE9MWUdPTjo3LFBPTFlMSU5FOjgsSElHSExJR0hUOjksVU5ERVJMSU5FOjEwLFNRVUlHR0xZOjExLFNUUklLRU9VVDoxMixTVEFNUDoxMyxDQVJFVDoxNCxJTks6MTUsUE9QVVA6MTYsRklMRUFUVEFDSE1FTlQ6MTcsU09VTkQ6MTgsTU9WSUU6MTksV0lER0VUOjIwLFNDUkVFTjoyMSxQUklOVEVSTUFSSzoyMixUUkFQTkVUOjIzLFdBVEVSTUFSSzoyNCxUSFJFRUQ6MjUsUkVEQUNUOjI2fSxEPSJHcm91cCIsUj0iUiIsRT0xLE49MixfPTQsTD0xNixqPTMyLFU9MTI4LHE9NTEyLFg9MSxIPTIsVz00MDk2LHo9ODE5MixHPTMyNzY4LCQ9NjU1MzYsVj0xMzEwNzIsSz0xMDQ4NTc2LEo9MjA5NzE1MixZPTgzODg2MDgsWj0xNjc3NzIxNixRPTEsZWU9Mix0ZT0zLHJlPTQsYWU9NSxuZT17RToiTW91c2UgRW50ZXIiLFg6Ik1vdXNlIEV4aXQiLEQ6Ik1vdXNlIERvd24iLFU6Ik1vdXNlIFVwIixGbzoiRm9jdXMiLEJsOiJCbHVyIixQTzoiUGFnZU9wZW4iLFBDOiJQYWdlQ2xvc2UiLFBWOiJQYWdlVmlzaWJsZSIsUEk6IlBhZ2VJbnZpc2libGUiLEs6IktleXN0cm9rZSIsRjoiRm9ybWF0IixWOiJWYWxpZGF0ZSIsQzoiQ2FsY3VsYXRlIn0saWU9e1dDOiJXaWxsQ2xvc2UiLFdTOiJXaWxsU2F2ZSIsRFM6IkRpZFNhdmUiLFdQOiJXaWxsUHJpbnQiLERQOiJEaWRQcmludCJ9LHNlPXtPOiJQYWdlT3BlbiIsQzoiUGFnZUNsb3NlIn0sb2U9MSxjZT01LGxlPTEsaGU9Mix1ZT0zLGRlPTQsZmU9NSxnZT02LHBlPTcsbWU9OCxiZT05LHllPTEwLHdlPTExLHhlPTEyLFNlPTEzLEFlPTE0LGtlPTE1LENlPTE2LHZlPTE3LEZlPTE4LEllPTE5LFRlPTIwLE9lPTIxLE1lPTIyLERlPTIzLEJlPTI0LFJlPTI1LEVlPTI2LE5lPTI3LFBlPTI4LF9lPTI5LExlPTMwLGplPTMxLFVlPTMyLHFlPTMzLFhlPTM0LEhlPTM1LFdlPTM2LHplPTM3LEdlPTM4LCRlPTM5LFZlPTQwLEtlPTQxLEplPTQyLFllPTQzLFplPTQ0LFFlPTQ1LGV0PTQ2LHR0PTQ3LHJ0PTQ4LG50PTQ5LGl0PTUwLHN0PTUxLG90PTUyLGN0PTUzLGx0PTU0LGh0PTU1LHV0PTU2LGR0PTU3LGZ0PTU4LGd0PTU5LHB0PTYwLG10PTYxLGJ0PTYyLHl0PTYzLHd0PTY0LHh0PTY1LFN0PTY2LEF0PTY3LGt0PTY4LEN0PTY5LHZ0PTcwLEZ0PTcxLEl0PTcyLFR0PTczLE90PTc0LE10PTc1LER0PTc2LEJ0PTc3LFJ0PTgwLEV0PTgxLE50PTgzLFB0PTg0LF90PTg1LEx0PTg2LGp0PTg3LFV0PTg4LHF0PTg5LFh0PTkwLEh0PTkxLFd0PTkyLHp0PTkzLEd0PTk0LCR0PTAsVnQ9MSxLdD0yLEp0PTMsWXQ9MSxadD0yO2xldCBRdD1vZTtmdW5jdGlvbiBnZXRWZXJib3NpdHlMZXZlbCgpe3JldHVybiBRdH1mdW5jdGlvbiBpbmZvKGUpe1F0Pj1jZSYmY29uc29sZS5pbmZvKGBJbmZvOiAke2V9YCl9ZnVuY3Rpb24gd2FybihlKXtRdD49b2UmJmNvbnNvbGUud2FybihgV2FybmluZzogJHtlfWApfWZ1bmN0aW9uIHVucmVhY2hhYmxlKGUpe3Rocm93IG5ldyBFcnJvcihlKX1mdW5jdGlvbiBhc3NlcnQoZSx0KXtlfHx1bnJlYWNoYWJsZSh0KX1mdW5jdGlvbiBjcmVhdGVWYWxpZEFic29sdXRlVXJsKGUsdD1udWxsLHI9bnVsbCl7aWYoIWUpcmV0dXJuIG51bGw7aWYociYmInN0cmluZyI9PXR5cGVvZiBlKXtpZihyLmFkZERlZmF1bHRQcm90b2NvbCYmZS5zdGFydHNXaXRoKCJ3d3cuIikpe2NvbnN0IHQ9ZS5tYXRjaCgvXC4vZyk7dD8ubGVuZ3RoPj0yJiYoZT1gaHR0cDovLyR7ZX1gKX1pZihyLnRyeUNvbnZlcnRFbmNvZGluZyl0cnl7ZT1zdHJpbmdUb1VURjhTdHJpbmcoZSl9Y2F0Y2h7fX1jb25zdCBhPXQ/VVJMLnBhcnNlKGUsdCk6VVJMLnBhcnNlKGUpO3JldHVybiBmdW5jdGlvbiBfaXNWYWxpZFByb3RvY29sKGUpe3N3aXRjaChlPy5wcm90b2NvbCl7Y2FzZSJodHRwOiI6Y2FzZSJodHRwczoiOmNhc2UiZnRwOiI6Y2FzZSJtYWlsdG86IjpjYXNlInRlbDoiOnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuITF9fShhKT9hOm51bGx9ZnVuY3Rpb24gc2hhZG93KGUsdCxyLGE9ITEpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShlLHQse3ZhbHVlOnIsZW51bWVyYWJsZTohYSxjb25maWd1cmFibGU6ITAsd3JpdGFibGU6ITF9KTtyZXR1cm4gcn1jb25zdCBlcj1mdW5jdGlvbiBCYXNlRXhjZXB0aW9uQ2xvc3VyZSgpe2Z1bmN0aW9uIEJhc2VFeGNlcHRpb24oZSx0KXt0aGlzLm1lc3NhZ2U9ZTt0aGlzLm5hbWU9dH1CYXNlRXhjZXB0aW9uLnByb3RvdHlwZT1uZXcgRXJyb3I7QmFzZUV4Y2VwdGlvbi5jb25zdHJ1Y3Rvcj1CYXNlRXhjZXB0aW9uO3JldHVybiBCYXNlRXhjZXB0aW9ufSgpO2NsYXNzIFBhc3N3b3JkRXhjZXB0aW9uIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihlLCJQYXNzd29yZEV4Y2VwdGlvbiIpO3RoaXMuY29kZT10fX1jbGFzcyBVbmtub3duRXJyb3JFeGNlcHRpb24gZXh0ZW5kcyBlcntjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGUsIlVua25vd25FcnJvckV4Y2VwdGlvbiIpO3RoaXMuZGV0YWlscz10fX1jbGFzcyBJbnZhbGlkUERGRXhjZXB0aW9uIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiSW52YWxpZFBERkV4Y2VwdGlvbiIpfX1jbGFzcyBSZXNwb25zZUV4Y2VwdGlvbiBleHRlbmRzIGVye2NvbnN0cnVjdG9yKGUsdCxyKXtzdXBlcihlLCJSZXNwb25zZUV4Y2VwdGlvbiIpO3RoaXMuc3RhdHVzPXQ7dGhpcy5taXNzaW5nPXJ9fWNsYXNzIEZvcm1hdEVycm9yIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiRm9ybWF0RXJyb3IiKX19Y2xhc3MgQWJvcnRFeGNlcHRpb24gZXh0ZW5kcyBlcntjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJBYm9ydEV4Y2VwdGlvbiIpfX1mdW5jdGlvbiBieXRlc1RvU3RyaW5nKGUpeyJvYmplY3QiPT10eXBlb2YgZSYmdm9pZCAwIT09ZT8ubGVuZ3RofHx1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3IgYnl0ZXNUb1N0cmluZyIpO2NvbnN0IHQ9ZS5sZW5ndGgscj04MTkyO2lmKHQ8cilyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGUpO2NvbnN0IGE9W107Zm9yKGxldCBuPTA7bjx0O24rPXIpe2NvbnN0IGk9TWF0aC5taW4obityLHQpLHM9ZS5zdWJhcnJheShuLGkpO2EucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwscykpfXJldHVybiBhLmpvaW4oIiIpfWZ1bmN0aW9uIHN0cmluZ1RvQnl0ZXMoZSl7InN0cmluZyIhPXR5cGVvZiBlJiZ1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3Igc3RyaW5nVG9CeXRlcyIpO2NvbnN0IHQ9ZS5sZW5ndGgscj1uZXcgVWludDhBcnJheSh0KTtmb3IobGV0IGE9MDthPHQ7KythKXJbYV09MjU1JmUuY2hhckNvZGVBdChhKTtyZXR1cm4gcn1mdW5jdGlvbiBzdHJpbmczMihlKXtyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShlPj4yNCYyNTUsZT4+MTYmMjU1LGU+PjgmMjU1LDI1NSZlKX1mdW5jdGlvbiBvYmplY3RTaXplKGUpe3JldHVybiBPYmplY3Qua2V5cyhlKS5sZW5ndGh9Y2xhc3MgRmVhdHVyZVRlc3R7c3RhdGljIGdldCBpc0xpdHRsZUVuZGlhbigpe3JldHVybiBzaGFkb3codGhpcywiaXNMaXR0bGVFbmRpYW4iLGZ1bmN0aW9uIGlzTGl0dGxlRW5kaWFuKCl7Y29uc3QgZT1uZXcgVWludDhBcnJheSg0KTtlWzBdPTE7cmV0dXJuIDE9PT1uZXcgVWludDMyQXJyYXkoZS5idWZmZXIsMCwxKVswXX0oKSl9c3RhdGljIGdldCBpc0V2YWxTdXBwb3J0ZWQoKXtyZXR1cm4gc2hhZG93KHRoaXMsImlzRXZhbFN1cHBvcnRlZCIsZnVuY3Rpb24gaXNFdmFsU3VwcG9ydGVkKCl7dHJ5e25ldyBGdW5jdGlvbigiIik7cmV0dXJuITB9Y2F0Y2h7cmV0dXJuITF9fSgpKX1zdGF0aWMgZ2V0IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCIsInVuZGVmaW5lZCIhPXR5cGVvZiBPZmZzY3JlZW5DYW52YXMpfXN0YXRpYyBnZXQgaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQoKXtyZXR1cm4gc2hhZG93KHRoaXMsImlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkIiwidW5kZWZpbmVkIiE9dHlwZW9mIEltYWdlRGVjb2Rlcil9c3RhdGljIGdldCBwbGF0Zm9ybSgpe2NvbnN0e3BsYXRmb3JtOmUsdXNlckFnZW50OnR9PW5hdmlnYXRvcjtyZXR1cm4gc2hhZG93KHRoaXMsInBsYXRmb3JtIix7aXNBbmRyb2lkOnQuaW5jbHVkZXMoIkFuZHJvaWQiKSxpc0xpbnV4OmUuaW5jbHVkZXMoIkxpbnV4IiksaXNNYWM6ZS5pbmNsdWRlcygiTWFjIiksaXNXaW5kb3dzOmUuaW5jbHVkZXMoIldpbiIpLGlzRmlyZWZveDp0LmluY2x1ZGVzKCJGaXJlZm94Iil9KX1zdGF0aWMgZ2V0IGlzQ1NTUm91bmRTdXBwb3J0ZWQoKXtyZXR1cm4gc2hhZG93KHRoaXMsImlzQ1NTUm91bmRTdXBwb3J0ZWQiLGdsb2JhbFRoaXMuQ1NTPy5zdXBwb3J0cz8uKCJ3aWR0aDogcm91bmQoMS41cHgsIDFweCkiKSl9fWNvbnN0IHRyPUFycmF5LmZyb20oQXJyYXkoMjU2KS5rZXlzKCksZT0+ZS50b1N0cmluZygxNikucGFkU3RhcnQoMiwiMCIpKTtjbGFzcyBVdGlse3N0YXRpYyBtYWtlSGV4Q29sb3IoZSx0LHIpe3JldHVybmAjJHt0cltlXX0ke3RyW3RdfSR7dHJbcl19YH1zdGF0aWMgZG9tTWF0cml4VG9UcmFuc2Zvcm0oZSl7cmV0dXJuW2UuYSxlLmIsZS5jLGUuZCxlLmUsZS5mXX1zdGF0aWMgc2NhbGVNaW5NYXgoZSx0KXtsZXQgcjtpZihlWzBdKXtpZihlWzBdPDApe3I9dFswXTt0WzBdPXRbMl07dFsyXT1yfXRbMF0qPWVbMF07dFsyXSo9ZVswXTtpZihlWzNdPDApe3I9dFsxXTt0WzFdPXRbM107dFszXT1yfXRbMV0qPWVbM107dFszXSo9ZVszXX1lbHNle3I9dFswXTt0WzBdPXRbMV07dFsxXT1yO3I9dFsyXTt0WzJdPXRbM107dFszXT1yO2lmKGVbMV08MCl7cj10WzFdO3RbMV09dFszXTt0WzNdPXJ9dFsxXSo9ZVsxXTt0WzNdKj1lWzFdO2lmKGVbMl08MCl7cj10WzBdO3RbMF09dFsyXTt0WzJdPXJ9dFswXSo9ZVsyXTt0WzJdKj1lWzJdfXRbMF0rPWVbNF07dFsxXSs9ZVs1XTt0WzJdKz1lWzRdO3RbM10rPWVbNV19c3RhdGljIHRyYW5zZm9ybShlLHQpe3JldHVybltlWzBdKnRbMF0rZVsyXSp0WzFdLGVbMV0qdFswXStlWzNdKnRbMV0sZVswXSp0WzJdK2VbMl0qdFszXSxlWzFdKnRbMl0rZVszXSp0WzNdLGVbMF0qdFs0XStlWzJdKnRbNV0rZVs0XSxlWzFdKnRbNF0rZVszXSp0WzVdK2VbNV1dfXN0YXRpYyBtdWx0aXBseUJ5RE9NTWF0cml4KGUsdCl7cmV0dXJuW2VbMF0qdC5hK2VbMl0qdC5iLGVbMV0qdC5hK2VbM10qdC5iLGVbMF0qdC5jK2VbMl0qdC5kLGVbMV0qdC5jK2VbM10qdC5kLGVbMF0qdC5lK2VbMl0qdC5mK2VbNF0sZVsxXSp0LmUrZVszXSp0LmYrZVs1XV19c3RhdGljIGFwcGx5VHJhbnNmb3JtKGUsdCxyPTApe2NvbnN0IGE9ZVtyXSxuPWVbcisxXTtlW3JdPWEqdFswXStuKnRbMl0rdFs0XTtlW3IrMV09YSp0WzFdK24qdFszXSt0WzVdfXN0YXRpYyBhcHBseVRyYW5zZm9ybVRvQmV6aWVyKGUsdCxyPTApe2NvbnN0IGE9dFswXSxuPXRbMV0saT10WzJdLHM9dFszXSxvPXRbNF0sYz10WzVdO2ZvcihsZXQgdD0wO3Q8Njt0Kz0yKXtjb25zdCBsPWVbcit0XSxoPWVbcit0KzFdO2Vbcit0XT1sKmEraCppK287ZVtyK3QrMV09bCpuK2gqcytjfX1zdGF0aWMgYXBwbHlJbnZlcnNlVHJhbnNmb3JtKGUsdCl7Y29uc3Qgcj1lWzBdLGE9ZVsxXSxuPXRbMF0qdFszXS10WzFdKnRbMl07ZVswXT0ocip0WzNdLWEqdFsyXSt0WzJdKnRbNV0tdFs0XSp0WzNdKS9uO2VbMV09KC1yKnRbMV0rYSp0WzBdK3RbNF0qdFsxXS10WzVdKnRbMF0pL259c3RhdGljIGF4aWFsQWxpZ25lZEJvdW5kaW5nQm94KGUsdCxyKXtjb25zdCBhPXRbMF0sbj10WzFdLGk9dFsyXSxzPXRbM10sbz10WzRdLGM9dFs1XSxsPWVbMF0saD1lWzFdLHU9ZVsyXSxkPWVbM107bGV0IGY9YSpsK28sZz1mLHA9YSp1K28sbT1wLGI9cypoK2MseT1iLHc9cypkK2MseD13O2lmKDAhPT1ufHwwIT09aSl7Y29uc3QgZT1uKmwsdD1uKnUscj1pKmgsYT1pKmQ7Zis9cjttKz1yO3ArPWE7Zys9YTtiKz1lO3grPWU7dys9dDt5Kz10fXJbMF09TWF0aC5taW4oclswXSxmLHAsZyxtKTtyWzFdPU1hdGgubWluKHJbMV0sYix3LHkseCk7clsyXT1NYXRoLm1heChyWzJdLGYscCxnLG0pO3JbM109TWF0aC5tYXgoclszXSxiLHcseSx4KX1zdGF0aWMgaW52ZXJzZVRyYW5zZm9ybShlKXtjb25zdCB0PWVbMF0qZVszXS1lWzFdKmVbMl07cmV0dXJuW2VbM10vdCwtZVsxXS90LC1lWzJdL3QsZVswXS90LChlWzJdKmVbNV0tZVs0XSplWzNdKS90LChlWzRdKmVbMV0tZVs1XSplWzBdKS90XX1zdGF0aWMgc2luZ3VsYXJWYWx1ZURlY29tcG9zZTJkU2NhbGUoZSx0KXtjb25zdCByPWVbMF0sYT1lWzFdLG49ZVsyXSxpPWVbM10scz1yKioyK2EqKjIsbz1yKm4rYSppLGM9bioqMitpKioyLGw9KHMrYykvMixoPU1hdGguc3FydChsKioyLShzKmMtbyoqMikpO3RbMF09TWF0aC5zcXJ0KGwraHx8MSk7dFsxXT1NYXRoLnNxcnQobC1ofHwxKX1zdGF0aWMgbm9ybWFsaXplUmVjdChlKXtjb25zdCB0PWUuc2xpY2UoMCk7aWYoZVswXT5lWzJdKXt0WzBdPWVbMl07dFsyXT1lWzBdfWlmKGVbMV0+ZVszXSl7dFsxXT1lWzNdO3RbM109ZVsxXX1yZXR1cm4gdH1zdGF0aWMgaW50ZXJzZWN0KGUsdCl7Y29uc3Qgcj1NYXRoLm1heChNYXRoLm1pbihlWzBdLGVbMl0pLE1hdGgubWluKHRbMF0sdFsyXSkpLGE9TWF0aC5taW4oTWF0aC5tYXgoZVswXSxlWzJdKSxNYXRoLm1heCh0WzBdLHRbMl0pKTtpZihyPmEpcmV0dXJuIG51bGw7Y29uc3Qgbj1NYXRoLm1heChNYXRoLm1pbihlWzFdLGVbM10pLE1hdGgubWluKHRbMV0sdFszXSkpLGk9TWF0aC5taW4oTWF0aC5tYXgoZVsxXSxlWzNdKSxNYXRoLm1heCh0WzFdLHRbM10pKTtyZXR1cm4gbj5pP251bGw6W3IsbixhLGldfXN0YXRpYyBwb2ludEJvdW5kaW5nQm94KGUsdCxyKXtyWzBdPU1hdGgubWluKHJbMF0sZSk7clsxXT1NYXRoLm1pbihyWzFdLHQpO3JbMl09TWF0aC5tYXgoclsyXSxlKTtyWzNdPU1hdGgubWF4KHJbM10sdCl9c3RhdGljIHJlY3RCb3VuZGluZ0JveChlLHQscixhLG4pe25bMF09TWF0aC5taW4oblswXSxlLHIpO25bMV09TWF0aC5taW4oblsxXSx0LGEpO25bMl09TWF0aC5tYXgoblsyXSxlLHIpO25bM109TWF0aC5tYXgoblszXSx0LGEpfXN0YXRpYyNlKGUsdCxyLGEsbixpLHMsbyxjLGwpe2lmKGM8PTB8fGM+PTEpcmV0dXJuO2NvbnN0IGg9MS1jLHU9YypjLGQ9dSpjLGY9aCooaCooaCplKzMqYyp0KSszKnUqcikrZCphLGc9aCooaCooaCpuKzMqYyppKSszKnUqcykrZCpvO2xbMF09TWF0aC5taW4obFswXSxmKTtsWzFdPU1hdGgubWluKGxbMV0sZyk7bFsyXT1NYXRoLm1heChsWzJdLGYpO2xbM109TWF0aC5tYXgobFszXSxnKX1zdGF0aWMjdChlLHQscixhLG4saSxzLG8sYyxsLGgsdSl7aWYoTWF0aC5hYnMoYyk8MWUtMTIpe01hdGguYWJzKGwpPj0xZS0xMiYmdGhpcy4jZShlLHQscixhLG4saSxzLG8sLWgvbCx1KTtyZXR1cm59Y29uc3QgZD1sKioyLTQqaCpjO2lmKGQ8MClyZXR1cm47Y29uc3QgZj1NYXRoLnNxcnQoZCksZz0yKmM7dGhpcy4jZShlLHQscixhLG4saSxzLG8sKC1sK2YpL2csdSk7dGhpcy4jZShlLHQscixhLG4saSxzLG8sKC1sLWYpL2csdSl9c3RhdGljIGJlemllckJvdW5kaW5nQm94KGUsdCxyLGEsbixpLHMsbyxjKXtjWzBdPU1hdGgubWluKGNbMF0sZSxzKTtjWzFdPU1hdGgubWluKGNbMV0sdCxvKTtjWzJdPU1hdGgubWF4KGNbMl0sZSxzKTtjWzNdPU1hdGgubWF4KGNbM10sdCxvKTt0aGlzLiN0KGUscixuLHMsdCxhLGksbywzKigzKihyLW4pLWUrcyksNiooZS0yKnIrbiksMyooci1lKSxjKTt0aGlzLiN0KGUscixuLHMsdCxhLGksbywzKigzKihhLWkpLXQrbyksNioodC0yKmEraSksMyooYS10KSxjKX19Y29uc3QgcnI9WzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDcyOCw3MTEsNzEwLDcyOSw3MzMsNzMxLDczMCw3MzIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsODIyNiw4MjI0LDgyMjUsODIzMCw4MjEyLDgyMTEsNDAyLDgyNjAsODI0OSw4MjUwLDg3MjIsODI0MCw4MjIyLDgyMjAsODIyMSw4MjE2LDgyMTcsODIxOCw4NDgyLDY0MjU3LDY0MjU4LDMyMSwzMzgsMzUyLDM3NiwzODEsMzA1LDMyMiwzMzksMzUzLDM4MiwwLDgzNjRdO2Z1bmN0aW9uIHN0cmluZ1RvUERGU3RyaW5nKGUsdD0hMSl7aWYoZVswXT49IsOvIil7bGV0IHI7aWYoIsO+Ij09PWVbMF0mJiLDvyI9PT1lWzFdKXtyPSJ1dGYtMTZiZSI7ZS5sZW5ndGglMj09MSYmKGU9ZS5zbGljZSgwLC0xKSl9ZWxzZSBpZigiw78iPT09ZVswXSYmIsO+Ij09PWVbMV0pe3I9InV0Zi0xNmxlIjtlLmxlbmd0aCUyPT0xJiYoZT1lLnNsaWNlKDAsLTEpKX1lbHNlIsOvIj09PWVbMF0mJiLCuyI9PT1lWzFdJiYiwr8iPT09ZVsyXSYmKHI9InV0Zi04Iik7aWYocil0cnl7Y29uc3QgYT1uZXcgVGV4dERlY29kZXIocix7ZmF0YWw6ITB9KSxuPXN0cmluZ1RvQnl0ZXMoZSksaT1hLmRlY29kZShuKTtyZXR1cm4gdHx8IWkuaW5jbHVkZXMoIhsiKT9pOmkucmVwbGFjZUFsbCgvXHgxYlteXHgxYl0qKD86XHgxYnwkKS9nLCIiKX1jYXRjaChlKXt3YXJuKGBzdHJpbmdUb1BERlN0cmluZzogIiR7ZX0iLmApfX1jb25zdCByPVtdO2ZvcihsZXQgYT0wLG49ZS5sZW5ndGg7YTxuO2ErKyl7Y29uc3QgaT1lLmNoYXJDb2RlQXQoYSk7aWYoIXQmJjI3PT09aSl7Zm9yKDsrK2E8biYmMjchPT1lLmNoYXJDb2RlQXQoYSk7KTtjb250aW51ZX1jb25zdCBzPXJyW2ldO3IucHVzaChzP1N0cmluZy5mcm9tQ2hhckNvZGUocyk6ZS5jaGFyQXQoYSkpfXJldHVybiByLmpvaW4oIiIpfWZ1bmN0aW9uIHN0cmluZ1RvVVRGOFN0cmluZyhlKXtyZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KGVzY2FwZShlKSl9ZnVuY3Rpb24gdXRmOFN0cmluZ1RvU3RyaW5nKGUpe3JldHVybiB1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoZSkpfWZ1bmN0aW9uIGlzQXJyYXlFcXVhbChlLHQpe2lmKGUubGVuZ3RoIT09dC5sZW5ndGgpcmV0dXJuITE7Zm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKWlmKGVbcl0hPT10W3JdKXJldHVybiExO3JldHVybiEwfWZ1bmN0aW9uIGdldE1vZGlmaWNhdGlvbkRhdGUoZT1uZXcgRGF0ZSl7ZSBpbnN0YW5jZW9mIERhdGV8fChlPW5ldyBEYXRlKGUpKTtyZXR1cm5bZS5nZXRVVENGdWxsWWVhcigpLnRvU3RyaW5nKCksKGUuZ2V0VVRDTW9udGgoKSsxKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsIjAiKSxlLmdldFVUQ0RhdGUoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsIjAiKSxlLmdldFVUQ0hvdXJzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCIwIiksZS5nZXRVVENNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCIwIiksZS5nZXRVVENTZWNvbmRzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCIwIildLmpvaW4oIiIpfWxldCBhcj1udWxsLG5yPW51bGw7ZnVuY3Rpb24gTWF0aENsYW1wKGUsdCxyKXtyZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgoZSx0KSxyKX1mdW5jdGlvbiB0b0hleFV0aWwoZSl7cmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLnRvSGV4P2UudG9IZXgoKTpBcnJheS5mcm9tKGUsZT0+dHJbZV0pLmpvaW4oIiIpfSJmdW5jdGlvbiIhPXR5cGVvZiBNYXRoLnN1bVByZWNpc2UmJihNYXRoLnN1bVByZWNpc2U9ZnVuY3Rpb24oZSl7cmV0dXJuIGUucmVkdWNlKChlLHQpPT5lK3QsMCl9KTsiZnVuY3Rpb24iIT10eXBlb2YgQWJvcnRTaWduYWwuYW55JiYoQWJvcnRTaWduYWwuYW55PWZ1bmN0aW9uKGUpe2NvbnN0IHQ9bmV3IEFib3J0Q29udHJvbGxlcix7c2lnbmFsOnJ9PXQ7Zm9yKGNvbnN0IGEgb2YgZSlpZihhLmFib3J0ZWQpe3QuYWJvcnQoYS5yZWFzb24pO3JldHVybiByfWZvcihjb25zdCBhIG9mIGUpYS5hZGRFdmVudExpc3RlbmVyKCJhYm9ydCIsKCk9Pnt0LmFib3J0KGEucmVhc29uKX0se3NpZ25hbDpyfSk7cmV0dXJuIHJ9KTtfX3dlYnBhY2tfcmVxdWlyZV9fKDExNDgpO2NvbnN0IGlyPVN5bWJvbCgiQ0lSQ1VMQVJfUkVGIiksc3I9U3ltYm9sKCJFT0YiKTtsZXQgb3I9T2JqZWN0LmNyZWF0ZShudWxsKSxjcj1PYmplY3QuY3JlYXRlKG51bGwpLGxyPU9iamVjdC5jcmVhdGUobnVsbCk7Y2xhc3MgTmFtZXtjb25zdHJ1Y3RvcihlKXt0aGlzLm5hbWU9ZX1zdGF0aWMgZ2V0KGUpe3JldHVybiBjcltlXXx8PW5ldyBOYW1lKGUpfX1jbGFzcyBDbWR7Y29uc3RydWN0b3IoZSl7dGhpcy5jbWQ9ZX1zdGF0aWMgZ2V0KGUpe3JldHVybiBvcltlXXx8PW5ldyBDbWQoZSl9fWNvbnN0IGhyPWZ1bmN0aW9uIG5vblNlcmlhbGl6YWJsZUNsb3N1cmUoKXtyZXR1cm4gaHJ9O2NsYXNzIERpY3R7Y29uc3RydWN0b3IoZT1udWxsKXt0aGlzLl9tYXA9bmV3IE1hcDt0aGlzLnhyZWY9ZTt0aGlzLm9iaklkPW51bGw7dGhpcy5zdXBwcmVzc0VuY3J5cHRpb249ITE7dGhpcy5fX25vblNlcmlhbGl6YWJsZV9fPWhyfWFzc2lnblhyZWYoZSl7dGhpcy54cmVmPWV9Z2V0IHNpemUoKXtyZXR1cm4gdGhpcy5fbWFwLnNpemV9Z2V0KGUsdCxyKXtsZXQgYT10aGlzLl9tYXAuZ2V0KGUpO2lmKHZvaWQgMD09PWEmJnZvaWQgMCE9PXQpe2E9dGhpcy5fbWFwLmdldCh0KTt2b2lkIDA9PT1hJiZ2b2lkIDAhPT1yJiYoYT10aGlzLl9tYXAuZ2V0KHIpKX1yZXR1cm4gYSBpbnN0YW5jZW9mIFJlZiYmdGhpcy54cmVmP3RoaXMueHJlZi5mZXRjaChhLHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKTphfWFzeW5jIGdldEFzeW5jKGUsdCxyKXtsZXQgYT10aGlzLl9tYXAuZ2V0KGUpO2lmKHZvaWQgMD09PWEmJnZvaWQgMCE9PXQpe2E9dGhpcy5fbWFwLmdldCh0KTt2b2lkIDA9PT1hJiZ2b2lkIDAhPT1yJiYoYT10aGlzLl9tYXAuZ2V0KHIpKX1yZXR1cm4gYSBpbnN0YW5jZW9mIFJlZiYmdGhpcy54cmVmP3RoaXMueHJlZi5mZXRjaEFzeW5jKGEsdGhpcy5zdXBwcmVzc0VuY3J5cHRpb24pOmF9Z2V0QXJyYXkoZSx0LHIpe2xldCBhPXRoaXMuX21hcC5nZXQoZSk7aWYodm9pZCAwPT09YSYmdm9pZCAwIT09dCl7YT10aGlzLl9tYXAuZ2V0KHQpO3ZvaWQgMD09PWEmJnZvaWQgMCE9PXImJihhPXRoaXMuX21hcC5nZXQocikpfWEgaW5zdGFuY2VvZiBSZWYmJnRoaXMueHJlZiYmKGE9dGhpcy54cmVmLmZldGNoKGEsdGhpcy5zdXBwcmVzc0VuY3J5cHRpb24pKTtpZihBcnJheS5pc0FycmF5KGEpKXthPWEuc2xpY2UoKTtmb3IobGV0IGU9MCx0PWEubGVuZ3RoO2U8dDtlKyspYVtlXWluc3RhbmNlb2YgUmVmJiZ0aGlzLnhyZWYmJihhW2VdPXRoaXMueHJlZi5mZXRjaChhW2VdLHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKSl9cmV0dXJuIGF9Z2V0UmF3KGUpe3JldHVybiB0aGlzLl9tYXAuZ2V0KGUpfWdldEtleXMoKXtyZXR1cm5bLi4udGhpcy5fbWFwLmtleXMoKV19Z2V0UmF3VmFsdWVzKCl7cmV0dXJuWy4uLnRoaXMuX21hcC52YWx1ZXMoKV19c2V0KGUsdCl7dGhpcy5fbWFwLnNldChlLHQpfXNldElmTm90RXhpc3RzKGUsdCl7dGhpcy5oYXMoZSl8fHRoaXMuc2V0KGUsdCl9c2V0SWZOdW1iZXIoZSx0KXsibnVtYmVyIj09dHlwZW9mIHQmJnRoaXMuc2V0KGUsdCl9c2V0SWZBcnJheShlLHQpeyhBcnJheS5pc0FycmF5KHQpfHxBcnJheUJ1ZmZlci5pc1ZpZXcodCkpJiZ0aGlzLnNldChlLHQpfXNldElmRGVmaW5lZChlLHQpe251bGwhPXQmJnRoaXMuc2V0KGUsdCl9c2V0SWZOYW1lKGUsdCl7InN0cmluZyI9PXR5cGVvZiB0P3RoaXMuc2V0KGUsTmFtZS5nZXQodCkpOnQgaW5zdGFuY2VvZiBOYW1lJiZ0aGlzLnNldChlLHQpfWhhcyhlKXtyZXR1cm4gdGhpcy5fbWFwLmhhcyhlKX0qW1N5bWJvbC5pdGVyYXRvcl0oKXtmb3IoY29uc3RbZSx0XW9mIHRoaXMuX21hcCl5aWVsZFtlLHQgaW5zdGFuY2VvZiBSZWYmJnRoaXMueHJlZj90aGlzLnhyZWYuZmV0Y2godCx0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik6dF19c3RhdGljIGdldCBlbXB0eSgpe2NvbnN0IGU9bmV3IERpY3QobnVsbCk7ZS5zZXQ9KGUsdCk9Pnt1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIGBzZXRgIG9uIHRoZSBlbXB0eSBkaWN0aW9uYXJ5LiIpfTtyZXR1cm4gc2hhZG93KHRoaXMsImVtcHR5IixlKX1zdGF0aWMgbWVyZ2Uoe3hyZWY6ZSxkaWN0QXJyYXk6dCxtZXJnZVN1YkRpY3RzOnI9ITF9KXtjb25zdCBhPW5ldyBEaWN0KGUpLG49bmV3IE1hcDtmb3IoY29uc3QgZSBvZiB0KWlmKGUgaW5zdGFuY2VvZiBEaWN0KWZvcihjb25zdFt0LGFdb2YgZS5fbWFwKXtsZXQgZT1uLmdldCh0KTtpZih2b2lkIDA9PT1lKXtlPVtdO24uc2V0KHQsZSl9ZWxzZSBpZighKHImJmEgaW5zdGFuY2VvZiBEaWN0KSljb250aW51ZTtlLnB1c2goYSl9Zm9yKGNvbnN0W3Qscl1vZiBuKXtpZigxPT09ci5sZW5ndGh8fCEoclswXWluc3RhbmNlb2YgRGljdCkpe2EuX21hcC5zZXQodCxyWzBdKTtjb250aW51ZX1jb25zdCBuPW5ldyBEaWN0KGUpO2Zvcihjb25zdCBlIG9mIHIpZm9yKGNvbnN0W3Qscl1vZiBlLl9tYXApbi5fbWFwLmhhcyh0KXx8bi5fbWFwLnNldCh0LHIpO24uc2l6ZT4wJiZhLl9tYXAuc2V0KHQsbil9bi5jbGVhcigpO3JldHVybiBhLnNpemU+MD9hOkRpY3QuZW1wdHl9Y2xvbmUoKXtjb25zdCBlPW5ldyBEaWN0KHRoaXMueHJlZik7Zm9yKGNvbnN0IHQgb2YgdGhpcy5nZXRLZXlzKCkpZS5zZXQodCx0aGlzLmdldFJhdyh0KSk7cmV0dXJuIGV9ZGVsZXRlKGUpe3RoaXMuX21hcC5kZWxldGUoZSl9fWNsYXNzIFJlZntjb25zdHJ1Y3RvcihlLHQpe3RoaXMubnVtPWU7dGhpcy5nZW49dH10b1N0cmluZygpe3JldHVybiAwPT09dGhpcy5nZW4/YCR7dGhpcy5udW19UmA6YCR7dGhpcy5udW19UiR7dGhpcy5nZW59YH1zdGF0aWMgZnJvbVN0cmluZyhlKXtjb25zdCB0PWxyW2VdO2lmKHQpcmV0dXJuIHQ7Y29uc3Qgcj0vXihcZCspUihcZCopJC8uZXhlYyhlKTtyZXR1cm4gciYmIjAiIT09clsxXT9scltlXT1uZXcgUmVmKHBhcnNlSW50KHJbMV0pLHJbMl0/cGFyc2VJbnQoclsyXSk6MCk6bnVsbH1zdGF0aWMgZ2V0KGUsdCl7Y29uc3Qgcj0wPT09dD9gJHtlfVJgOmAke2V9UiR7dH1gO3JldHVybiBscltyXXx8PW5ldyBSZWYoZSx0KX19Y2xhc3MgUmVmU2V0e2NvbnN0cnVjdG9yKGU9bnVsbCl7dGhpcy5fc2V0PW5ldyBTZXQoZT8uX3NldCl9aGFzKGUpe3JldHVybiB0aGlzLl9zZXQuaGFzKGUudG9TdHJpbmcoKSl9cHV0KGUpe3RoaXMuX3NldC5hZGQoZS50b1N0cmluZygpKX1yZW1vdmUoZSl7dGhpcy5fc2V0LmRlbGV0ZShlLnRvU3RyaW5nKCkpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX3NldC52YWx1ZXMoKX1jbGVhcigpe3RoaXMuX3NldC5jbGVhcigpfX1jbGFzcyBSZWZTZXRDYWNoZXtjb25zdHJ1Y3Rvcigpe3RoaXMuX21hcD1uZXcgTWFwfWdldCBzaXplKCl7cmV0dXJuIHRoaXMuX21hcC5zaXplfWdldChlKXtyZXR1cm4gdGhpcy5fbWFwLmdldChlLnRvU3RyaW5nKCkpfWhhcyhlKXtyZXR1cm4gdGhpcy5fbWFwLmhhcyhlLnRvU3RyaW5nKCkpfXB1dChlLHQpe3RoaXMuX21hcC5zZXQoZS50b1N0cmluZygpLHQpfXB1dEFsaWFzKGUsdCl7dGhpcy5fbWFwLnNldChlLnRvU3RyaW5nKCksdGhpcy5nZXQodCkpfVtTeW1ib2wuaXRlcmF0b3JdKCl7cmV0dXJuIHRoaXMuX21hcC52YWx1ZXMoKX1jbGVhcigpe3RoaXMuX21hcC5jbGVhcigpfSp2YWx1ZXMoKXt5aWVsZCp0aGlzLl9tYXAudmFsdWVzKCl9Kml0ZW1zKCl7Zm9yKGNvbnN0W2UsdF1vZiB0aGlzLl9tYXApeWllbGRbUmVmLmZyb21TdHJpbmcoZSksdF19fWZ1bmN0aW9uIGlzTmFtZShlLHQpe3JldHVybiBlIGluc3RhbmNlb2YgTmFtZSYmKHZvaWQgMD09PXR8fGUubmFtZT09PXQpfWZ1bmN0aW9uIGlzQ21kKGUsdCl7cmV0dXJuIGUgaW5zdGFuY2VvZiBDbWQmJih2b2lkIDA9PT10fHxlLmNtZD09PXQpfWZ1bmN0aW9uIGlzRGljdChlLHQpe3JldHVybiBlIGluc3RhbmNlb2YgRGljdCYmKHZvaWQgMD09PXR8fGlzTmFtZShlLmdldCgiVHlwZSIpLHQpKX1mdW5jdGlvbiBpc1JlZnNFcXVhbChlLHQpe3JldHVybiBlLm51bT09PXQubnVtJiZlLmdlbj09PXQuZ2VufWNsYXNzIEJhc2VTdHJlYW17Z2V0IGxlbmd0aCgpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBnZXR0ZXIgYGxlbmd0aGAgYWNjZXNzZWQiKX1nZXQgaXNFbXB0eSgpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBnZXR0ZXIgYGlzRW1wdHlgIGFjY2Vzc2VkIil9Z2V0IGlzRGF0YUxvYWRlZCgpe3JldHVybiBzaGFkb3codGhpcywiaXNEYXRhTG9hZGVkIiwhMCl9Z2V0Qnl0ZSgpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVgIGNhbGxlZCIpfWdldEJ5dGVzKGUpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVzYCBjYWxsZWQiKX1hc3luYyBnZXRJbWFnZURhdGEoZSx0KXtyZXR1cm4gdGhpcy5nZXRCeXRlcyhlLHQpfWFzeW5jIGFzeW5jR2V0Qnl0ZXMoKXt1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBhc3luY0dldEJ5dGVzYCBjYWxsZWQiKX1nZXQgaXNBc3luYygpe3JldHVybiExfWdldCBpc0FzeW5jRGVjb2Rlcigpe3JldHVybiExfWdldCBjYW5Bc3luY0RlY29kZUltYWdlRnJvbUJ1ZmZlcigpe3JldHVybiExfWFzeW5jIGdldFRyYW5zZmVyYWJsZUltYWdlKCl7cmV0dXJuIG51bGx9cGVla0J5dGUoKXtjb25zdCBlPXRoaXMuZ2V0Qnl0ZSgpOy0xIT09ZSYmdGhpcy5wb3MtLTtyZXR1cm4gZX1wZWVrQnl0ZXMoZSl7Y29uc3QgdD10aGlzLmdldEJ5dGVzKGUpO3RoaXMucG9zLT10Lmxlbmd0aDtyZXR1cm4gdH1nZXRVaW50MTYoKXtjb25zdCBlPXRoaXMuZ2V0Qnl0ZSgpLHQ9dGhpcy5nZXRCeXRlKCk7cmV0dXJuLTE9PT1lfHwtMT09PXQ/LTE6KGU8PDgpK3R9Z2V0SW50MzIoKXtyZXR1cm4odGhpcy5nZXRCeXRlKCk8PDI0KSsodGhpcy5nZXRCeXRlKCk8PDE2KSsodGhpcy5nZXRCeXRlKCk8PDgpK3RoaXMuZ2V0Qnl0ZSgpfWdldEJ5dGVSYW5nZShlLHQpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGdldEJ5dGVSYW5nZWAgY2FsbGVkIil9Z2V0U3RyaW5nKGUpe3JldHVybiBieXRlc1RvU3RyaW5nKHRoaXMuZ2V0Qnl0ZXMoZSkpfXNraXAoZSl7dGhpcy5wb3MrPWV8fDF9cmVzZXQoKXt1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGByZXNldGAgY2FsbGVkIil9bW92ZVN0YXJ0KCl7dW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgbW92ZVN0YXJ0YCBjYWxsZWQiKX1tYWtlU3ViU3RyZWFtKGUsdCxyPW51bGwpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYG1ha2VTdWJTdHJlYW1gIGNhbGxlZCIpfWdldEJhc2VTdHJlYW1zKCl7cmV0dXJuIG51bGx9fWNvbnN0IHVyPS9eWzEtOV1cLlxkJC8sZHI9MioqMzEtMSxmcj1bMSwwLDAsMSwwLDBdLGdyPVsiQ29sb3JTcGFjZSIsIkV4dEdTdGF0ZSIsIkZvbnQiLCJQYXR0ZXJuIiwiUHJvcGVydGllcyIsIlNoYWRpbmciLCJYT2JqZWN0Il0scHI9WyJFeHRHU3RhdGUiLCJGb250IiwiUHJvcGVydGllcyIsIlhPYmplY3QiXTtmdW5jdGlvbiBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZSl7bGV0IHQ7cmV0dXJuIGZ1bmN0aW9uKCl7aWYoZSl7dD1PYmplY3QuY3JlYXRlKG51bGwpO2UodCk7ZT1udWxsfXJldHVybiB0fX1jbGFzcyBNaXNzaW5nRGF0YUV4Y2VwdGlvbiBleHRlbmRzIGVye2NvbnN0cnVjdG9yKGUsdCl7c3VwZXIoYE1pc3NpbmcgZGF0YSBbJHtlfSwgJHt0fSlgLCJNaXNzaW5nRGF0YUV4Y2VwdGlvbiIpO3RoaXMuYmVnaW49ZTt0aGlzLmVuZD10fX1jbGFzcyBQYXJzZXJFT0ZFeGNlcHRpb24gZXh0ZW5kcyBlcntjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJQYXJzZXJFT0ZFeGNlcHRpb24iKX19Y2xhc3MgWFJlZkVudHJ5RXhjZXB0aW9uIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiWFJlZkVudHJ5RXhjZXB0aW9uIil9fWNsYXNzIFhSZWZQYXJzZUV4Y2VwdGlvbiBleHRlbmRzIGVye2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUsIlhSZWZQYXJzZUV4Y2VwdGlvbiIpfX1mdW5jdGlvbiBhcnJheUJ1ZmZlcnNUb0J5dGVzKGUpe2NvbnN0IHQ9ZS5sZW5ndGg7aWYoMD09PXQpcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKDE9PT10KXJldHVybiBuZXcgVWludDhBcnJheShlWzBdKTtsZXQgcj0wO2ZvcihsZXQgYT0wO2E8dDthKyspcis9ZVthXS5ieXRlTGVuZ3RoO2NvbnN0IGE9bmV3IFVpbnQ4QXJyYXkocik7bGV0IG49MDtmb3IobGV0IHI9MDtyPHQ7cisrKXtjb25zdCB0PW5ldyBVaW50OEFycmF5KGVbcl0pO2Euc2V0KHQsbik7bis9dC5ieXRlTGVuZ3RofXJldHVybiBhfWFzeW5jIGZ1bmN0aW9uIGZldGNoQmluYXJ5RGF0YShlKXtjb25zdCB0PWF3YWl0IGZldGNoKGUpO2lmKCF0Lm9rKXRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGZldGNoIGZpbGUgIiR7ZX0iIHdpdGggIiR7dC5zdGF0dXNUZXh0fSIuYCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KGF3YWl0IHQuYXJyYXlCdWZmZXIoKSl9ZnVuY3Rpb24gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDplLGtleTp0LGdldEFycmF5OnI9ITEsc3RvcFdoZW5Gb3VuZDphPSEwfSl7bGV0IG47Y29uc3QgaT1uZXcgUmVmU2V0O2Zvcig7ZSBpbnN0YW5jZW9mIERpY3QmJighZS5vYmpJZHx8IWkuaGFzKGUub2JqSWQpKTspe2Uub2JqSWQmJmkucHV0KGUub2JqSWQpO2NvbnN0IHM9cj9lLmdldEFycmF5KHQpOmUuZ2V0KHQpO2lmKHZvaWQgMCE9PXMpe2lmKGEpcmV0dXJuIHM7KG58fD1bXSkucHVzaChzKX1lPWUuZ2V0KCJQYXJlbnQiKX1yZXR1cm4gbn1jb25zdCBtcj1bIiIsIkMiLCJDQyIsIkNDQyIsIkNEIiwiRCIsIkRDIiwiRENDIiwiRENDQyIsIkNNIiwiIiwiWCIsIlhYIiwiWFhYIiwiWEwiLCJMIiwiTFgiLCJMWFgiLCJMWFhYIiwiWEMiLCIiLCJJIiwiSUkiLCJJSUkiLCJJViIsIlYiLCJWSSIsIlZJSSIsIlZJSUkiLCJJWCJdO2Z1bmN0aW9uIHRvUm9tYW5OdW1lcmFscyhlLHQ9ITEpe2Fzc2VydChOdW1iZXIuaXNJbnRlZ2VyKGUpJiZlPjAsIlRoZSBudW1iZXIgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlci4iKTtjb25zdCByPSJNIi5yZXBlYXQoZS8xZTN8MCkrbXJbZSUxZTMvMTAwfDBdK21yWzEwKyhlJTEwMC8xMHwwKV0rbXJbMjArZSUxMF07cmV0dXJuIHQ/ci50b0xvd2VyQ2FzZSgpOnJ9ZnVuY3Rpb24gbG9nMihlKXtyZXR1cm4gZT4wP01hdGguY2VpbChNYXRoLmxvZzIoZSkpOjB9ZnVuY3Rpb24gcmVhZEludDgoZSx0KXtyZXR1cm4gZVt0XTw8MjQ+PjI0fWZ1bmN0aW9uIHJlYWRJbnQxNihlLHQpe3JldHVybihlW3RdPDwyNHxlW3QrMV08PDE2KT4+MTZ9ZnVuY3Rpb24gcmVhZFVpbnQxNihlLHQpe3JldHVybiBlW3RdPDw4fGVbdCsxXX1mdW5jdGlvbiByZWFkVWludDMyKGUsdCl7cmV0dXJuKGVbdF08PDI0fGVbdCsxXTw8MTZ8ZVt0KzJdPDw4fGVbdCszXSk+Pj4wfWZ1bmN0aW9uIGlzV2hpdGVTcGFjZShlKXtyZXR1cm4gMzI9PT1lfHw5PT09ZXx8MTM9PT1lfHwxMD09PWV9ZnVuY3Rpb24gaXNOdW1iZXJBcnJheShlLHQpe3JldHVybiBBcnJheS5pc0FycmF5KGUpPyhudWxsPT09dHx8ZS5sZW5ndGg9PT10KSYmZS5ldmVyeShlPT4ibnVtYmVyIj09dHlwZW9mIGUpOkFycmF5QnVmZmVyLmlzVmlldyhlKSYmIShlIGluc3RhbmNlb2YgQmlnSW50NjRBcnJheXx8ZSBpbnN0YW5jZW9mIEJpZ1VpbnQ2NEFycmF5KSYmKG51bGw9PT10fHxlLmxlbmd0aD09PXQpfWZ1bmN0aW9uIGxvb2t1cE1hdHJpeChlLHQpe3JldHVybiBpc051bWJlckFycmF5KGUsNik/ZTp0fWZ1bmN0aW9uIGxvb2t1cFJlY3QoZSx0KXtyZXR1cm4gaXNOdW1iZXJBcnJheShlLDQpP2U6dH1mdW5jdGlvbiBsb29rdXBOb3JtYWxSZWN0KGUsdCl7cmV0dXJuIGlzTnVtYmVyQXJyYXkoZSw0KT9VdGlsLm5vcm1hbGl6ZVJlY3QoZSk6dH1mdW5jdGlvbiBwYXJzZVhGQVBhdGgoZSl7Y29uc3QgdD0vKC4rKVxbKFxkKylcXSQvO3JldHVybiBlLnNwbGl0KCIuIikubWFwKGU9Pntjb25zdCByPWUubWF0Y2godCk7cmV0dXJuIHI/e25hbWU6clsxXSxwb3M6cGFyc2VJbnQoclsyXSwxMCl9OntuYW1lOmUscG9zOjB9fSl9ZnVuY3Rpb24gZXNjYXBlUERGTmFtZShlKXtjb25zdCB0PVtdO2xldCByPTA7Zm9yKGxldCBhPTAsbj1lLmxlbmd0aDthPG47YSsrKXtjb25zdCBuPWUuY2hhckNvZGVBdChhKTtpZihuPDMzfHxuPjEyNnx8MzU9PT1ufHw0MD09PW58fDQxPT09bnx8NjA9PT1ufHw2Mj09PW58fDkxPT09bnx8OTM9PT1ufHwxMjM9PT1ufHwxMjU9PT1ufHw0Nz09PW58fDM3PT09bil7cjxhJiZ0LnB1c2goZS5zdWJzdHJpbmcocixhKSk7dC5wdXNoKGAjJHtuLnRvU3RyaW5nKDE2KX1gKTtyPWErMX19aWYoMD09PXQubGVuZ3RoKXJldHVybiBlO3I8ZS5sZW5ndGgmJnQucHVzaChlLnN1YnN0cmluZyhyLGUubGVuZ3RoKSk7cmV0dXJuIHQuam9pbigiIil9ZnVuY3Rpb24gZXNjYXBlU3RyaW5nKGUpe3JldHVybiBlLnJlcGxhY2VBbGwoLyhbKClcXFxuXHJdKS9nLGU9PiJcbiI9PT1lPyJcXG4iOiJcciI9PT1lPyJcXHIiOmBcXCR7ZX1gKX1mdW5jdGlvbiBfY29sbGVjdEpTKGUsdCxyLGEpe2lmKCFlKXJldHVybjtsZXQgbj1udWxsO2lmKGUgaW5zdGFuY2VvZiBSZWYpe2lmKGEuaGFzKGUpKXJldHVybjtuPWU7YS5wdXQobik7ZT10LmZldGNoKGUpfWlmKEFycmF5LmlzQXJyYXkoZSkpZm9yKGNvbnN0IG4gb2YgZSlfY29sbGVjdEpTKG4sdCxyLGEpO2Vsc2UgaWYoZSBpbnN0YW5jZW9mIERpY3Qpe2lmKGlzTmFtZShlLmdldCgiUyIpLCJKYXZhU2NyaXB0Iikpe2NvbnN0IHQ9ZS5nZXQoIkpTIik7bGV0IGE7dCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0/YT10LmdldFN0cmluZygpOiJzdHJpbmciPT10eXBlb2YgdCYmKGE9dCk7YSYmPXN0cmluZ1RvUERGU3RyaW5nKGEsITApLnJlcGxhY2VBbGwoIlwwIiwiIik7YSYmci5wdXNoKGEudHJpbSgpKX1fY29sbGVjdEpTKGUuZ2V0UmF3KCJOZXh0IiksdCxyLGEpfW4mJmEucmVtb3ZlKG4pfWZ1bmN0aW9uIGNvbGxlY3RBY3Rpb25zKGUsdCxyKXtjb25zdCBhPU9iamVjdC5jcmVhdGUobnVsbCksbj1nZXRJbmhlcml0YWJsZVByb3BlcnR5KHtkaWN0OnQsa2V5OiJBQSIsc3RvcFdoZW5Gb3VuZDohMX0pO2lmKG4pZm9yKGxldCB0PW4ubGVuZ3RoLTE7dD49MDt0LS0pe2NvbnN0IGk9blt0XTtpZihpIGluc3RhbmNlb2YgRGljdClmb3IoY29uc3QgdCBvZiBpLmdldEtleXMoKSl7Y29uc3Qgbj1yW3RdO2lmKCFuKWNvbnRpbnVlO2NvbnN0IHM9W107X2NvbGxlY3RKUyhpLmdldFJhdyh0KSxlLHMsbmV3IFJlZlNldCk7cy5sZW5ndGg+MCYmKGFbbl09cyl9fWlmKHQuaGFzKCJBIikpe2NvbnN0IHI9W107X2NvbGxlY3RKUyh0LmdldCgiQSIpLGUscixuZXcgUmVmU2V0KTtyLmxlbmd0aD4wJiYoYS5BY3Rpb249cil9cmV0dXJuIG9iamVjdFNpemUoYSk+MD9hOm51bGx9Y29uc3QgYnI9ezYwOiImbHQ7Iiw2MjoiJmd0OyIsMzg6IiZhbXA7IiwzNDoiJnF1b3Q7IiwzOToiJmFwb3M7In07ZnVuY3Rpb24qY29kZVBvaW50SXRlcihlKXtmb3IobGV0IHQ9MCxyPWUubGVuZ3RoO3Q8cjt0Kyspe2NvbnN0IHI9ZS5jb2RlUG9pbnRBdCh0KTtyPjU1Mjk1JiYocjw1NzM0NHx8cj42NTUzMykmJnQrKzt5aWVsZCByfX1mdW5jdGlvbiBlbmNvZGVUb1htbFN0cmluZyhlKXtjb25zdCB0PVtdO2xldCByPTA7Zm9yKGxldCBhPTAsbj1lLmxlbmd0aDthPG47YSsrKXtjb25zdCBuPWUuY29kZVBvaW50QXQoYSk7aWYoMzI8PW4mJm48PTEyNil7Y29uc3QgaT1icltuXTtpZihpKXtyPGEmJnQucHVzaChlLnN1YnN0cmluZyhyLGEpKTt0LnB1c2goaSk7cj1hKzF9fWVsc2V7cjxhJiZ0LnB1c2goZS5zdWJzdHJpbmcocixhKSk7dC5wdXNoKGAmI3gke24udG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCl9O2ApO24+NTUyOTUmJihuPDU3MzQ0fHxuPjY1NTMzKSYmYSsrO3I9YSsxfX1pZigwPT09dC5sZW5ndGgpcmV0dXJuIGU7cjxlLmxlbmd0aCYmdC5wdXNoKGUuc3Vic3RyaW5nKHIsZS5sZW5ndGgpKTtyZXR1cm4gdC5qb2luKCIiKX1mdW5jdGlvbiB2YWxpZGF0ZUZvbnROYW1lKGUsdD0hMSl7Y29uc3Qgcj0vXigifCcpLiooInwnKSQvLmV4ZWMoZSk7aWYociYmclsxXT09PXJbMl0pe2lmKG5ldyBSZWdFeHAoYFteXFxcXF0ke3JbMV19YCkudGVzdChlLnNsaWNlKDEsLTEpKSl7dCYmd2FybihgRm9udEZhbWlseSBjb250YWlucyB1bmVzY2FwZWQgJHtyWzFdfTogJHtlfS5gKTtyZXR1cm4hMX19ZWxzZSBmb3IoY29uc3QgciBvZiBlLnNwbGl0KC9bIFx0XSsvKSlpZigvXihcZHwoLShcZHwtKSkpLy50ZXN0KHIpfHwhL15bXHctXFxdKyQvLnRlc3Qocikpe3QmJndhcm4oYEZvbnRGYW1pbHkgY29udGFpbnMgaW52YWxpZCA8Y3VzdG9tLWlkZW50PjogJHtlfS5gKTtyZXR1cm4hMX1yZXR1cm4hMH1mdW5jdGlvbiB2YWxpZGF0ZUNTU0ZvbnQoZSl7Y29uc3QgdD1uZXcgU2V0KFsiMTAwIiwiMjAwIiwiMzAwIiwiNDAwIiwiNTAwIiwiNjAwIiwiNzAwIiwiODAwIiwiOTAwIiwiMTAwMCIsIm5vcm1hbCIsImJvbGQiLCJib2xkZXIiLCJsaWdodGVyIl0pLHtmb250RmFtaWx5OnIsZm9udFdlaWdodDphLGl0YWxpY0FuZ2xlOm59PWU7aWYoIXZhbGlkYXRlRm9udE5hbWUociwhMCkpcmV0dXJuITE7Y29uc3QgaT1hP2EudG9TdHJpbmcoKToiIjtlLmZvbnRXZWlnaHQ9dC5oYXMoaSk/aToiNDAwIjtjb25zdCBzPXBhcnNlRmxvYXQobik7ZS5pdGFsaWNBbmdsZT1pc05hTihzKXx8czwtOTB8fHM+OTA/IjE0IjpuLnRvU3RyaW5nKCk7cmV0dXJuITB9ZnVuY3Rpb24gcmVjb3ZlckpzVVJMKGUpe2NvbnN0IHQ9bmV3IFJlZ0V4cCgiXlxccyooIitbImFwcC5sYXVuY2hVUkwiLCJ3aW5kb3cub3BlbiIsInhmYS5ob3N0LmdvdG9VUkwiXS5qb2luKCJ8IikucmVwbGFjZUFsbCgiLiIsIlxcLiIpKyIpXFwoKD86J3xcIikoW14nXCJdKikoPzonfFwiKSg/OixcXHMqKFxcdyspXFwpfFxcKSkiLCJpIikuZXhlYyhlKTtyZXR1cm4gdD8uWzJdP3t1cmw6dFsyXSxuZXdXaW5kb3c6ImFwcC5sYXVuY2hVUkwiPT09dFsxXSYmInRydWUiPT09dFszXX06bnVsbH1mdW5jdGlvbiBudW1iZXJUb1N0cmluZyhlKXtpZihOdW1iZXIuaXNJbnRlZ2VyKGUpKXJldHVybiBlLnRvU3RyaW5nKCk7Y29uc3QgdD1NYXRoLnJvdW5kKDEwMCplKTtyZXR1cm4gdCUxMDA9PTA/KHQvMTAwKS50b1N0cmluZygpOnQlMTA9PTA/ZS50b0ZpeGVkKDEpOmUudG9GaXhlZCgyKX1mdW5jdGlvbiBnZXROZXdBbm5vdGF0aW9uc01hcChlKXtpZighZSlyZXR1cm4gbnVsbDtjb25zdCB0PW5ldyBNYXA7Zm9yKGNvbnN0W3IsYV1vZiBlKXtpZighci5zdGFydHNXaXRoKHApKWNvbnRpbnVlO2xldCBlPXQuZ2V0KGEucGFnZUluZGV4KTtpZighZSl7ZT1bXTt0LnNldChhLnBhZ2VJbmRleCxlKX1lLnB1c2goYSl9cmV0dXJuIHQuc2l6ZT4wP3Q6bnVsbH1mdW5jdGlvbiBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGUpe3JldHVybiBudWxsPT1lfHxmdW5jdGlvbiBpc0FzY2lpKGUpe2lmKCJzdHJpbmciIT10eXBlb2YgZSlyZXR1cm4hMTtyZXR1cm4hZXx8L15bXHgwMC1ceDdGXSokLy50ZXN0KGUpfShlKT9lOnN0cmluZ1RvVVRGMTZTdHJpbmcoZSwhMCl9ZnVuY3Rpb24gc3RyaW5nVG9VVEYxNkhleFN0cmluZyhlKXtjb25zdCB0PVtdO2ZvcihsZXQgcj0wLGE9ZS5sZW5ndGg7cjxhO3IrKyl7Y29uc3QgYT1lLmNoYXJDb2RlQXQocik7dC5wdXNoKHRyW2E+PjgmMjU1XSx0clsyNTUmYV0pfXJldHVybiB0LmpvaW4oIiIpfWZ1bmN0aW9uIHN0cmluZ1RvVVRGMTZTdHJpbmcoZSx0PSExKXtjb25zdCByPVtdO3QmJnIucHVzaCgiw77DvyIpO2ZvcihsZXQgdD0wLGE9ZS5sZW5ndGg7dDxhO3QrKyl7Y29uc3QgYT1lLmNoYXJDb2RlQXQodCk7ci5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYT4+OCYyNTUpLFN0cmluZy5mcm9tQ2hhckNvZGUoMjU1JmEpKX1yZXR1cm4gci5qb2luKCIiKX1mdW5jdGlvbiBnZXRSb3RhdGlvbk1hdHJpeChlLHQscil7c3dpdGNoKGUpe2Nhc2UgOTA6cmV0dXJuWzAsMSwtMSwwLHQsMF07Y2FzZSAxODA6cmV0dXJuWy0xLDAsMCwtMSx0LHJdO2Nhc2UgMjcwOnJldHVyblswLC0xLDEsMCwwLHJdO2RlZmF1bHQ6dGhyb3cgbmV3IEVycm9yKCJJbnZhbGlkIHJvdGF0aW9uIil9fWZ1bmN0aW9uIGdldFNpemVJbkJ5dGVzKGUpe3JldHVybiBNYXRoLmNlaWwoTWF0aC5jZWlsKE1hdGgubG9nMigxK2UpKS84KX1fX3dlYnBhY2tfcmVxdWlyZV9fKDQ2MDMpLF9fd2VicGFja19yZXF1aXJlX18oNzU2NiksX193ZWJwYWNrX3JlcXVpcmVfXyg4NzIxKTtjbGFzcyBRQ01Te3N0YXRpYyNyPW51bGw7c3RhdGljIF9tZW1vcnk9bnVsbDtzdGF0aWMgX211c3RBZGRBbHBoYT0hMTtzdGF0aWMgX2Rlc3RCdWZmZXI9bnVsbDtzdGF0aWMgX2Rlc3RPZmZzZXQ9MDtzdGF0aWMgX2Rlc3RMZW5ndGg9MDtzdGF0aWMgX2Nzc0NvbG9yPSIiO3N0YXRpYyBfbWFrZUhleENvbG9yPW51bGw7c3RhdGljIGdldCBfbWVtb3J5QXJyYXkoKXtjb25zdCBlPXRoaXMuI3I7cmV0dXJuIGU/LmJ5dGVMZW5ndGg/ZTp0aGlzLiNyPW5ldyBVaW50OEFycmF5KHRoaXMuX21lbW9yeS5idWZmZXIpfX1sZXQgeXI7Y29uc3Qgd3I9InVuZGVmaW5lZCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoInV0Zi04Iix7aWdub3JlQk9NOiEwLGZhdGFsOiEwfSk6e2RlY29kZTooKT0+e3Rocm93IEVycm9yKCJUZXh0RGVjb2RlciBub3QgYXZhaWxhYmxlIil9fTsidW5kZWZpbmVkIiE9dHlwZW9mIFRleHREZWNvZGVyJiZ3ci5kZWNvZGUoKTtsZXQgeHI9bnVsbDtmdW5jdGlvbiBnZXRVaW50OEFycmF5TWVtb3J5MCgpe251bGwhPT14ciYmMCE9PXhyLmJ5dGVMZW5ndGh8fCh4cj1uZXcgVWludDhBcnJheSh5ci5tZW1vcnkuYnVmZmVyKSk7cmV0dXJuIHhyfWxldCBTcj0wO2Z1bmN0aW9uIHBhc3NBcnJheThUb1dhc20wKGUsdCl7Y29uc3Qgcj10KDEqZS5sZW5ndGgsMSk+Pj4wO2dldFVpbnQ4QXJyYXlNZW1vcnkwKCkuc2V0KGUsci8xKTtTcj1lLmxlbmd0aDtyZXR1cm4gcn1jb25zdCBBcj1PYmplY3QuZnJlZXplKHtSR0I4OjAsMDoiUkdCOCIsUkdCQTg6MSwxOiJSR0JBOCIsQkdSQTg6MiwyOiJCR1JBOCIsR3JheTg6MywzOiJHcmF5OCIsR3JheUE4OjQsNDoiR3JheUE4IixDTVlLOjUsNToiQ01ZSyJ9KSxrcj1PYmplY3QuZnJlZXplKHtQZXJjZXB0dWFsOjAsMDoiUGVyY2VwdHVhbCIsUmVsYXRpdmVDb2xvcmltZXRyaWM6MSwxOiJSZWxhdGl2ZUNvbG9yaW1ldHJpYyIsU2F0dXJhdGlvbjoyLDI6IlNhdHVyYXRpb24iLEFic29sdXRlQ29sb3JpbWV0cmljOjMsMzoiQWJzb2x1dGVDb2xvcmltZXRyaWMifSk7ZnVuY3Rpb24gX193YmdfZ2V0X2ltcG9ydHMoKXtjb25zdCBlPXt3Ymc6e319O2Uud2JnLl9fd2JnX2NvcHlyZXN1bHRfYjA4ZWU3ZDI3M2YyOTVkZD1mdW5jdGlvbihlLHQpeyFmdW5jdGlvbiBjb3B5X3Jlc3VsdChlLHQpe2NvbnN0e19tdXN0QWRkQWxwaGE6cixfZGVzdEJ1ZmZlcjphLF9kZXN0T2Zmc2V0Om4sX2Rlc3RMZW5ndGg6aSxfbWVtb3J5QXJyYXk6c309UUNNUztpZih0IT09aSlpZihyKWZvcihsZXQgcj1lLGk9ZSt0LG89bjtyPGk7cis9MyxvKz00KXthW29dPXNbcl07YVtvKzFdPXNbcisxXTthW28rMl09c1tyKzJdO2FbbyszXT0yNTV9ZWxzZSBmb3IobGV0IHI9ZSxpPWUrdCxvPW47cjxpO3IrPTMsbys9NCl7YVtvXT1zW3JdO2FbbysxXT1zW3IrMV07YVtvKzJdPXNbcisyXX1lbHNlIGEuc2V0KHMuc3ViYXJyYXkoZSxlK3QpLG4pfShlPj4+MCx0Pj4+MCl9O2Uud2JnLl9fd2JnX2NvcHlyZ2JfZDYwY2UxN2JiMDVkOWI2Nz1mdW5jdGlvbihlKXshZnVuY3Rpb24gY29weV9yZ2IoZSl7Y29uc3R7X2Rlc3RCdWZmZXI6dCxfZGVzdE9mZnNldDpyLF9tZW1vcnlBcnJheTphfT1RQ01TO3Rbcl09YVtlXTt0W3IrMV09YVtlKzFdO3RbcisyXT1hW2UrMl19KGU+Pj4wKX07ZS53YmcuX193YmdfbWFrZWNzc1JHQl84OTNiZjBjZDlmZGIzMDJkPWZ1bmN0aW9uKGUpeyFmdW5jdGlvbiBtYWtlX2Nzc1JHQihlKXtjb25zdHtfbWVtb3J5QXJyYXk6dH09UUNNUztRQ01TLl9jc3NDb2xvcj1RQ01TLl9tYWtlSGV4Q29sb3IodFtlXSx0W2UrMV0sdFtlKzJdKX0oZT4+PjApfTtlLndiZy5fX3diaW5kZ2VuX2luaXRfZXh0ZXJucmVmX3RhYmxlPWZ1bmN0aW9uKCl7Y29uc3QgZT15ci5fX3diaW5kZ2VuX2V4cG9ydF8wLHQ9ZS5ncm93KDQpO2Uuc2V0KDAsdm9pZCAwKTtlLnNldCh0KzAsdm9pZCAwKTtlLnNldCh0KzEsbnVsbCk7ZS5zZXQodCsyLCEwKTtlLnNldCh0KzMsITEpfTtlLndiZy5fX3diaW5kZ2VuX3Rocm93PWZ1bmN0aW9uKGUsdCl7dGhyb3cgbmV3IEVycm9yKGZ1bmN0aW9uIGdldFN0cmluZ0Zyb21XYXNtMChlLHQpe2U+Pj49MDtyZXR1cm4gd3IuZGVjb2RlKGdldFVpbnQ4QXJyYXlNZW1vcnkwKCkuc3ViYXJyYXkoZSxlK3QpKX0oZSx0KSl9O3JldHVybiBlfWZ1bmN0aW9uIF9fd2JnX2ZpbmFsaXplX2luaXQoZSx0KXt5cj1lLmV4cG9ydHM7X193YmdfaW5pdC5fX3diaW5kZ2VuX3dhc21fbW9kdWxlPXQ7eHI9bnVsbDt5ci5fX3diaW5kZ2VuX3N0YXJ0KCk7cmV0dXJuIHlyfWFzeW5jIGZ1bmN0aW9uIF9fd2JnX2luaXQoZSl7aWYodm9pZCAwIT09eXIpcmV0dXJuIHlyO3ZvaWQgMCE9PWUmJihPYmplY3QuZ2V0UHJvdG90eXBlT2YoZSk9PT1PYmplY3QucHJvdG90eXBlPyh7bW9kdWxlX29yX3BhdGg6ZX09ZSk6Y29uc29sZS53YXJuKCJ1c2luZyBkZXByZWNhdGVkIHBhcmFtZXRlcnMgZm9yIHRoZSBpbml0aWFsaXphdGlvbiBmdW5jdGlvbjsgcGFzcyBhIHNpbmdsZSBvYmplY3QgaW5zdGVhZCIpKTtjb25zdCB0PV9fd2JnX2dldF9pbXBvcnRzKCk7KCJzdHJpbmciPT10eXBlb2YgZXx8ImZ1bmN0aW9uIj09dHlwZW9mIFJlcXVlc3QmJmUgaW5zdGFuY2VvZiBSZXF1ZXN0fHwiZnVuY3Rpb24iPT10eXBlb2YgVVJMJiZlIGluc3RhbmNlb2YgVVJMKSYmKGU9ZmV0Y2goZSkpO2NvbnN0e2luc3RhbmNlOnIsbW9kdWxlOmF9PWF3YWl0IGFzeW5jIGZ1bmN0aW9uIF9fd2JnX2xvYWQoZSx0KXtpZigiZnVuY3Rpb24iPT10eXBlb2YgUmVzcG9uc2UmJmUgaW5zdGFuY2VvZiBSZXNwb25zZSl7aWYoImZ1bmN0aW9uIj09dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKXRyeXtyZXR1cm4gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmcoZSx0KX1jYXRjaCh0KXtpZigiYXBwbGljYXRpb24vd2FzbSI9PWUuaGVhZGVycy5nZXQoIkNvbnRlbnQtVHlwZSIpKXRocm93IHQ7Y29uc29sZS53YXJuKCJgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGVTdHJlYW1pbmdgIGZhaWxlZCBiZWNhdXNlIHlvdXIgc2VydmVyIGRvZXMgbm90IHNlcnZlIFdhc20gd2l0aCBgYXBwbGljYXRpb24vd2FzbWAgTUlNRSB0eXBlLiBGYWxsaW5nIGJhY2sgdG8gYFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlYCB3aGljaCBpcyBzbG93ZXIuIE9yaWdpbmFsIGVycm9yOlxuIix0KX1jb25zdCByPWF3YWl0IGUuYXJyYXlCdWZmZXIoKTtyZXR1cm4gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUocix0KX17Y29uc3Qgcj1hd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShlLHQpO3JldHVybiByIGluc3RhbmNlb2YgV2ViQXNzZW1ibHkuSW5zdGFuY2U/e2luc3RhbmNlOnIsbW9kdWxlOmV9OnJ9fShhd2FpdCBlLHQpO3JldHVybiBfX3diZ19maW5hbGl6ZV9pbml0KHIsYSl9Y2xhc3MgQ29sb3JTcGFjZXtzdGF0aWMjYT1uZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7Y29uc3RydWN0b3IoZSx0KXt0aGlzLm5hbWU9ZTt0aGlzLm51bUNvbXBzPXR9Z2V0UmdiKGUsdCxyPW5ldyBVaW50OENsYW1wZWRBcnJheSgzKSl7dGhpcy5nZXRSZ2JJdGVtKGUsdCxyLDApO3JldHVybiByfWdldFJnYkhleChlLHQpe2NvbnN0IHI9dGhpcy5nZXRSZ2IoZSx0LENvbG9yU3BhY2UuI2EpO3JldHVybiBVdGlsLm1ha2VIZXhDb2xvcihyWzBdLHJbMV0sclsyXSl9Z2V0UmdiSXRlbShlLHQscixhKXt1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIENvbG9yU3BhY2UuZ2V0UmdiSXRlbSIpfWdldFJnYkJ1ZmZlcihlLHQscixhLG4saSxzKXt1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIENvbG9yU3BhY2UuZ2V0UmdiQnVmZmVyIil9Z2V0T3V0cHV0TGVuZ3RoKGUsdCl7dW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldE91dHB1dExlbmd0aCIpfWlzUGFzc3Rocm91Z2goZSl7cmV0dXJuITF9aXNEZWZhdWx0RGVjb2RlKGUsdCl7cmV0dXJuIENvbG9yU3BhY2UuaXNEZWZhdWx0RGVjb2RlKGUsdGhpcy5udW1Db21wcyl9ZmlsbFJnYihlLHQscixhLG4saSxzLG8sYyl7Y29uc3QgbD10KnI7bGV0IGg9bnVsbDtjb25zdCB1PTE8PHMsZD1yIT09bnx8dCE9PWE7aWYodGhpcy5pc1Bhc3N0aHJvdWdoKHMpKWg9bztlbHNlIGlmKDE9PT10aGlzLm51bUNvbXBzJiZsPnUmJiJEZXZpY2VHcmF5IiE9PXRoaXMubmFtZSYmIkRldmljZVJHQiIhPT10aGlzLm5hbWUpe2NvbnN0IHQ9czw9OD9uZXcgVWludDhBcnJheSh1KTpuZXcgVWludDE2QXJyYXkodSk7Zm9yKGxldCBlPTA7ZTx1O2UrKyl0W2VdPWU7Y29uc3Qgcj1uZXcgVWludDhDbGFtcGVkQXJyYXkoMyp1KTt0aGlzLmdldFJnYkJ1ZmZlcih0LDAsdSxyLDAscywwKTtpZihkKXtoPW5ldyBVaW50OEFycmF5KDMqbCk7bGV0IGU9MDtmb3IobGV0IHQ9MDt0PGw7Kyt0KXtjb25zdCBhPTMqb1t0XTtoW2UrK109clthXTtoW2UrK109clthKzFdO2hbZSsrXT1yW2ErMl19fWVsc2V7bGV0IHQ9MDtmb3IobGV0IGE9MDthPGw7KythKXtjb25zdCBuPTMqb1thXTtlW3QrK109cltuXTtlW3QrK109cltuKzFdO2VbdCsrXT1yW24rMl07dCs9Y319fWVsc2UgaWYoZCl7aD1uZXcgVWludDhDbGFtcGVkQXJyYXkoMypsKTt0aGlzLmdldFJnYkJ1ZmZlcihvLDAsbCxoLDAscywwKX1lbHNlIHRoaXMuZ2V0UmdiQnVmZmVyKG8sMCxhKmksZSwwLHMsYyk7aWYoaClpZihkKSFmdW5jdGlvbiByZXNpemVSZ2JJbWFnZShlLHQscixhLG4saSxzKXtzPTEhPT1zPzA6cztjb25zdCBvPXIvbixjPWEvaTtsZXQgbCxoPTA7Y29uc3QgdT1uZXcgVWludDE2QXJyYXkobiksZD0zKnI7Zm9yKGxldCBlPTA7ZTxuO2UrKyl1W2VdPTMqTWF0aC5mbG9vcihlKm8pO2ZvcihsZXQgcj0wO3I8aTtyKyspe2NvbnN0IGE9TWF0aC5mbG9vcihyKmMpKmQ7Zm9yKGxldCByPTA7cjxuO3IrKyl7bD1hK3Vbcl07dFtoKytdPWVbbCsrXTt0W2grK109ZVtsKytdO3RbaCsrXT1lW2wrK107aCs9c319fShoLGUsdCxyLGEsbixjKTtlbHNle2xldCB0PTAscj0wO2ZvcihsZXQgbj0wLHM9YSppO248cztuKyspe2VbdCsrXT1oW3IrK107ZVt0KytdPWhbcisrXTtlW3QrK109aFtyKytdO3QrPWN9fX1nZXQgdXNlc1plcm9Ub09uZVJhbmdlKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJ1c2VzWmVyb1RvT25lUmFuZ2UiLCEwKX1zdGF0aWMgaXNEZWZhdWx0RGVjb2RlKGUsdCl7aWYoIUFycmF5LmlzQXJyYXkoZSkpcmV0dXJuITA7aWYoMip0IT09ZS5sZW5ndGgpe3dhcm4oIlRoZSBkZWNvZGUgbWFwIGlzIG5vdCB0aGUgY29ycmVjdCBsZW5ndGgiKTtyZXR1cm4hMH1mb3IobGV0IHQ9MCxyPWUubGVuZ3RoO3Q8cjt0Kz0yKWlmKDAhPT1lW3RdfHwxIT09ZVt0KzFdKXJldHVybiExO3JldHVybiEwfX1jbGFzcyBBbHRlcm5hdGVDUyBleHRlbmRzIENvbG9yU3BhY2V7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKCJBbHRlcm5hdGUiLGUpO3RoaXMuYmFzZT10O3RoaXMudGludEZuPXI7dGhpcy50bXBCdWY9bmV3IEZsb2F0MzJBcnJheSh0Lm51bUNvbXBzKX1nZXRSZ2JJdGVtKGUsdCxyLGEpe2NvbnN0IG49dGhpcy50bXBCdWY7dGhpcy50aW50Rm4oZSx0LG4sMCk7dGhpcy5iYXNlLmdldFJnYkl0ZW0obiwwLHIsYSl9Z2V0UmdiQnVmZmVyKGUsdCxyLGEsbixpLHMpe2NvbnN0IG89dGhpcy50aW50Rm4sYz10aGlzLmJhc2UsbD0xLygoMTw8aSktMSksaD1jLm51bUNvbXBzLHU9Yy51c2VzWmVyb1RvT25lUmFuZ2UsZD0oYy5pc1Bhc3N0aHJvdWdoKDgpfHwhdSkmJjA9PT1zO2xldCBmPWQ/bjowO2NvbnN0IGc9ZD9hOm5ldyBVaW50OENsYW1wZWRBcnJheShoKnIpLHA9dGhpcy5udW1Db21wcyxtPW5ldyBGbG9hdDMyQXJyYXkocCksYj1uZXcgRmxvYXQzMkFycmF5KGgpO2xldCB5LHc7Zm9yKHk9MDt5PHI7eSsrKXtmb3Iodz0wO3c8cDt3KyspbVt3XT1lW3QrK10qbDtvKG0sMCxiLDApO2lmKHUpZm9yKHc9MDt3PGg7dysrKWdbZisrXT0yNTUqYlt3XTtlbHNle2MuZ2V0UmdiSXRlbShiLDAsZyxmKTtmKz1ofX1kfHxjLmdldFJnYkJ1ZmZlcihnLDAscixhLG4sOCxzKX1nZXRPdXRwdXRMZW5ndGgoZSx0KXtyZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChlKnRoaXMuYmFzZS5udW1Db21wcy90aGlzLm51bUNvbXBzLHQpfX1jbGFzcyBQYXR0ZXJuQ1MgZXh0ZW5kcyBDb2xvclNwYWNle2NvbnN0cnVjdG9yKGUpe3N1cGVyKCJQYXR0ZXJuIixudWxsKTt0aGlzLmJhc2U9ZX1pc0RlZmF1bHREZWNvZGUoZSx0KXt1bnJlYWNoYWJsZSgiU2hvdWxkIG5vdCBjYWxsIFBhdHRlcm5DUy5pc0RlZmF1bHREZWNvZGUiKX19Y2xhc3MgSW5kZXhlZENTIGV4dGVuZHMgQ29sb3JTcGFjZXtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIoIkluZGV4ZWQiLDEpO3RoaXMuYmFzZT1lO3RoaXMuaGlnaFZhbD10O2NvbnN0IGE9ZS5udW1Db21wcyoodCsxKTt0aGlzLmxvb2t1cD1uZXcgVWludDhBcnJheShhKTtpZihyIGluc3RhbmNlb2YgQmFzZVN0cmVhbSl7Y29uc3QgZT1yLmdldEJ5dGVzKGEpO3RoaXMubG9va3VwLnNldChlKX1lbHNle2lmKCJzdHJpbmciIT10eXBlb2Ygcil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEluZGV4ZWRDUyAtIHVucmVjb2duaXplZCBsb29rdXAgdGFibGU6ICR7cn1gKTtmb3IobGV0IGU9MDtlPGE7KytlKXRoaXMubG9va3VwW2VdPTI1NSZyLmNoYXJDb2RlQXQoZSl9fWdldFJnYkl0ZW0oZSx0LHIsYSl7Y29uc3R7YmFzZTpuLGhpZ2hWYWw6aSxsb29rdXA6c309dGhpcyxvPU1hdGhDbGFtcChNYXRoLnJvdW5kKGVbdF0pLDAsaSkqbi5udW1Db21wcztuLmdldFJnYkJ1ZmZlcihzLG8sMSxyLGEsOCwwKX1nZXRSZ2JCdWZmZXIoZSx0LHIsYSxuLGkscyl7Y29uc3R7YmFzZTpvLGhpZ2hWYWw6Yyxsb29rdXA6bH09dGhpcyx7bnVtQ29tcHM6aH09byx1PW8uZ2V0T3V0cHV0TGVuZ3RoKGgscyk7Zm9yKGxldCBpPTA7aTxyOysraSl7Y29uc3Qgcj1NYXRoQ2xhbXAoTWF0aC5yb3VuZChlW3QrK10pLDAsYykqaDtvLmdldFJnYkJ1ZmZlcihsLHIsMSxhLG4sOCxzKTtuKz11fX1nZXRPdXRwdXRMZW5ndGgoZSx0KXtyZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChlKnRoaXMuYmFzZS5udW1Db21wcyx0KX1pc0RlZmF1bHREZWNvZGUoZSx0KXtpZighQXJyYXkuaXNBcnJheShlKSlyZXR1cm4hMDtpZigyIT09ZS5sZW5ndGgpe3dhcm4oIkRlY29kZSBtYXAgbGVuZ3RoIGlzIG5vdCBjb3JyZWN0Iik7cmV0dXJuITB9aWYoIU51bWJlci5pc0ludGVnZXIodCl8fHQ8MSl7d2FybigiQml0cyBwZXIgY29tcG9uZW50IGlzIG5vdCBjb3JyZWN0Iik7cmV0dXJuITB9cmV0dXJuIDA9PT1lWzBdJiZlWzFdPT09KDE8PHQpLTF9fWNsYXNzIERldmljZUdyYXlDUyBleHRlbmRzIENvbG9yU3BhY2V7Y29uc3RydWN0b3IoKXtzdXBlcigiRGV2aWNlR3JheSIsMSl9Z2V0UmdiSXRlbShlLHQscixhKXtjb25zdCBuPTI1NSplW3RdO3JbYV09clthKzFdPXJbYSsyXT1ufWdldFJnYkJ1ZmZlcihlLHQscixhLG4saSxzKXtjb25zdCBvPTI1NS8oKDE8PGkpLTEpO2xldCBjPXQsbD1uO2ZvcihsZXQgdD0wO3Q8cjsrK3Qpe2NvbnN0IHQ9byplW2MrK107YVtsKytdPXQ7YVtsKytdPXQ7YVtsKytdPXQ7bCs9c319Z2V0T3V0cHV0TGVuZ3RoKGUsdCl7cmV0dXJuIGUqKDMrdCl9fWNsYXNzIERldmljZVJnYkNTIGV4dGVuZHMgQ29sb3JTcGFjZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKCJEZXZpY2VSR0IiLDMpfWdldFJnYkl0ZW0oZSx0LHIsYSl7clthXT0yNTUqZVt0XTtyW2ErMV09MjU1KmVbdCsxXTtyW2ErMl09MjU1KmVbdCsyXX1nZXRSZ2JCdWZmZXIoZSx0LHIsYSxuLGkscyl7aWYoOD09PWkmJjA9PT1zKXthLnNldChlLnN1YmFycmF5KHQsdCszKnIpLG4pO3JldHVybn1jb25zdCBvPTI1NS8oKDE8PGkpLTEpO2xldCBjPXQsbD1uO2ZvcihsZXQgdD0wO3Q8cjsrK3Qpe2FbbCsrXT1vKmVbYysrXTthW2wrK109byplW2MrK107YVtsKytdPW8qZVtjKytdO2wrPXN9fWdldE91dHB1dExlbmd0aChlLHQpe3JldHVybiBlKigzK3QpLzN8MH1pc1Bhc3N0aHJvdWdoKGUpe3JldHVybiA4PT09ZX19Y2xhc3MgRGV2aWNlUmdiYUNTIGV4dGVuZHMgQ29sb3JTcGFjZXtjb25zdHJ1Y3Rvcigpe3N1cGVyKCJEZXZpY2VSR0JBIiw0KX1nZXRPdXRwdXRMZW5ndGgoZSx0KXtyZXR1cm4gNCplfWlzUGFzc3Rocm91Z2goZSl7cmV0dXJuIDg9PT1lfWZpbGxSZ2IoZSx0LHIsYSxuLGkscyxvLGMpe3IhPT1ufHx0IT09YT9mdW5jdGlvbiByZXNpemVSZ2JhSW1hZ2UoZSx0LHIsYSxuLGkscyl7Y29uc3Qgbz1yL24sYz1hL2k7bGV0IGw9MDtjb25zdCBoPW5ldyBVaW50MTZBcnJheShuKTtpZigxPT09cyl7Zm9yKGxldCBlPTA7ZTxuO2UrKyloW2VdPU1hdGguZmxvb3IoZSpvKTtjb25zdCBhPW5ldyBVaW50MzJBcnJheShlLmJ1ZmZlcikscz1uZXcgVWludDMyQXJyYXkodC5idWZmZXIpLHU9RmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4/MTY3NzcyMTU6NDI5NDk2NzA0MDtmb3IobGV0IGU9MDtlPGk7ZSsrKXtjb25zdCB0PWEuc3ViYXJyYXkoTWF0aC5mbG9vcihlKmMpKnIpO2ZvcihsZXQgZT0wO2U8bjtlKyspc1tsKytdfD10W2hbZV1dJnV9fWVsc2V7Y29uc3QgYT00LHM9ciphO2ZvcihsZXQgZT0wO2U8bjtlKyspaFtlXT1NYXRoLmZsb29yKGUqbykqYTtmb3IobGV0IHI9MDtyPGk7cisrKXtjb25zdCBhPWUuc3ViYXJyYXkoTWF0aC5mbG9vcihyKmMpKnMpO2ZvcihsZXQgZT0wO2U8bjtlKyspe2NvbnN0IHI9aFtlXTt0W2wrK109YVtyXTt0W2wrK109YVtyKzFdO3RbbCsrXT1hW3IrMl19fX19KG8sZSx0LHIsYSxuLGMpOmZ1bmN0aW9uIGNvcHlSZ2JhSW1hZ2UoZSx0LHIpe2lmKDE9PT1yKXtjb25zdCByPW5ldyBVaW50MzJBcnJheShlLmJ1ZmZlciksYT1uZXcgVWludDMyQXJyYXkodC5idWZmZXIpLG49RmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4/MTY3NzcyMTU6NDI5NDk2NzA0MDtmb3IobGV0IGU9MCx0PXIubGVuZ3RoO2U8dDtlKyspYVtlXXw9cltlXSZufWVsc2V7bGV0IHI9MDtmb3IobGV0IGE9MCxuPWUubGVuZ3RoO2E8bjthKz00KXt0W3IrK109ZVthXTt0W3IrK109ZVthKzFdO3RbcisrXT1lW2ErMl19fX0obyxlLGMpfX1jbGFzcyBEZXZpY2VDbXlrQ1MgZXh0ZW5kcyBDb2xvclNwYWNle2NvbnN0cnVjdG9yKCl7c3VwZXIoIkRldmljZUNNWUsiLDQpfSNuKGUsdCxyLGEsbil7Y29uc3QgaT1lW3RdKnIscz1lW3QrMV0qcixvPWVbdCsyXSpyLGM9ZVt0KzNdKnI7YVtuXT0yNTUraSooLTQuMzg3MzMyMzg0NjA5OTg4KmkrNTQuNDg2MTUxOTQxODkxNzYqcysxOC44MjI5MDUwMjE2NTMwMipvKzIxMi4yNTY2MjQ1MTYzOTU4NSpjLTI4NS4yMzMxMDI2MTM3MDA0KStzKigxLjcxNDk3NjM0NzczNjIxMzQqcy01LjYwOTY3MzY5MDQwNDczMTUqbystMTcuODczODcwODYxNDE1NDQ0KmMtNS40OTcwMDY0MjcxOTYzNjYpK28qKC0yLjUyMTczNDAxMzE2ODMwMzMqby0yMS4yNDg5MjMzMzczNTMwNzMqYysxNy41MTE5MjcwODQxODEzKStjKigtMjEuODYxMjIxNDc0NjM2MDUqYy0xODkuNDgxODA4MzU5MjI3NDcpO2FbbisxXT0yNTUraSooOC44NDEwNDE0MjIwMzYxNDkqaSs2MC4xMTgwMjcwNDU1OTczNjYqcys2Ljg3MTQyNTU5MjA0OTAwNypvKzMxLjE1OTEwMDEzMDA1NTkyMipjLTc5LjI5NzA4NDQ4MTY1NDgpK3MqKC0xNS4zMTAzNjEzMDY5Njc4MTcqcysxNy41NzUyNTEyNjExMDk0ODIqbysxMzEuMzUyNTA5MTI0OTM5NzYqYy0xOTAuOTQ1MzMwMjU4ODk1MSkrbyooNC40NDQzMzkxMDI4NTI3Mzkqbys5Ljg2MzI4NjE0OTM0MDUqYy0yNC44Njc0MTU4MjU1NTg3OCkrYyooLTIwLjczNzMyNTQ3MTE4MTAzNCpjLTE4Ny44MDQ1MzcwOTcxOTU3OCk7YVtuKzJdPTI1NStpKiguODg0MjUyMjQzMDAwMzI5NippKzguMDc4Njc3NTAzMTEyOTI4KnMrMzAuODk5NzgzMDk3MDM3Mjkqby0uMjM4ODMyMzg2ODkxNzg5MzQqYy0xNC4xODM1NzY3OTk2NzMyODYpK3MqKDEwLjQ5NTkzMjczNDMyMDcyKnMrNjMuMDIzNzg0OTQ3NTQwNTIqbys1MC42MDY5NTc2NTYzNjA3MzQqYy0xMTIuMjM4ODQyNTM3MTkyNDgpK28qKC4wMzI5NjA0MTExNDg3MzIxNypvKzExNS42MDM4NDQ0OTY0NjY0MSpjLTE5My41ODIwOTM1Njg2MTUwNSkrYyooLTIyLjMzODE2ODA3MzA5ODg2KmMtMTgwLjEyNjEzOTc0NzA4MzY3KX1nZXRSZ2JJdGVtKGUsdCxyLGEpe3RoaXMuI24oZSx0LDEscixhKX1nZXRSZ2JCdWZmZXIoZSx0LHIsYSxuLGkscyl7Y29uc3Qgbz0xLygoMTw8aSktMSk7Zm9yKGxldCBpPTA7aTxyO2krKyl7dGhpcy4jbihlLHQsbyxhLG4pO3QrPTQ7bis9MytzfX1nZXRPdXRwdXRMZW5ndGgoZSx0KXtyZXR1cm4gZS80KigzK3QpfDB9fWNsYXNzIENhbEdyYXlDUyBleHRlbmRzIENvbG9yU3BhY2V7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKCJDYWxHcmF5IiwxKTtpZighZSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBDYWxHcmF5Iik7W3RoaXMuWFcsdGhpcy5ZVyx0aGlzLlpXXT1lO1t0aGlzLlhCLHRoaXMuWUIsdGhpcy5aQl09dHx8WzAsMCwwXTt0aGlzLkc9cnx8MTtpZih0aGlzLlhXPDB8fHRoaXMuWlc8MHx8MSE9PXRoaXMuWVcpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFdoaXRlUG9pbnQgY29tcG9uZW50cyBmb3IgJHt0aGlzLm5hbWV9LCBubyBmYWxsYmFjayBhdmFpbGFibGVgKTtpZih0aGlzLlhCPDB8fHRoaXMuWUI8MHx8dGhpcy5aQjwwKXtpbmZvKGBJbnZhbGlkIEJsYWNrUG9pbnQgZm9yICR7dGhpcy5uYW1lfSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7dGhpcy5YQj10aGlzLllCPXRoaXMuWkI9MH0wPT09dGhpcy5YQiYmMD09PXRoaXMuWUImJjA9PT10aGlzLlpCfHx3YXJuKGAke3RoaXMubmFtZX0sIEJsYWNrUG9pbnQ6IFhCOiAke3RoaXMuWEJ9LCBZQjogJHt0aGlzLllCfSwgWkI6ICR7dGhpcy5aQn0sIG9ubHkgZGVmYXVsdCB2YWx1ZXMgYXJlIHN1cHBvcnRlZC5gKTtpZih0aGlzLkc8MSl7aW5mbyhgSW52YWxpZCBHYW1tYTogJHt0aGlzLkd9IGZvciAke3RoaXMubmFtZX0sIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0LmApO3RoaXMuRz0xfX0jbihlLHQscixhLG4pe2NvbnN0IGk9KGVbdF0qbikqKnRoaXMuRyxzPXRoaXMuWVcqaSxvPU1hdGgubWF4KDI5NS44KnMqKi4zMzMzMzMzMzMzMzMzMzMzLTQwLjgsMCk7clthXT1vO3JbYSsxXT1vO3JbYSsyXT1vfWdldFJnYkl0ZW0oZSx0LHIsYSl7dGhpcy4jbihlLHQscixhLDEpfWdldFJnYkJ1ZmZlcihlLHQscixhLG4saSxzKXtjb25zdCBvPTEvKCgxPDxpKS0xKTtmb3IobGV0IGk9MDtpPHI7KytpKXt0aGlzLiNuKGUsdCxhLG4sbyk7dCs9MTtuKz0zK3N9fWdldE91dHB1dExlbmd0aChlLHQpe3JldHVybiBlKigzK3QpfX1jbGFzcyBDYWxSR0JDUyBleHRlbmRzIENvbG9yU3BhY2V7c3RhdGljI2k9bmV3IEZsb2F0MzJBcnJheShbLjg5NTEsLjI2NjQsLS4xNjE0LC0uNzUwMiwxLjcxMzUsLjAzNjcsLjAzODksLS4wNjg1LDEuMDI5Nl0pO3N0YXRpYyNzPW5ldyBGbG9hdDMyQXJyYXkoWy45ODY5OTI5LC0uMTQ3MDU0MywuMTU5OTYyNywuNDMyMzA1MywuNTE4MzYwMywuMDQ5MjkxMiwtLjAwODUyODcsLjA0MDA0MjgsLjk2ODQ4NjddKTtzdGF0aWMjbz1uZXcgRmxvYXQzMkFycmF5KFszLjI0MDQ1NDIsLTEuNTM3MTM4NSwtLjQ5ODUzMTQsLS45NjkyNjYsMS44NzYwMTA4LC4wNDE1NTYsLjA1NTY0MzQsLS4yMDQwMjU5LDEuMDU3MjI1Ml0pO3N0YXRpYyNjPW5ldyBGbG9hdDMyQXJyYXkoWzEsMSwxXSk7c3RhdGljI2w9bmV3IEZsb2F0MzJBcnJheSgzKTtzdGF0aWMjaD1uZXcgRmxvYXQzMkFycmF5KDMpO3N0YXRpYyN1PW5ldyBGbG9hdDMyQXJyYXkoMyk7c3RhdGljI2Q9KDI0LzExNikqKjMvODtjb25zdHJ1Y3RvcihlLHQscixhKXtzdXBlcigiQ2FsUkdCIiwzKTtpZighZSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIldoaXRlUG9pbnQgbWlzc2luZyAtIHJlcXVpcmVkIGZvciBjb2xvciBzcGFjZSBDYWxSR0IiKTtjb25zdFtuLGksc109dGhpcy53aGl0ZVBvaW50PWUsW28sYyxsXT10aGlzLmJsYWNrUG9pbnQ9dHx8bmV3IEZsb2F0MzJBcnJheSgzKTtbdGhpcy5HUix0aGlzLkdHLHRoaXMuR0JdPXJ8fG5ldyBGbG9hdDMyQXJyYXkoWzEsMSwxXSk7W3RoaXMuTVhBLHRoaXMuTVlBLHRoaXMuTVpBLHRoaXMuTVhCLHRoaXMuTVlCLHRoaXMuTVpCLHRoaXMuTVhDLHRoaXMuTVlDLHRoaXMuTVpDXT1hfHxuZXcgRmxvYXQzMkFycmF5KFsxLDAsMCwwLDEsMCwwLDAsMV0pO2lmKG48MHx8czwwfHwxIT09aSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgV2hpdGVQb2ludCBjb21wb25lbnRzIGZvciAke3RoaXMubmFtZX0sIG5vIGZhbGxiYWNrIGF2YWlsYWJsZWApO2lmKG88MHx8YzwwfHxsPDApe2luZm8oYEludmFsaWQgQmxhY2tQb2ludCBmb3IgJHt0aGlzLm5hbWV9IFske299LCAke2N9LCAke2x9XSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7dGhpcy5ibGFja1BvaW50PW5ldyBGbG9hdDMyQXJyYXkoMyl9aWYodGhpcy5HUjwwfHx0aGlzLkdHPDB8fHRoaXMuR0I8MCl7aW5mbyhgSW52YWxpZCBHYW1tYSBbJHt0aGlzLkdSfSwgJHt0aGlzLkdHfSwgJHt0aGlzLkdCfV0gZm9yICR7dGhpcy5uYW1lfSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7dGhpcy5HUj10aGlzLkdHPXRoaXMuR0I9MX19I2YoZSx0LHIpe3JbMF09ZVswXSp0WzBdK2VbMV0qdFsxXStlWzJdKnRbMl07clsxXT1lWzNdKnRbMF0rZVs0XSp0WzFdK2VbNV0qdFsyXTtyWzJdPWVbNl0qdFswXStlWzddKnRbMV0rZVs4XSp0WzJdfSNnKGUsdCxyKXtyWzBdPTEqdFswXS9lWzBdO3JbMV09MSp0WzFdL2VbMV07clsyXT0xKnRbMl0vZVsyXX0jcChlLHQscil7clswXT0uOTUwNDcqdFswXS9lWzBdO3JbMV09MSp0WzFdL2VbMV07clsyXT0xLjA4ODgzKnRbMl0vZVsyXX0jbShlKXtyZXR1cm4gZTw9LjAwMzEzMDg/TWF0aENsYW1wKDEyLjkyKmUsMCwxKTplPj0uOTk1NTQ1MjU/MTpNYXRoQ2xhbXAoMS4wNTUqZSoqKDEvMi40KS0uMDU1LDAsMSl9I2IoZSl7cmV0dXJuIGU8MD8tdGhpcy4jYigtZSk6ZT44PygoZSsxNikvMTE2KSoqMzplKkNhbFJHQkNTLiNkfSN5KGUsdCxyKXtpZigwPT09ZVswXSYmMD09PWVbMV0mJjA9PT1lWzJdKXtyWzBdPXRbMF07clsxXT10WzFdO3JbMl09dFsyXTtyZXR1cm59Y29uc3QgYT10aGlzLiNiKDApLG49KDEtYSkvKDEtdGhpcy4jYihlWzBdKSksaT0xLW4scz0oMS1hKS8oMS10aGlzLiNiKGVbMV0pKSxvPTEtcyxjPSgxLWEpLygxLXRoaXMuI2IoZVsyXSkpLGw9MS1jO3JbMF09dFswXSpuK2k7clsxXT10WzFdKnMrbztyWzJdPXRbMl0qYytsfSN3KGUsdCxyKXtpZigxPT09ZVswXSYmMT09PWVbMl0pe3JbMF09dFswXTtyWzFdPXRbMV07clsyXT10WzJdO3JldHVybn1jb25zdCBhPXI7dGhpcy4jZihDYWxSR0JDUy4jaSx0LGEpO2NvbnN0IG49Q2FsUkdCQ1MuI2w7dGhpcy4jZyhlLGEsbik7dGhpcy4jZihDYWxSR0JDUy4jcyxuLHIpfSN4KGUsdCxyKXtjb25zdCBhPXI7dGhpcy4jZihDYWxSR0JDUy4jaSx0LGEpO2NvbnN0IG49Q2FsUkdCQ1MuI2w7dGhpcy4jcChlLGEsbik7dGhpcy4jZihDYWxSR0JDUy4jcyxuLHIpfSNuKGUsdCxyLGEsbil7Y29uc3QgaT1NYXRoQ2xhbXAoZVt0XSpuLDAsMSkscz1NYXRoQ2xhbXAoZVt0KzFdKm4sMCwxKSxvPU1hdGhDbGFtcChlW3QrMl0qbiwwLDEpLGM9MT09PWk/MTppKip0aGlzLkdSLGw9MT09PXM/MTpzKip0aGlzLkdHLGg9MT09PW8/MTpvKip0aGlzLkdCLHU9dGhpcy5NWEEqYyt0aGlzLk1YQipsK3RoaXMuTVhDKmgsZD10aGlzLk1ZQSpjK3RoaXMuTVlCKmwrdGhpcy5NWUMqaCxmPXRoaXMuTVpBKmMrdGhpcy5NWkIqbCt0aGlzLk1aQypoLGc9Q2FsUkdCQ1MuI2g7Z1swXT11O2dbMV09ZDtnWzJdPWY7Y29uc3QgcD1DYWxSR0JDUy4jdTt0aGlzLiN3KHRoaXMud2hpdGVQb2ludCxnLHApO2NvbnN0IG09Q2FsUkdCQ1MuI2g7dGhpcy4jeSh0aGlzLmJsYWNrUG9pbnQscCxtKTtjb25zdCBiPUNhbFJHQkNTLiN1O3RoaXMuI3goQ2FsUkdCQ1MuI2MsbSxiKTtjb25zdCB5PUNhbFJHQkNTLiNoO3RoaXMuI2YoQ2FsUkdCQ1MuI28sYix5KTtyW2FdPTI1NSp0aGlzLiNtKHlbMF0pO3JbYSsxXT0yNTUqdGhpcy4jbSh5WzFdKTtyW2ErMl09MjU1KnRoaXMuI20oeVsyXSl9Z2V0UmdiSXRlbShlLHQscixhKXt0aGlzLiNuKGUsdCxyLGEsMSl9Z2V0UmdiQnVmZmVyKGUsdCxyLGEsbixpLHMpe2NvbnN0IG89MS8oKDE8PGkpLTEpO2ZvcihsZXQgaT0wO2k8cjsrK2kpe3RoaXMuI24oZSx0LGEsbixvKTt0Kz0zO24rPTMrc319Z2V0T3V0cHV0TGVuZ3RoKGUsdCl7cmV0dXJuIGUqKDMrdCkvM3wwfX1jbGFzcyBMYWJDUyBleHRlbmRzIENvbG9yU3BhY2V7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKCJMYWIiLDMpO2lmKCFlKXRocm93IG5ldyBGb3JtYXRFcnJvcigiV2hpdGVQb2ludCBtaXNzaW5nIC0gcmVxdWlyZWQgZm9yIGNvbG9yIHNwYWNlIExhYiIpO1t0aGlzLlhXLHRoaXMuWVcsdGhpcy5aV109ZTtbdGhpcy5hbWluLHRoaXMuYW1heCx0aGlzLmJtaW4sdGhpcy5ibWF4XT1yfHxbLTEwMCwxMDAsLTEwMCwxMDBdO1t0aGlzLlhCLHRoaXMuWUIsdGhpcy5aQl09dHx8WzAsMCwwXTtpZih0aGlzLlhXPDB8fHRoaXMuWlc8MHx8MSE9PXRoaXMuWVcpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFdoaXRlUG9pbnQgY29tcG9uZW50cywgbm8gZmFsbGJhY2sgYXZhaWxhYmxlIik7aWYodGhpcy5YQjwwfHx0aGlzLllCPDB8fHRoaXMuWkI8MCl7aW5mbygiSW52YWxpZCBCbGFja1BvaW50LCBmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdCIpO3RoaXMuWEI9dGhpcy5ZQj10aGlzLlpCPTB9aWYodGhpcy5hbWluPnRoaXMuYW1heHx8dGhpcy5ibWluPnRoaXMuYm1heCl7aW5mbygiSW52YWxpZCBSYW5nZSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHRzIik7dGhpcy5hbWluPS0xMDA7dGhpcy5hbWF4PTEwMDt0aGlzLmJtaW49LTEwMDt0aGlzLmJtYXg9MTAwfX0jUyhlKXtyZXR1cm4gZT49Ni8yOT9lKiozOjEwOC84NDEqKGUtNC8yOSl9I0EoZSx0LHIsYSl7cmV0dXJuIHIrZSooYS1yKS90fSNuKGUsdCxyLGEsbil7bGV0IGk9ZVt0XSxzPWVbdCsxXSxvPWVbdCsyXTtpZighMSE9PXIpe2k9dGhpcy4jQShpLHIsMCwxMDApO3M9dGhpcy4jQShzLHIsdGhpcy5hbWluLHRoaXMuYW1heCk7bz10aGlzLiNBKG8scix0aGlzLmJtaW4sdGhpcy5ibWF4KX1zPnRoaXMuYW1heD9zPXRoaXMuYW1heDpzPHRoaXMuYW1pbiYmKHM9dGhpcy5hbWluKTtvPnRoaXMuYm1heD9vPXRoaXMuYm1heDpvPHRoaXMuYm1pbiYmKG89dGhpcy5ibWluKTtjb25zdCBjPShpKzE2KS8xMTYsbD1jK3MvNTAwLGg9Yy1vLzIwMCx1PXRoaXMuWFcqdGhpcy4jUyhsKSxkPXRoaXMuWVcqdGhpcy4jUyhjKSxmPXRoaXMuWlcqdGhpcy4jUyhoKTtsZXQgZyxwLG07aWYodGhpcy5aVzwxKXtnPTMuMTMzOSp1Ky0xLjYxNypkKy0uNDkwNipmO3A9LS45Nzg1KnUrMS45MTYqZCsuMDMzMypmO209LjA3Mip1Ky0uMjI5KmQrMS40MDU3KmZ9ZWxzZXtnPTMuMjQwNip1Ky0xLjUzNzIqZCstLjQ5ODYqZjtwPS0uOTY4OSp1KzEuODc1OCpkKy4wNDE1KmY7bT0uMDU1Nyp1Ky0uMjA0KmQrMS4wNTcqZn1hW25dPTI1NSpNYXRoLnNxcnQoZyk7YVtuKzFdPTI1NSpNYXRoLnNxcnQocCk7YVtuKzJdPTI1NSpNYXRoLnNxcnQobSl9Z2V0UmdiSXRlbShlLHQscixhKXt0aGlzLiNuKGUsdCwhMSxyLGEpfWdldFJnYkJ1ZmZlcihlLHQscixhLG4saSxzKXtjb25zdCBvPSgxPDxpKS0xO2ZvcihsZXQgaT0wO2k8cjtpKyspe3RoaXMuI24oZSx0LG8sYSxuKTt0Kz0zO24rPTMrc319Z2V0T3V0cHV0TGVuZ3RoKGUsdCl7cmV0dXJuIGUqKDMrdCkvM3wwfWlzRGVmYXVsdERlY29kZShlLHQpe3JldHVybiEwfWdldCB1c2VzWmVyb1RvT25lUmFuZ2UoKXtyZXR1cm4gc2hhZG93KHRoaXMsInVzZXNaZXJvVG9PbmVSYW5nZSIsITEpfX1mdW5jdGlvbiBmZXRjaFN5bmMoZSl7Y29uc3QgdD1uZXcgWE1MSHR0cFJlcXVlc3Q7dC5vcGVuKCJHRVQiLGUsITEpO3QucmVzcG9uc2VUeXBlPSJhcnJheWJ1ZmZlciI7dC5zZW5kKG51bGwpO3JldHVybiB0LnJlc3BvbnNlfWNsYXNzIEljY0NvbG9yU3BhY2UgZXh0ZW5kcyBDb2xvclNwYWNleyNrOyNDO3N0YXRpYyN2PSEwO3N0YXRpYyNGPW51bGw7c3RhdGljI0k9bnVsbDtjb25zdHJ1Y3RvcihlLHQscil7aWYoIUljY0NvbG9yU3BhY2UuaXNVc2FibGUpdGhyb3cgbmV3IEVycm9yKCJObyBJQ0MgY29sb3Igc3BhY2Ugc3VwcG9ydCIpO3N1cGVyKHQscik7bGV0IGE7c3dpdGNoKHIpe2Nhc2UgMTphPUFyLkdyYXk4O3RoaXMuI0M9KGUsdCxyKT0+ZnVuY3Rpb24gcWNtc19jb252ZXJ0X29uZShlLHQscil7eXIucWNtc19jb252ZXJ0X29uZShlLHQscil9KHRoaXMuI2ssMjU1KmVbdF0scik7YnJlYWs7Y2FzZSAzOmE9QXIuUkdCODt0aGlzLiNDPShlLHQscik9PmZ1bmN0aW9uIHFjbXNfY29udmVydF90aHJlZShlLHQscixhLG4pe3lyLnFjbXNfY29udmVydF90aHJlZShlLHQscixhLG4pfSh0aGlzLiNrLDI1NSplW3RdLDI1NSplW3QrMV0sMjU1KmVbdCsyXSxyKTticmVhaztjYXNlIDQ6YT1Bci5DTVlLO3RoaXMuI0M9KGUsdCxyKT0+ZnVuY3Rpb24gcWNtc19jb252ZXJ0X2ZvdXIoZSx0LHIsYSxuLGkpe3lyLnFjbXNfY29udmVydF9mb3VyKGUsdCxyLGEsbixpKX0odGhpcy4jaywyNTUqZVt0XSwyNTUqZVt0KzFdLDI1NSplW3QrMl0sMjU1KmVbdCszXSxyKTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgbnVtYmVyIG9mIGNvbXBvbmVudHM6ICR7cn1gKX10aGlzLiNrPWZ1bmN0aW9uIHFjbXNfdHJhbnNmb3JtZXJfZnJvbV9tZW1vcnkoZSx0LHIpe2NvbnN0IGE9cGFzc0FycmF5OFRvV2FzbTAoZSx5ci5fX3diaW5kZ2VuX21hbGxvYyksbj1TcjtyZXR1cm4geXIucWNtc190cmFuc2Zvcm1lcl9mcm9tX21lbW9yeShhLG4sdCxyKT4+PjB9KGUsYSxrci5QZXJjZXB0dWFsKTtpZighdGhpcy4jayl0aHJvdyBuZXcgRXJyb3IoIkZhaWxlZCB0byBjcmVhdGUgSUNDIGNvbG9yIHNwYWNlIik7SWNjQ29sb3JTcGFjZS4jSXx8PW5ldyBGaW5hbGl6YXRpb25SZWdpc3RyeShlPT57IWZ1bmN0aW9uIHFjbXNfZHJvcF90cmFuc2Zvcm1lcihlKXt5ci5xY21zX2Ryb3BfdHJhbnNmb3JtZXIoZSl9KGUpfSk7SWNjQ29sb3JTcGFjZS4jSS5yZWdpc3Rlcih0aGlzLHRoaXMuI2spfWdldFJnYkhleChlLHQpe3RoaXMuI0MoZSx0LCEwKTtyZXR1cm4gUUNNUy5fY3NzQ29sb3J9Z2V0UmdiSXRlbShlLHQscixhKXtRQ01TLl9kZXN0QnVmZmVyPXI7UUNNUy5fZGVzdE9mZnNldD1hO1FDTVMuX2Rlc3RMZW5ndGg9Mzt0aGlzLiNDKGUsdCwhMSk7UUNNUy5fZGVzdEJ1ZmZlcj1udWxsfWdldFJnYkJ1ZmZlcihlLHQscixhLG4saSxzKXtlPWUuc3ViYXJyYXkodCx0K3IqdGhpcy5udW1Db21wcyk7aWYoOCE9PWkpe2NvbnN0IHQ9MjU1LygoMTw8aSktMSk7Zm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKWVbcl0qPXR9UUNNUy5fbXVzdEFkZEFscGhhPXMmJmEuYnVmZmVyPT09ZS5idWZmZXI7UUNNUy5fZGVzdEJ1ZmZlcj1hO1FDTVMuX2Rlc3RPZmZzZXQ9bjtRQ01TLl9kZXN0TGVuZ3RoPXIqKDMrcyk7IWZ1bmN0aW9uIHFjbXNfY29udmVydF9hcnJheShlLHQpe2NvbnN0IHI9cGFzc0FycmF5OFRvV2FzbTAodCx5ci5fX3diaW5kZ2VuX21hbGxvYyksYT1Tcjt5ci5xY21zX2NvbnZlcnRfYXJyYXkoZSxyLGEpfSh0aGlzLiNrLGUpO1FDTVMuX211c3RBZGRBbHBoYT0hMTtRQ01TLl9kZXN0QnVmZmVyPW51bGx9Z2V0T3V0cHV0TGVuZ3RoKGUsdCl7cmV0dXJuIGUvdGhpcy5udW1Db21wcyooMyt0KXwwfXN0YXRpYyBzZXRPcHRpb25zKHt1c2VXYXNtOmUsdXNlV29ya2VyRmV0Y2g6dCx3YXNtVXJsOnJ9KXtpZih0KXt0aGlzLiN2PWU7dGhpcy4jRj1yfWVsc2UgdGhpcy4jdj0hMX1zdGF0aWMgZ2V0IGlzVXNhYmxlKCl7bGV0IGU9ITE7aWYodGhpcy4jdilpZih0aGlzLiNGKXRyeXt0aGlzLl9tb2R1bGU9ZnVuY3Rpb24gaW5pdFN5bmMoZSl7aWYodm9pZCAwIT09eXIpcmV0dXJuIHlyO3ZvaWQgMCE9PWUmJihPYmplY3QuZ2V0UHJvdG90eXBlT2YoZSk9PT1PYmplY3QucHJvdG90eXBlPyh7bW9kdWxlOmV9PWUpOmNvbnNvbGUud2FybigidXNpbmcgZGVwcmVjYXRlZCBwYXJhbWV0ZXJzIGZvciBgaW5pdFN5bmMoKWA7IHBhc3MgYSBzaW5nbGUgb2JqZWN0IGluc3RlYWQiKSk7Y29uc3QgdD1fX3diZ19nZXRfaW1wb3J0cygpO2UgaW5zdGFuY2VvZiBXZWJBc3NlbWJseS5Nb2R1bGV8fChlPW5ldyBXZWJBc3NlbWJseS5Nb2R1bGUoZSkpO3JldHVybiBfX3diZ19maW5hbGl6ZV9pbml0KG5ldyBXZWJBc3NlbWJseS5JbnN0YW5jZShlLHQpLGUpfSh7bW9kdWxlOmZldGNoU3luYyhgJHt0aGlzLiNGfXFjbXNfYmcud2FzbWApfSk7ZT0hIXRoaXMuX21vZHVsZTtRQ01TLl9tZW1vcnk9dGhpcy5fbW9kdWxlLm1lbW9yeTtRQ01TLl9tYWtlSGV4Q29sb3I9VXRpbC5tYWtlSGV4Q29sb3J9Y2F0Y2goZSl7d2FybihgSUNDQmFzZWQgY29sb3Igc3BhY2U6ICIke2V9Ii5gKX1lbHNlIHdhcm4oIk5vIElDQyBjb2xvciBzcGFjZSBzdXBwb3J0IGR1ZSB0byBtaXNzaW5nIGB3YXNtVXJsYCBBUEkgb3B0aW9uIik7cmV0dXJuIHNoYWRvdyh0aGlzLCJpc1VzYWJsZSIsZSl9fWNsYXNzIENteWtJQ0NCYXNlZENTIGV4dGVuZHMgSWNjQ29sb3JTcGFjZXtzdGF0aWMjVDtjb25zdHJ1Y3Rvcigpe3N1cGVyKG5ldyBVaW50OEFycmF5KGZldGNoU3luYyhgJHtDbXlrSUNDQmFzZWRDUy4jVH1DR0FUUzAwMUNvbXBhdC12Mi1taWNyby5pY2NgKSksIkRldmljZUNNWUsiLDQpfXN0YXRpYyBzZXRPcHRpb25zKHtpY2NVcmw6ZX0pe3RoaXMuI1Q9ZX1zdGF0aWMgZ2V0IGlzVXNhYmxlKCl7bGV0IGU9ITE7SWNjQ29sb3JTcGFjZS5pc1VzYWJsZSYmKHRoaXMuI1Q/ZT0hMDp3YXJuKCJObyBDTVlLIElDQyBwcm9maWxlIHN1cHBvcnQgZHVlIHRvIG1pc3NpbmcgYGljY1VybGAgQVBJIG9wdGlvbiIpKTtyZXR1cm4gc2hhZG93KHRoaXMsImlzVXNhYmxlIixlKX19Y2xhc3MgU3RyZWFtIGV4dGVuZHMgQmFzZVN0cmVhbXtjb25zdHJ1Y3RvcihlLHQscixhKXtzdXBlcigpO3RoaXMuYnl0ZXM9ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXk/ZTpuZXcgVWludDhBcnJheShlKTt0aGlzLnN0YXJ0PXR8fDA7dGhpcy5wb3M9dGhpcy5zdGFydDt0aGlzLmVuZD10K3J8fHRoaXMuYnl0ZXMubGVuZ3RoO3RoaXMuZGljdD1hfWdldCBsZW5ndGgoKXtyZXR1cm4gdGhpcy5lbmQtdGhpcy5zdGFydH1nZXQgaXNFbXB0eSgpe3JldHVybiAwPT09dGhpcy5sZW5ndGh9Z2V0Qnl0ZSgpe3JldHVybiB0aGlzLnBvcz49dGhpcy5lbmQ/LTE6dGhpcy5ieXRlc1t0aGlzLnBvcysrXX1nZXRCeXRlcyhlKXtjb25zdCB0PXRoaXMuYnl0ZXMscj10aGlzLnBvcyxhPXRoaXMuZW5kO2lmKCFlKXJldHVybiB0LnN1YmFycmF5KHIsYSk7bGV0IG49citlO24+YSYmKG49YSk7dGhpcy5wb3M9bjtyZXR1cm4gdC5zdWJhcnJheShyLG4pfWdldEJ5dGVSYW5nZShlLHQpe2U8MCYmKGU9MCk7dD50aGlzLmVuZCYmKHQ9dGhpcy5lbmQpO3JldHVybiB0aGlzLmJ5dGVzLnN1YmFycmF5KGUsdCl9cmVzZXQoKXt0aGlzLnBvcz10aGlzLnN0YXJ0fW1vdmVTdGFydCgpe3RoaXMuc3RhcnQ9dGhpcy5wb3N9bWFrZVN1YlN0cmVhbShlLHQscj1udWxsKXtyZXR1cm4gbmV3IFN0cmVhbSh0aGlzLmJ5dGVzLmJ1ZmZlcixlLHQscil9fWNsYXNzIFN0cmluZ1N0cmVhbSBleHRlbmRzIFN0cmVhbXtjb25zdHJ1Y3RvcihlKXtzdXBlcihzdHJpbmdUb0J5dGVzKGUpKX19Y2xhc3MgTnVsbFN0cmVhbSBleHRlbmRzIFN0cmVhbXtjb25zdHJ1Y3Rvcigpe3N1cGVyKG5ldyBVaW50OEFycmF5KDApKX19Y2xhc3MgQ2h1bmtlZFN0cmVhbSBleHRlbmRzIFN0cmVhbXtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIobmV3IFVpbnQ4QXJyYXkoZSksMCxlLG51bGwpO3RoaXMuY2h1bmtTaXplPXQ7dGhpcy5fbG9hZGVkQ2h1bmtzPW5ldyBTZXQ7dGhpcy5udW1DaHVua3M9TWF0aC5jZWlsKGUvdCk7dGhpcy5tYW5hZ2VyPXI7dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGg9MDt0aGlzLmxhc3RTdWNjZXNzZnVsRW5zdXJlQnl0ZUNodW5rPS0xfWdldE1pc3NpbmdDaHVua3MoKXtjb25zdCBlPVtdO2ZvcihsZXQgdD0wLHI9dGhpcy5udW1DaHVua3M7dDxyOysrdCl0aGlzLl9sb2FkZWRDaHVua3MuaGFzKHQpfHxlLnB1c2godCk7cmV0dXJuIGV9Z2V0IG51bUNodW5rc0xvYWRlZCgpe3JldHVybiB0aGlzLl9sb2FkZWRDaHVua3Muc2l6ZX1nZXQgaXNEYXRhTG9hZGVkKCl7cmV0dXJuIHRoaXMubnVtQ2h1bmtzTG9hZGVkPT09dGhpcy5udW1DaHVua3N9b25SZWNlaXZlRGF0YShlLHQpe2NvbnN0IHI9dGhpcy5jaHVua1NpemU7aWYoZSVyIT09MCl0aHJvdyBuZXcgRXJyb3IoYEJhZCBiZWdpbiBvZmZzZXQ6ICR7ZX1gKTtjb25zdCBhPWUrdC5ieXRlTGVuZ3RoO2lmKGElciE9PTAmJmEhPT10aGlzLmJ5dGVzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoYEJhZCBlbmQgb2Zmc2V0OiAke2F9YCk7dGhpcy5ieXRlcy5zZXQobmV3IFVpbnQ4QXJyYXkodCksZSk7Y29uc3Qgbj1NYXRoLmZsb29yKGUvciksaT1NYXRoLmZsb29yKChhLTEpL3IpKzE7Zm9yKGxldCBlPW47ZTxpOysrZSl0aGlzLl9sb2FkZWRDaHVua3MuYWRkKGUpfW9uUmVjZWl2ZVByb2dyZXNzaXZlRGF0YShlKXtsZXQgdD10aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aDtjb25zdCByPU1hdGguZmxvb3IodC90aGlzLmNodW5rU2l6ZSk7dGhpcy5ieXRlcy5zZXQobmV3IFVpbnQ4QXJyYXkoZSksdCk7dCs9ZS5ieXRlTGVuZ3RoO3RoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoPXQ7Y29uc3QgYT10Pj10aGlzLmVuZD90aGlzLm51bUNodW5rczpNYXRoLmZsb29yKHQvdGhpcy5jaHVua1NpemUpO2ZvcihsZXQgZT1yO2U8YTsrK2UpdGhpcy5fbG9hZGVkQ2h1bmtzLmFkZChlKX1lbnN1cmVCeXRlKGUpe2lmKGU8dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpcmV0dXJuO2NvbnN0IHQ9TWF0aC5mbG9vcihlL3RoaXMuY2h1bmtTaXplKTtpZighKHQ+dGhpcy5udW1DaHVua3MpJiZ0IT09dGhpcy5sYXN0U3VjY2Vzc2Z1bEVuc3VyZUJ5dGVDaHVuayl7aWYoIXRoaXMuX2xvYWRlZENodW5rcy5oYXModCkpdGhyb3cgbmV3IE1pc3NpbmdEYXRhRXhjZXB0aW9uKGUsZSsxKTt0aGlzLmxhc3RTdWNjZXNzZnVsRW5zdXJlQnl0ZUNodW5rPXR9fWVuc3VyZVJhbmdlKGUsdCl7aWYoZT49dClyZXR1cm47aWYodDw9dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpcmV0dXJuO2NvbnN0IHI9TWF0aC5mbG9vcihlL3RoaXMuY2h1bmtTaXplKTtpZihyPnRoaXMubnVtQ2h1bmtzKXJldHVybjtjb25zdCBhPU1hdGgubWluKE1hdGguZmxvb3IoKHQtMSkvdGhpcy5jaHVua1NpemUpKzEsdGhpcy5udW1DaHVua3MpO2ZvcihsZXQgbj1yO248YTsrK24paWYoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMobikpdGhyb3cgbmV3IE1pc3NpbmdEYXRhRXhjZXB0aW9uKGUsdCl9bmV4dEVtcHR5Q2h1bmsoZSl7Y29uc3QgdD10aGlzLm51bUNodW5rcztmb3IobGV0IHI9MDtyPHQ7KytyKXtjb25zdCBhPShlK3IpJXQ7aWYoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoYSkpcmV0dXJuIGF9cmV0dXJuIG51bGx9aGFzQ2h1bmsoZSl7cmV0dXJuIHRoaXMuX2xvYWRlZENodW5rcy5oYXMoZSl9Z2V0Qnl0ZSgpe2NvbnN0IGU9dGhpcy5wb3M7aWYoZT49dGhpcy5lbmQpcmV0dXJuLTE7ZT49dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgmJnRoaXMuZW5zdXJlQnl0ZShlKTtyZXR1cm4gdGhpcy5ieXRlc1t0aGlzLnBvcysrXX1nZXRCeXRlcyhlKXtjb25zdCB0PXRoaXMuYnl0ZXMscj10aGlzLnBvcyxhPXRoaXMuZW5kO2lmKCFlKXthPnRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoJiZ0aGlzLmVuc3VyZVJhbmdlKHIsYSk7cmV0dXJuIHQuc3ViYXJyYXkocixhKX1sZXQgbj1yK2U7bj5hJiYobj1hKTtuPnRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoJiZ0aGlzLmVuc3VyZVJhbmdlKHIsbik7dGhpcy5wb3M9bjtyZXR1cm4gdC5zdWJhcnJheShyLG4pfWdldEJ5dGVSYW5nZShlLHQpe2U8MCYmKGU9MCk7dD50aGlzLmVuZCYmKHQ9dGhpcy5lbmQpO3Q+dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgmJnRoaXMuZW5zdXJlUmFuZ2UoZSx0KTtyZXR1cm4gdGhpcy5ieXRlcy5zdWJhcnJheShlLHQpfW1ha2VTdWJTdHJlYW0oZSx0LHI9bnVsbCl7dD9lK3Q+dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgmJnRoaXMuZW5zdXJlUmFuZ2UoZSxlK3QpOmU+PXRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoJiZ0aGlzLmVuc3VyZUJ5dGUoZSk7ZnVuY3Rpb24gQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbSgpe31DaHVua2VkU3RyZWFtU3Vic3RyZWFtLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHRoaXMpO0NodW5rZWRTdHJlYW1TdWJzdHJlYW0ucHJvdG90eXBlLmdldE1pc3NpbmdDaHVua3M9ZnVuY3Rpb24oKXtjb25zdCBlPXRoaXMuY2h1bmtTaXplLHQ9TWF0aC5mbG9vcih0aGlzLnN0YXJ0L2UpLHI9TWF0aC5mbG9vcigodGhpcy5lbmQtMSkvZSkrMSxhPVtdO2ZvcihsZXQgZT10O2U8cjsrK2UpdGhpcy5fbG9hZGVkQ2h1bmtzLmhhcyhlKXx8YS5wdXNoKGUpO3JldHVybiBhfTtPYmplY3QuZGVmaW5lUHJvcGVydHkoQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUsImlzRGF0YUxvYWRlZCIse2dldCgpe3JldHVybiB0aGlzLm51bUNodW5rc0xvYWRlZD09PXRoaXMubnVtQ2h1bmtzfHwwPT09dGhpcy5nZXRNaXNzaW5nQ2h1bmtzKCkubGVuZ3RofSxjb25maWd1cmFibGU6ITB9KTtjb25zdCBhPW5ldyBDaHVua2VkU3RyZWFtU3Vic3RyZWFtO2EucG9zPWEuc3RhcnQ9ZTthLmVuZD1lK3R8fHRoaXMuZW5kO2EuZGljdD1yO3JldHVybiBhfWdldEJhc2VTdHJlYW1zKCl7cmV0dXJuW3RoaXNdfX1jbGFzcyBDaHVua2VkU3RyZWFtTWFuYWdlcntjb25zdHJ1Y3RvcihlLHQpe3RoaXMubGVuZ3RoPXQubGVuZ3RoO3RoaXMuY2h1bmtTaXplPXQucmFuZ2VDaHVua1NpemU7dGhpcy5zdHJlYW09bmV3IENodW5rZWRTdHJlYW0odGhpcy5sZW5ndGgsdGhpcy5jaHVua1NpemUsdGhpcyk7dGhpcy5wZGZOZXR3b3JrU3RyZWFtPWU7dGhpcy5kaXNhYmxlQXV0b0ZldGNoPXQuZGlzYWJsZUF1dG9GZXRjaDt0aGlzLm1zZ0hhbmRsZXI9dC5tc2dIYW5kbGVyO3RoaXMuY3VyclJlcXVlc3RJZD0wO3RoaXMuX2NodW5rc05lZWRlZEJ5UmVxdWVzdD1uZXcgTWFwO3RoaXMuX3JlcXVlc3RzQnlDaHVuaz1uZXcgTWFwO3RoaXMuX3Byb21pc2VzQnlSZXF1ZXN0PW5ldyBNYXA7dGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGg9MDt0aGlzLmFib3J0ZWQ9ITE7dGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eT1Qcm9taXNlLndpdGhSZXNvbHZlcnMoKX1zZW5kUmVxdWVzdChlLHQpe2NvbnN0IHI9dGhpcy5wZGZOZXR3b3JrU3RyZWFtLmdldFJhbmdlUmVhZGVyKGUsdCk7ci5pc1N0cmVhbWluZ1N1cHBvcnRlZHx8KHIub25Qcm9ncmVzcz10aGlzLm9uUHJvZ3Jlc3MuYmluZCh0aGlzKSk7bGV0IGE9W10sbj0wO3JldHVybiBuZXcgUHJvbWlzZSgoZSx0KT0+e2NvbnN0IHJlYWRDaHVuaz0oe3ZhbHVlOmksZG9uZTpzfSk9Pnt0cnl7aWYocyl7Y29uc3QgdD1hcnJheUJ1ZmZlcnNUb0J5dGVzKGEpO2E9bnVsbDtlKHQpO3JldHVybn1uKz1pLmJ5dGVMZW5ndGg7ci5pc1N0cmVhbWluZ1N1cHBvcnRlZCYmdGhpcy5vblByb2dyZXNzKHtsb2FkZWQ6bn0pO2EucHVzaChpKTtyLnJlYWQoKS50aGVuKHJlYWRDaHVuayx0KX1jYXRjaChlKXt0KGUpfX07ci5yZWFkKCkudGhlbihyZWFkQ2h1bmssdCl9KS50aGVuKHQ9Pnt0aGlzLmFib3J0ZWR8fHRoaXMub25SZWNlaXZlRGF0YSh7Y2h1bms6dCxiZWdpbjplfSl9KX1yZXF1ZXN0QWxsQ2h1bmtzKGU9ITEpe2lmKCFlKXtjb25zdCBlPXRoaXMuc3RyZWFtLmdldE1pc3NpbmdDaHVua3MoKTt0aGlzLl9yZXF1ZXN0Q2h1bmtzKGUpfXJldHVybiB0aGlzLl9sb2FkZWRTdHJlYW1DYXBhYmlsaXR5LnByb21pc2V9X3JlcXVlc3RDaHVua3MoZSl7Y29uc3QgdD10aGlzLmN1cnJSZXF1ZXN0SWQrKyxyPW5ldyBTZXQ7dGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LnNldCh0LHIpO2Zvcihjb25zdCB0IG9mIGUpdGhpcy5zdHJlYW0uaGFzQ2h1bmsodCl8fHIuYWRkKHQpO2lmKDA9PT1yLnNpemUpcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO2NvbnN0IGE9UHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7dGhpcy5fcHJvbWlzZXNCeVJlcXVlc3Quc2V0KHQsYSk7Y29uc3Qgbj1bXTtmb3IoY29uc3QgZSBvZiByKXtsZXQgcj10aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuZ2V0KGUpO2lmKCFyKXtyPVtdO3RoaXMuX3JlcXVlc3RzQnlDaHVuay5zZXQoZSxyKTtuLnB1c2goZSl9ci5wdXNoKHQpfWlmKG4ubGVuZ3RoPjApe2NvbnN0IGU9dGhpcy5ncm91cENodW5rcyhuKTtmb3IoY29uc3QgdCBvZiBlKXtjb25zdCBlPXQuYmVnaW5DaHVuayp0aGlzLmNodW5rU2l6ZSxyPU1hdGgubWluKHQuZW5kQ2h1bmsqdGhpcy5jaHVua1NpemUsdGhpcy5sZW5ndGgpO3RoaXMuc2VuZFJlcXVlc3QoZSxyKS5jYXRjaChhLnJlamVjdCl9fXJldHVybiBhLnByb21pc2UuY2F0Y2goZT0+e2lmKCF0aGlzLmFib3J0ZWQpdGhyb3cgZX0pfWdldFN0cmVhbSgpe3JldHVybiB0aGlzLnN0cmVhbX1yZXF1ZXN0UmFuZ2UoZSx0KXt0PU1hdGgubWluKHQsdGhpcy5sZW5ndGgpO2NvbnN0IHI9dGhpcy5nZXRCZWdpbkNodW5rKGUpLGE9dGhpcy5nZXRFbmRDaHVuayh0KSxuPVtdO2ZvcihsZXQgZT1yO2U8YTsrK2Upbi5wdXNoKGUpO3JldHVybiB0aGlzLl9yZXF1ZXN0Q2h1bmtzKG4pfXJlcXVlc3RSYW5nZXMoZT1bXSl7Y29uc3QgdD1bXTtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPXRoaXMuZ2V0QmVnaW5DaHVuayhyLmJlZ2luKSxhPXRoaXMuZ2V0RW5kQ2h1bmsoci5lbmQpO2ZvcihsZXQgcj1lO3I8YTsrK3IpdC5pbmNsdWRlcyhyKXx8dC5wdXNoKHIpfXQuc29ydCgoZSx0KT0+ZS10KTtyZXR1cm4gdGhpcy5fcmVxdWVzdENodW5rcyh0KX1ncm91cENodW5rcyhlKXtjb25zdCB0PVtdO2xldCByPS0xLGE9LTE7Zm9yKGxldCBuPTAsaT1lLmxlbmd0aDtuPGk7KytuKXtjb25zdCBpPWVbbl07cjwwJiYocj1pKTtpZihhPj0wJiZhKzEhPT1pKXt0LnB1c2goe2JlZ2luQ2h1bms6cixlbmRDaHVuazphKzF9KTtyPWl9bisxPT09ZS5sZW5ndGgmJnQucHVzaCh7YmVnaW5DaHVuazpyLGVuZENodW5rOmkrMX0pO2E9aX1yZXR1cm4gdH1vblByb2dyZXNzKGUpe3RoaXMubXNnSGFuZGxlci5zZW5kKCJEb2NQcm9ncmVzcyIse2xvYWRlZDp0aGlzLnN0cmVhbS5udW1DaHVua3NMb2FkZWQqdGhpcy5jaHVua1NpemUrZS5sb2FkZWQsdG90YWw6dGhpcy5sZW5ndGh9KX1vblJlY2VpdmVEYXRhKGUpe2NvbnN0IHQ9ZS5jaHVuayxyPXZvaWQgMD09PWUuYmVnaW4sYT1yP3RoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoOmUuYmVnaW4sbj1hK3QuYnl0ZUxlbmd0aCxpPU1hdGguZmxvb3IoYS90aGlzLmNodW5rU2l6ZSkscz1uPHRoaXMubGVuZ3RoP01hdGguZmxvb3Iobi90aGlzLmNodW5rU2l6ZSk6TWF0aC5jZWlsKG4vdGhpcy5jaHVua1NpemUpO2lmKHIpe3RoaXMuc3RyZWFtLm9uUmVjZWl2ZVByb2dyZXNzaXZlRGF0YSh0KTt0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aD1ufWVsc2UgdGhpcy5zdHJlYW0ub25SZWNlaXZlRGF0YShhLHQpO3RoaXMuc3RyZWFtLmlzRGF0YUxvYWRlZCYmdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eS5yZXNvbHZlKHRoaXMuc3RyZWFtKTtjb25zdCBvPVtdO2ZvcihsZXQgZT1pO2U8czsrK2Upe2NvbnN0IHQ9dGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChlKTtpZih0KXt0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuZGVsZXRlKGUpO2Zvcihjb25zdCByIG9mIHQpe2NvbnN0IHQ9dGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LmdldChyKTt0LmhhcyhlKSYmdC5kZWxldGUoZSk7dC5zaXplPjB8fG8ucHVzaChyKX19fWlmKCF0aGlzLmRpc2FibGVBdXRvRmV0Y2gmJjA9PT10aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuc2l6ZSl7bGV0IGU7aWYoMT09PXRoaXMuc3RyZWFtLm51bUNodW5rc0xvYWRlZCl7Y29uc3QgdD10aGlzLnN0cmVhbS5udW1DaHVua3MtMTt0aGlzLnN0cmVhbS5oYXNDaHVuayh0KXx8KGU9dCl9ZWxzZSBlPXRoaXMuc3RyZWFtLm5leHRFbXB0eUNodW5rKHMpO051bWJlci5pc0ludGVnZXIoZSkmJnRoaXMuX3JlcXVlc3RDaHVua3MoW2VdKX1mb3IoY29uc3QgZSBvZiBvKXtjb25zdCB0PXRoaXMuX3Byb21pc2VzQnlSZXF1ZXN0LmdldChlKTt0aGlzLl9wcm9taXNlc0J5UmVxdWVzdC5kZWxldGUoZSk7dC5yZXNvbHZlKCl9dGhpcy5tc2dIYW5kbGVyLnNlbmQoIkRvY1Byb2dyZXNzIix7bG9hZGVkOnRoaXMuc3RyZWFtLm51bUNodW5rc0xvYWRlZCp0aGlzLmNodW5rU2l6ZSx0b3RhbDp0aGlzLmxlbmd0aH0pfW9uRXJyb3IoZSl7dGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eS5yZWplY3QoZSl9Z2V0QmVnaW5DaHVuayhlKXtyZXR1cm4gTWF0aC5mbG9vcihlL3RoaXMuY2h1bmtTaXplKX1nZXRFbmRDaHVuayhlKXtyZXR1cm4gTWF0aC5mbG9vcigoZS0xKS90aGlzLmNodW5rU2l6ZSkrMX1hYm9ydChlKXt0aGlzLmFib3J0ZWQ9ITA7dGhpcy5wZGZOZXR3b3JrU3RyZWFtPy5jYW5jZWxBbGxSZXF1ZXN0cyhlKTtmb3IoY29uc3QgdCBvZiB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdC52YWx1ZXMoKSl0LnJlamVjdChlKX19ZnVuY3Rpb24gY29udmVydFRvUkdCQShlKXtzd2l0Y2goZS5raW5kKXtjYXNlIHY6cmV0dXJuIGNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBKGUpO2Nhc2UgVDpyZXR1cm4gZnVuY3Rpb24gY29udmVydFJHQlRvUkdCQSh7c3JjOmUsc3JjUG9zOnQ9MCxkZXN0OnIsZGVzdFBvczphPTAsd2lkdGg6bixoZWlnaHQ6aX0pe2xldCBzPTA7Y29uc3Qgbz1uKmkqMyxjPW8+PjIsbD1uZXcgVWludDMyQXJyYXkoZS5idWZmZXIsdCxjKTtpZihGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbil7Zm9yKDtzPGMtMjtzKz0zLGErPTQpe2NvbnN0IGU9bFtzXSx0PWxbcysxXSxuPWxbcysyXTtyW2FdPTQyNzgxOTAwODB8ZTtyW2ErMV09ZT4+PjI0fHQ8PDh8NDI3ODE5MDA4MDtyW2ErMl09dD4+PjE2fG48PDE2fDQyNzgxOTAwODA7clthKzNdPW4+Pj44fDQyNzgxOTAwODB9Zm9yKGxldCBuPTQqcyxpPXQrbztuPGk7bis9MylyW2ErK109ZVtuXXxlW24rMV08PDh8ZVtuKzJdPDwxNnw0Mjc4MTkwMDgwfWVsc2V7Zm9yKDtzPGMtMjtzKz0zLGErPTQpe2NvbnN0IGU9bFtzXSx0PWxbcysxXSxuPWxbcysyXTtyW2FdPTI1NXxlO3JbYSsxXT1lPDwyNHx0Pj4+OHwyNTU7clthKzJdPXQ8PDE2fG4+Pj4xNnwyNTU7clthKzNdPW48PDh8MjU1fWZvcihsZXQgbj00KnMsaT10K287bjxpO24rPTMpclthKytdPWVbbl08PDI0fGVbbisxXTw8MTZ8ZVtuKzJdPDw4fDI1NX1yZXR1cm57c3JjUG9zOnQrbyxkZXN0UG9zOmF9fShlKX1yZXR1cm4gbnVsbH1mdW5jdGlvbiBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7c3JjOmUsc3JjUG9zOnQ9MCxkZXN0OnIsd2lkdGg6YSxoZWlnaHQ6bixub25CbGFja0NvbG9yOmk9NDI5NDk2NzI5NSxpbnZlcnNlRGVjb2RlOnM9ITF9KXtjb25zdCBvPUZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuPzQyNzgxOTAwODA6MjU1LFtjLGxdPXM/W2ksb106W28saV0saD1hPj4zLHU9NyZhLGQ9ZS5sZW5ndGg7cj1uZXcgVWludDMyQXJyYXkoci5idWZmZXIpO2xldCBmPTA7Zm9yKGxldCBhPTA7YTxuO2ErKyl7Zm9yKGNvbnN0IGE9dCtoO3Q8YTt0Kyspe2NvbnN0IGE9dDxkP2VbdF06MjU1O3JbZisrXT0xMjgmYT9sOmM7cltmKytdPTY0JmE/bDpjO3JbZisrXT0zMiZhP2w6YztyW2YrK109MTYmYT9sOmM7cltmKytdPTgmYT9sOmM7cltmKytdPTQmYT9sOmM7cltmKytdPTImYT9sOmM7cltmKytdPTEmYT9sOmN9aWYoMD09PXUpY29udGludWU7Y29uc3QgYT10PGQ/ZVt0KytdOjI1NTtmb3IobGV0IGU9MDtlPHU7ZSsrKXJbZisrXT1hJjE8PDctZT9sOmN9cmV0dXJue3NyY1Bvczp0LGRlc3RQb3M6Zn19Y2xhc3MgSW1hZ2VSZXNpemVye3N0YXRpYyNPPTIwNDg7c3RhdGljI009RmVhdHVyZVRlc3QuaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ7Y29uc3RydWN0b3IoZSx0KXt0aGlzLl9pbWdEYXRhPWU7dGhpcy5faXNNYXNrPXR9c3RhdGljIGdldCBjYW5Vc2VJbWFnZURlY29kZXIoKXtyZXR1cm4gc2hhZG93KHRoaXMsImNhblVzZUltYWdlRGVjb2RlciIsdGhpcy4jTT9JbWFnZURlY29kZXIuaXNUeXBlU3VwcG9ydGVkKCJpbWFnZS9ibXAiKTpQcm9taXNlLnJlc29sdmUoITEpKX1zdGF0aWMgbmVlZHNUb0JlUmVzaXplZChlLHQpe2lmKGU8PXRoaXMuI08mJnQ8PXRoaXMuI08pcmV0dXJuITE7Y29uc3R7TUFYX0RJTTpyfT10aGlzO2lmKGU+cnx8dD5yKXJldHVybiEwO2NvbnN0IGE9ZSp0O2lmKHRoaXMuX2hhc01heEFyZWEpcmV0dXJuIGE+dGhpcy5NQVhfQVJFQTtpZihhPHRoaXMuI08qKjIpcmV0dXJuITE7aWYodGhpcy5fYXJlR29vZERpbXMoZSx0KSl7dGhpcy4jTz1NYXRoLm1heCh0aGlzLiNPLE1hdGguZmxvb3IoTWF0aC5zcXJ0KGUqdCkpKTtyZXR1cm4hMX10aGlzLiNPPXRoaXMuX2d1ZXNzTWF4KHRoaXMuI08sciwxMjgsMCk7cmV0dXJuIGE+KHRoaXMuTUFYX0FSRUE9dGhpcy4jTyoqMil9c3RhdGljIGdldFJlZHVjZVBvd2VyRm9ySlBYKGUsdCxyKXtjb25zdCBhPWUqdCxuPTIqKjMwLyg0KnIpO2lmKCF0aGlzLm5lZWRzVG9CZVJlc2l6ZWQoZSx0KSlyZXR1cm4gYT5uP01hdGguY2VpbChNYXRoLmxvZzIoYS9uKSk6MDtjb25zdHtNQVhfRElNOmksTUFYX0FSRUE6c309dGhpcyxvPU1hdGgubWF4KGUvaSx0L2ksTWF0aC5zcXJ0KGEvTWF0aC5taW4obixzKSkpO3JldHVybiBNYXRoLmNlaWwoTWF0aC5sb2cyKG8pKX1zdGF0aWMgZ2V0IE1BWF9ESU0oKXtyZXR1cm4gc2hhZG93KHRoaXMsIk1BWF9ESU0iLHRoaXMuX2d1ZXNzTWF4KDIwNDgsNjU1MzcsMCwxKSl9c3RhdGljIGdldCBNQVhfQVJFQSgpe3RoaXMuX2hhc01heEFyZWE9ITA7cmV0dXJuIHNoYWRvdyh0aGlzLCJNQVhfQVJFQSIsdGhpcy5fZ3Vlc3NNYXgodGhpcy4jTyx0aGlzLk1BWF9ESU0sMTI4LDApKioyKX1zdGF0aWMgc2V0IE1BWF9BUkVBKGUpe2lmKGU+PTApe3RoaXMuX2hhc01heEFyZWE9ITA7c2hhZG93KHRoaXMsIk1BWF9BUkVBIixlKX19c3RhdGljIHNldE9wdGlvbnMoe2NhbnZhc01heEFyZWFJbkJ5dGVzOmU9LTEsaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ6dD0hMX0pe3RoaXMuX2hhc01heEFyZWF8fCh0aGlzLk1BWF9BUkVBPWU+PjIpO3RoaXMuI009dH1zdGF0aWMgX2FyZUdvb2REaW1zKGUsdCl7dHJ5e2NvbnN0IHI9bmV3IE9mZnNjcmVlbkNhbnZhcyhlLHQpLGE9ci5nZXRDb250ZXh0KCIyZCIpO2EuZmlsbFJlY3QoMCwwLDEsMSk7Y29uc3Qgbj1hLmdldEltYWdlRGF0YSgwLDAsMSwxKS5kYXRhWzNdO3Iud2lkdGg9ci5oZWlnaHQ9MTtyZXR1cm4gMCE9PW59Y2F0Y2h7cmV0dXJuITF9fXN0YXRpYyBfZ3Vlc3NNYXgoZSx0LHIsYSl7Zm9yKDtlK3IrMTx0Oyl7Y29uc3Qgcj1NYXRoLmZsb29yKChlK3QpLzIpLG49YXx8cjt0aGlzLl9hcmVHb29kRGltcyhyLG4pP2U9cjp0PXJ9cmV0dXJuIGV9c3RhdGljIGFzeW5jIGNyZWF0ZUltYWdlKGUsdD0hMSl7cmV0dXJuIG5ldyBJbWFnZVJlc2l6ZXIoZSx0KS5fY3JlYXRlSW1hZ2UoKX1hc3luYyBfY3JlYXRlSW1hZ2UoKXtjb25zdHtfaW1nRGF0YTplfT10aGlzLHt3aWR0aDp0LGhlaWdodDpyfT1lO2lmKHQqcio0PmRyKXtjb25zdCBlPXRoaXMuI0QoKTtpZihlKXJldHVybiBlfWNvbnN0IGE9dGhpcy5fZW5jb2RlQk1QKCk7bGV0IG4saTtpZihhd2FpdCBJbWFnZVJlc2l6ZXIuY2FuVXNlSW1hZ2VEZWNvZGVyKXtuPW5ldyBJbWFnZURlY29kZXIoe2RhdGE6YSx0eXBlOiJpbWFnZS9ibXAiLHByZWZlckFuaW1hdGlvbjohMSx0cmFuc2ZlcjpbYS5idWZmZXJdfSk7aT1uLmRlY29kZSgpLmNhdGNoKGU9Pnt3YXJuKGBCTVAgaW1hZ2UgZGVjb2RpbmcgZmFpbGVkOiAke2V9YCk7cmV0dXJuIGNyZWF0ZUltYWdlQml0bWFwKG5ldyBCbG9iKFt0aGlzLl9lbmNvZGVCTVAoKS5idWZmZXJdLHt0eXBlOiJpbWFnZS9ibXAifSkpfSkuZmluYWxseSgoKT0+e24uY2xvc2UoKX0pfWVsc2UgaT1jcmVhdGVJbWFnZUJpdG1hcChuZXcgQmxvYihbYS5idWZmZXJdLHt0eXBlOiJpbWFnZS9ibXAifSkpO2NvbnN0e01BWF9BUkVBOnMsTUFYX0RJTTpvfT1JbWFnZVJlc2l6ZXIsYz1NYXRoLm1heCh0L28sci9vLE1hdGguc3FydCh0KnIvcykpLGw9TWF0aC5tYXgoYywyKSxoPU1hdGgucm91bmQoMTAqKGMrMS4yNSkpLzEwL2wsdT1NYXRoLmZsb29yKE1hdGgubG9nMihoKSksZD1uZXcgQXJyYXkodSsyKS5maWxsKDIpO2RbMF09bDtkLnNwbGljZSgtMSwxLGgvKDE8PHUpKTtsZXQgZj10LGc9cjtjb25zdCBwPWF3YWl0IGk7bGV0IG09cC5pbWFnZXx8cDtmb3IoY29uc3QgZSBvZiBkKXtjb25zdCB0PWYscj1nO2Y9TWF0aC5mbG9vcihmL2UpLTE7Zz1NYXRoLmZsb29yKGcvZSktMTtjb25zdCBhPW5ldyBPZmZzY3JlZW5DYW52YXMoZixnKTthLmdldENvbnRleHQoIjJkIikuZHJhd0ltYWdlKG0sMCwwLHQsciwwLDAsZixnKTttLmNsb3NlKCk7bT1hLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpfWUuZGF0YT1udWxsO2UuYml0bWFwPW07ZS53aWR0aD1mO2UuaGVpZ2h0PWc7cmV0dXJuIGV9I0QoKXtjb25zdHtfaW1nRGF0YTplfT10aGlzLHtkYXRhOnQsd2lkdGg6cixoZWlnaHQ6YSxraW5kOm59PWUsaT1yKmEqNCxzPU1hdGguY2VpbChNYXRoLmxvZzIoaS9kcikpLG89cj4+cyxjPWE+PnM7bGV0IGwsaD1hO3RyeXtsPW5ldyBVaW50OEFycmF5KGkpfWNhdGNoe2xldCBlPU1hdGguZmxvb3IoTWF0aC5sb2cyKGkrMSkpO2Zvcig7Oyl0cnl7bD1uZXcgVWludDhBcnJheSgyKiplLTEpO2JyZWFrfWNhdGNoe2UtPTF9aD1NYXRoLmZsb29yKCgyKiplLTEpLyg0KnIpKTtjb25zdCB0PXIqaCo0O3Q8bC5sZW5ndGgmJihsPW5ldyBVaW50OEFycmF5KHQpKX1jb25zdCB1PW5ldyBVaW50MzJBcnJheShsLmJ1ZmZlciksZD1uZXcgVWludDMyQXJyYXkobypjKTtsZXQgZj0wLGc9MDtjb25zdCBwPU1hdGguY2VpbChhL2gpLG09YSVoPT09MD9hOmElaDtmb3IobGV0IGU9MDtlPHA7ZSsrKXtjb25zdCBhPWU8cC0xP2g6bTsoe3NyY1BvczpmfT1jb252ZXJ0VG9SR0JBKHtraW5kOm4sc3JjOnQsZGVzdDp1LHdpZHRoOnIsaGVpZ2h0OmEsaW52ZXJzZURlY29kZTp0aGlzLl9pc01hc2ssc3JjUG9zOmZ9KSk7Zm9yKGxldCBlPTAsdD1hPj5zO2U8dDtlKyspe2NvbnN0IHQ9dS5zdWJhcnJheSgoZTw8cykqcik7Zm9yKGxldCBlPTA7ZTxvO2UrKylkW2crK109dFtlPDxzXX19aWYoSW1hZ2VSZXNpemVyLm5lZWRzVG9CZVJlc2l6ZWQobyxjKSl7ZS5kYXRhPWQ7ZS53aWR0aD1vO2UuaGVpZ2h0PWM7ZS5raW5kPU87cmV0dXJuIG51bGx9Y29uc3QgYj1uZXcgT2Zmc2NyZWVuQ2FudmFzKG8sYyk7Yi5nZXRDb250ZXh0KCIyZCIse3dpbGxSZWFkRnJlcXVlbnRseTohMH0pLnB1dEltYWdlRGF0YShuZXcgSW1hZ2VEYXRhKG5ldyBVaW50OENsYW1wZWRBcnJheShkLmJ1ZmZlciksbyxjKSwwLDApO2UuZGF0YT1udWxsO2UuYml0bWFwPWIudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7ZS53aWR0aD1vO2UuaGVpZ2h0PWM7cmV0dXJuIGV9X2VuY29kZUJNUCgpe2NvbnN0e3dpZHRoOmUsaGVpZ2h0OnQsa2luZDpyfT10aGlzLl9pbWdEYXRhO2xldCBhLG49dGhpcy5faW1nRGF0YS5kYXRhLGk9bmV3IFVpbnQ4QXJyYXkoMCkscz1pLG89MDtzd2l0Y2gocil7Y2FzZSB2OnthPTE7aT1uZXcgVWludDhBcnJheSh0aGlzLl9pc01hc2s/WzI1NSwyNTUsMjU1LDI1NSwwLDAsMCwwXTpbMCwwLDAsMCwyNTUsMjU1LDI1NSwyNTVdKTtjb25zdCByPWUrNz4+MyxzPXIrMyYtNDtpZihyIT09cyl7Y29uc3QgZT1uZXcgVWludDhBcnJheShzKnQpO2xldCBhPTA7Zm9yKGxldCBpPTAsbz10KnI7aTxvO2krPXIsYSs9cyllLnNldChuLnN1YmFycmF5KGksaStyKSxhKTtuPWV9YnJlYWt9Y2FzZSBUOmE9MjQ7aWYoMyZlKXtjb25zdCByPTMqZSxhPXIrMyYtNCxpPWEtcixzPW5ldyBVaW50OEFycmF5KGEqdCk7bGV0IG89MDtmb3IobGV0IGU9MCxhPXQqcjtlPGE7ZSs9cil7Y29uc3QgdD1uLnN1YmFycmF5KGUsZStyKTtmb3IobGV0IGU9MDtlPHI7ZSs9Myl7c1tvKytdPXRbZSsyXTtzW28rK109dFtlKzFdO3NbbysrXT10W2VdfW8rPWl9bj1zfWVsc2UgZm9yKGxldCBlPTAsdD1uLmxlbmd0aDtlPHQ7ZSs9Myl7Y29uc3QgdD1uW2VdO25bZV09bltlKzJdO25bZSsyXT10fWJyZWFrO2Nhc2UgTzphPTMyO289MztzPW5ldyBVaW50OEFycmF5KDY4KTtjb25zdCByPW5ldyBEYXRhVmlldyhzLmJ1ZmZlcik7aWYoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4pe3Iuc2V0VWludDMyKDAsMjU1LCEwKTtyLnNldFVpbnQzMig0LDY1MjgwLCEwKTtyLnNldFVpbnQzMig4LDE2NzExNjgwLCEwKTtyLnNldFVpbnQzMigxMiw0Mjc4MTkwMDgwLCEwKX1lbHNle3Iuc2V0VWludDMyKDAsNDI3ODE5MDA4MCwhMCk7ci5zZXRVaW50MzIoNCwxNjcxMTY4MCwhMCk7ci5zZXRVaW50MzIoOCw2NTI4MCwhMCk7ci5zZXRVaW50MzIoMTIsMjU1LCEwKX1icmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcigiaW52YWxpZCBmb3JtYXQiKX1sZXQgYz0wO2NvbnN0IGw9NDArcy5sZW5ndGgsaD0xNCtsK2kubGVuZ3RoK24ubGVuZ3RoLHU9bmV3IFVpbnQ4QXJyYXkoaCksZD1uZXcgRGF0YVZpZXcodS5idWZmZXIpO2Quc2V0VWludDE2KGMsMTk3NzgsITApO2MrPTI7ZC5zZXRVaW50MzIoYyxoLCEwKTtjKz00O2Quc2V0VWludDMyKGMsMCwhMCk7Yys9NDtkLnNldFVpbnQzMihjLDE0K2wraS5sZW5ndGgsITApO2MrPTQ7ZC5zZXRVaW50MzIoYyxsLCEwKTtjKz00O2Quc2V0SW50MzIoYyxlLCEwKTtjKz00O2Quc2V0SW50MzIoYywtdCwhMCk7Yys9NDtkLnNldFVpbnQxNihjLDEsITApO2MrPTI7ZC5zZXRVaW50MTYoYyxhLCEwKTtjKz0yO2Quc2V0VWludDMyKGMsbywhMCk7Yys9NDtkLnNldFVpbnQzMihjLDAsITApO2MrPTQ7ZC5zZXRJbnQzMihjLDAsITApO2MrPTQ7ZC5zZXRJbnQzMihjLDAsITApO2MrPTQ7ZC5zZXRVaW50MzIoYyxpLmxlbmd0aC80LCEwKTtjKz00O2Quc2V0VWludDMyKGMsMCwhMCk7Yys9NDt1LnNldChzLGMpO2MrPXMubGVuZ3RoO3Uuc2V0KGksYyk7Yys9aS5sZW5ndGg7dS5zZXQobixjKTtyZXR1cm4gdX19Y29uc3QgQ3I9bmV3IFVpbnQ4QXJyYXkoMCk7Y2xhc3MgRGVjb2RlU3RyZWFtIGV4dGVuZHMgQmFzZVN0cmVhbXtjb25zdHJ1Y3RvcihlKXtzdXBlcigpO3RoaXMuX3Jhd01pbkJ1ZmZlckxlbmd0aD1lfHwwO3RoaXMucG9zPTA7dGhpcy5idWZmZXJMZW5ndGg9MDt0aGlzLmVvZj0hMTt0aGlzLmJ1ZmZlcj1Dcjt0aGlzLm1pbkJ1ZmZlckxlbmd0aD01MTI7aWYoZSlmb3IoO3RoaXMubWluQnVmZmVyTGVuZ3RoPGU7KXRoaXMubWluQnVmZmVyTGVuZ3RoKj0yfWdldCBpc0VtcHR5KCl7Zm9yKDshdGhpcy5lb2YmJjA9PT10aGlzLmJ1ZmZlckxlbmd0aDspdGhpcy5yZWFkQmxvY2soKTtyZXR1cm4gMD09PXRoaXMuYnVmZmVyTGVuZ3RofWVuc3VyZUJ1ZmZlcihlKXtjb25zdCB0PXRoaXMuYnVmZmVyO2lmKGU8PXQuYnl0ZUxlbmd0aClyZXR1cm4gdDtsZXQgcj10aGlzLm1pbkJ1ZmZlckxlbmd0aDtmb3IoO3I8ZTspcio9Mjtjb25zdCBhPW5ldyBVaW50OEFycmF5KHIpO2Euc2V0KHQpO3JldHVybiB0aGlzLmJ1ZmZlcj1hfWdldEJ5dGUoKXtjb25zdCBlPXRoaXMucG9zO2Zvcig7dGhpcy5idWZmZXJMZW5ndGg8PWU7KXtpZih0aGlzLmVvZilyZXR1cm4tMTt0aGlzLnJlYWRCbG9jaygpfXJldHVybiB0aGlzLmJ1ZmZlclt0aGlzLnBvcysrXX1nZXRCeXRlcyhlLHQ9bnVsbCl7Y29uc3Qgcj10aGlzLnBvcztsZXQgYTtpZihlKXt0aGlzLmVuc3VyZUJ1ZmZlcihyK2UpO2E9citlO2Zvcig7IXRoaXMuZW9mJiZ0aGlzLmJ1ZmZlckxlbmd0aDxhOyl0aGlzLnJlYWRCbG9jayh0KTtjb25zdCBuPXRoaXMuYnVmZmVyTGVuZ3RoO2E+biYmKGE9bil9ZWxzZXtmb3IoOyF0aGlzLmVvZjspdGhpcy5yZWFkQmxvY2sodCk7YT10aGlzLmJ1ZmZlckxlbmd0aH10aGlzLnBvcz1hO3JldHVybiB0aGlzLmJ1ZmZlci5zdWJhcnJheShyLGEpfWFzeW5jIGdldEltYWdlRGF0YShlLHQpe2lmKCF0aGlzLmNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKXJldHVybiB0aGlzLmlzQXN5bmNEZWNvZGVyP3RoaXMuZGVjb2RlSW1hZ2UobnVsbCx0KTp0aGlzLmdldEJ5dGVzKGUsdCk7Y29uc3Qgcj1hd2FpdCB0aGlzLnN0cmVhbS5hc3luY0dldEJ5dGVzKCk7cmV0dXJuIHRoaXMuZGVjb2RlSW1hZ2Uocix0KX1yZXNldCgpe3RoaXMucG9zPTB9bWFrZVN1YlN0cmVhbShlLHQscj1udWxsKXtpZih2b2lkIDA9PT10KWZvcig7IXRoaXMuZW9mOyl0aGlzLnJlYWRCbG9jaygpO2Vsc2V7Y29uc3Qgcj1lK3Q7Zm9yKDt0aGlzLmJ1ZmZlckxlbmd0aDw9ciYmIXRoaXMuZW9mOyl0aGlzLnJlYWRCbG9jaygpfXJldHVybiBuZXcgU3RyZWFtKHRoaXMuYnVmZmVyLGUsdCxyKX1nZXRCYXNlU3RyZWFtcygpe3JldHVybiB0aGlzLnN0cj90aGlzLnN0ci5nZXRCYXNlU3RyZWFtcygpOm51bGx9fWNsYXNzIFN0cmVhbXNTZXF1ZW5jZVN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbXtjb25zdHJ1Y3RvcihlLHQ9bnVsbCl7ZT1lLmZpbHRlcihlPT5lIGluc3RhbmNlb2YgQmFzZVN0cmVhbSk7bGV0IHI9MDtmb3IoY29uc3QgdCBvZiBlKXIrPXQgaW5zdGFuY2VvZiBEZWNvZGVTdHJlYW0/dC5fcmF3TWluQnVmZmVyTGVuZ3RoOnQubGVuZ3RoO3N1cGVyKHIpO3RoaXMuc3RyZWFtcz1lO3RoaXMuX29uRXJyb3I9dH1yZWFkQmxvY2soKXtjb25zdCBlPXRoaXMuc3RyZWFtcztpZigwPT09ZS5sZW5ndGgpe3RoaXMuZW9mPSEwO3JldHVybn1jb25zdCB0PWUuc2hpZnQoKTtsZXQgcjt0cnl7cj10LmdldEJ5dGVzKCl9Y2F0Y2goZSl7aWYodGhpcy5fb25FcnJvcil7dGhpcy5fb25FcnJvcihlLHQuZGljdD8ub2JqSWQpO3JldHVybn10aHJvdyBlfWNvbnN0IGE9dGhpcy5idWZmZXJMZW5ndGgsbj1hK3IubGVuZ3RoO3RoaXMuZW5zdXJlQnVmZmVyKG4pLnNldChyLGEpO3RoaXMuYnVmZmVyTGVuZ3RoPW59Z2V0QmFzZVN0cmVhbXMoKXtjb25zdCBlPVtdO2Zvcihjb25zdCB0IG9mIHRoaXMuc3RyZWFtcyl7Y29uc3Qgcj10LmdldEJhc2VTdHJlYW1zKCk7ciYmZS5wdXNoKC4uLnIpfXJldHVybiBlLmxlbmd0aD4wP2U6bnVsbH19Y2xhc3MgQ29sb3JTcGFjZVV0aWxze3N0YXRpYyBwYXJzZSh7Y3M6ZSx4cmVmOnQscmVzb3VyY2VzOnI9bnVsbCxwZGZGdW5jdGlvbkZhY3Rvcnk6YSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6bixsb2NhbENvbG9yU3BhY2VDYWNoZTppLGFzeW5jSWZOb3RDYWNoZWQ6cz0hMX0pe2NvbnN0IG89e3hyZWY6dCxyZXNvdXJjZXM6cixwZGZGdW5jdGlvbkZhY3Rvcnk6YSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6bixsb2NhbENvbG9yU3BhY2VDYWNoZTppfTtsZXQgYyxsLGg7aWYoZSBpbnN0YW5jZW9mIFJlZil7bD1lO2NvbnN0IHI9bi5nZXRCeVJlZihsKXx8aS5nZXRCeVJlZihsKTtpZihyKXJldHVybiByO2U9dC5mZXRjaChlKX1pZihlIGluc3RhbmNlb2YgTmFtZSl7Yz1lLm5hbWU7Y29uc3QgdD1pLmdldEJ5TmFtZShjKTtpZih0KXJldHVybiB0fXRyeXtoPXRoaXMuI0IoZSxvKX1jYXRjaChlKXtpZihzJiYhKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikpcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO3Rocm93IGV9aWYoY3x8bCl7aS5zZXQoYyxsLGgpO2wmJm4uc2V0KG51bGwsbCxoKX1yZXR1cm4gcz9Qcm9taXNlLnJlc29sdmUoaCk6aH1zdGF0aWMjUihlLHQpe2NvbnN0e2dsb2JhbENvbG9yU3BhY2VDYWNoZTpyfT10O2xldCBhO2lmKGUgaW5zdGFuY2VvZiBSZWYpe2E9ZTtjb25zdCB0PXIuZ2V0QnlSZWYoYSk7aWYodClyZXR1cm4gdH1jb25zdCBuPXRoaXMuI0IoZSx0KTthJiZyLnNldChudWxsLGEsbik7cmV0dXJuIG59c3RhdGljI0IoZSx0KXtjb25zdHt4cmVmOnIscmVzb3VyY2VzOmEscGRmRnVuY3Rpb25GYWN0b3J5Om4sZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOml9PXQ7aWYoKGU9ci5mZXRjaElmUmVmKGUpKWluc3RhbmNlb2YgTmFtZSlzd2l0Y2goZS5uYW1lKXtjYXNlIkciOmNhc2UiRGV2aWNlR3JheSI6cmV0dXJuIHRoaXMuZ3JheTtjYXNlIlJHQiI6Y2FzZSJEZXZpY2VSR0IiOnJldHVybiB0aGlzLnJnYjtjYXNlIkRldmljZVJHQkEiOnJldHVybiB0aGlzLnJnYmE7Y2FzZSJDTVlLIjpjYXNlIkRldmljZUNNWUsiOnJldHVybiB0aGlzLmNteWs7Y2FzZSJQYXR0ZXJuIjpyZXR1cm4gbmV3IFBhdHRlcm5DUyhudWxsKTtkZWZhdWx0OmlmKGEgaW5zdGFuY2VvZiBEaWN0KXtjb25zdCByPWEuZ2V0KCJDb2xvclNwYWNlIik7aWYociBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IGE9ci5nZXQoZS5uYW1lKTtpZihhKXtpZihhIGluc3RhbmNlb2YgTmFtZSlyZXR1cm4gdGhpcy4jQihhLHQpO2U9YTticmVha319fXdhcm4oYFVucmVjb2duaXplZCBDb2xvclNwYWNlOiAke2UubmFtZX1gKTtyZXR1cm4gdGhpcy5ncmF5fWlmKEFycmF5LmlzQXJyYXkoZSkpe2NvbnN0IGE9ci5mZXRjaElmUmVmKGVbMF0pLm5hbWU7bGV0IHMsbyxjLGwsaCx1O3N3aXRjaChhKXtjYXNlIkciOmNhc2UiRGV2aWNlR3JheSI6cmV0dXJuIHRoaXMuZ3JheTtjYXNlIlJHQiI6Y2FzZSJEZXZpY2VSR0IiOnJldHVybiB0aGlzLnJnYjtjYXNlIkNNWUsiOmNhc2UiRGV2aWNlQ01ZSyI6cmV0dXJuIHRoaXMuY215aztjYXNlIkNhbEdyYXkiOnM9ci5mZXRjaElmUmVmKGVbMV0pO2w9cy5nZXRBcnJheSgiV2hpdGVQb2ludCIpO2g9cy5nZXRBcnJheSgiQmxhY2tQb2ludCIpO3U9cy5nZXQoIkdhbW1hIik7cmV0dXJuIG5ldyBDYWxHcmF5Q1MobCxoLHUpO2Nhc2UiQ2FsUkdCIjpzPXIuZmV0Y2hJZlJlZihlWzFdKTtsPXMuZ2V0QXJyYXkoIldoaXRlUG9pbnQiKTtoPXMuZ2V0QXJyYXkoIkJsYWNrUG9pbnQiKTt1PXMuZ2V0QXJyYXkoIkdhbW1hIik7Y29uc3QgZD1zLmdldEFycmF5KCJNYXRyaXgiKTtyZXR1cm4gbmV3IENhbFJHQkNTKGwsaCx1LGQpO2Nhc2UiSUNDQmFzZWQiOmNvbnN0IGY9ZVsxXWluc3RhbmNlb2YgUmVmO2lmKGYpe2NvbnN0IHQ9aS5nZXRCeVJlZihlWzFdKTtpZih0KXJldHVybiB0fWNvbnN0IGc9ci5mZXRjaElmUmVmKGVbMV0pLHA9Zy5kaWN0O289cC5nZXQoIk4iKTtpZihJY2NDb2xvclNwYWNlLmlzVXNhYmxlKXRyeXtjb25zdCB0PW5ldyBJY2NDb2xvclNwYWNlKGcuZ2V0Qnl0ZXMoKSwiSUNDQmFzZWQiLG8pO2YmJmkuc2V0KG51bGwsZVsxXSx0KTtyZXR1cm4gdH1jYXRjaCh0KXtpZih0IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgdDt3YXJuKGBJQ0NCYXNlZCBjb2xvciBzcGFjZSAoJHtlWzFdfSk6ICIke3R9Ii5gKX1jb25zdCBtPXAuZ2V0UmF3KCJBbHRlcm5hdGUiKTtpZihtKXtjb25zdCBlPXRoaXMuI1IobSx0KTtpZihlLm51bUNvbXBzPT09bylyZXR1cm4gZTt3YXJuKCJJQ0NCYXNlZCBjb2xvciBzcGFjZTogSWdub3JpbmcgaW5jb3JyZWN0IC9BbHRlcm5hdGUgZW50cnkuIil9aWYoMT09PW8pcmV0dXJuIHRoaXMuZ3JheTtpZigzPT09bylyZXR1cm4gdGhpcy5yZ2I7aWYoND09PW8pcmV0dXJuIHRoaXMuY215azticmVhaztjYXNlIlBhdHRlcm4iOmM9ZVsxXXx8bnVsbDtjJiYoYz10aGlzLiNSKGMsdCkpO3JldHVybiBuZXcgUGF0dGVybkNTKGMpO2Nhc2UiSSI6Y2FzZSJJbmRleGVkIjpjPXRoaXMuI1IoZVsxXSx0KTtjb25zdCBiPU1hdGhDbGFtcChyLmZldGNoSWZSZWYoZVsyXSksMCwyNTUpLHk9ci5mZXRjaElmUmVmKGVbM10pO3JldHVybiBuZXcgSW5kZXhlZENTKGMsYix5KTtjYXNlIlNlcGFyYXRpb24iOmNhc2UiRGV2aWNlTiI6Y29uc3Qgdz1yLmZldGNoSWZSZWYoZVsxXSk7bz1BcnJheS5pc0FycmF5KHcpP3cubGVuZ3RoOjE7Yz10aGlzLiNSKGVbMl0sdCk7Y29uc3QgeD1uLmNyZWF0ZShlWzNdKTtyZXR1cm4gbmV3IEFsdGVybmF0ZUNTKG8sYyx4KTtjYXNlIkxhYiI6cz1yLmZldGNoSWZSZWYoZVsxXSk7bD1zLmdldEFycmF5KCJXaGl0ZVBvaW50Iik7aD1zLmdldEFycmF5KCJCbGFja1BvaW50Iik7Y29uc3QgUz1zLmdldEFycmF5KCJSYW5nZSIpO3JldHVybiBuZXcgTGFiQ1MobCxoLFMpO2RlZmF1bHQ6d2FybihgVW5pbXBsZW1lbnRlZCBDb2xvclNwYWNlIG9iamVjdDogJHthfWApO3JldHVybiB0aGlzLmdyYXl9fXdhcm4oYFVucmVjb2duaXplZCBDb2xvclNwYWNlIG9iamVjdDogJHtlfWApO3JldHVybiB0aGlzLmdyYXl9c3RhdGljIGdldCBncmF5KCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJncmF5IixuZXcgRGV2aWNlR3JheUNTKX1zdGF0aWMgZ2V0IHJnYigpe3JldHVybiBzaGFkb3codGhpcywicmdiIixuZXcgRGV2aWNlUmdiQ1MpfXN0YXRpYyBnZXQgcmdiYSgpe3JldHVybiBzaGFkb3codGhpcywicmdiYSIsbmV3IERldmljZVJnYmFDUyl9c3RhdGljIGdldCBjbXlrKCl7aWYoQ215a0lDQ0Jhc2VkQ1MuaXNVc2FibGUpdHJ5e3JldHVybiBzaGFkb3codGhpcywiY215ayIsbmV3IENteWtJQ0NCYXNlZENTKX1jYXRjaHt3YXJuKCJDTVlLIGZhbGxiYWNrOiBEZXZpY2VDTVlLIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJjbXlrIixuZXcgRGV2aWNlQ215a0NTKX19Y2xhc3MgSnBlZ0Vycm9yIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiSnBlZ0Vycm9yIil9fWNsYXNzIEROTE1hcmtlckVycm9yIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihlLCJETkxNYXJrZXJFcnJvciIpO3RoaXMuc2NhbkxpbmVzPXR9fWNsYXNzIEVPSU1hcmtlckVycm9yIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiRU9JTWFya2VyRXJyb3IiKX19Y29uc3QgdnI9bmV3IFVpbnQ4QXJyYXkoWzAsMSw4LDE2LDksMiwzLDEwLDE3LDI0LDMyLDI1LDE4LDExLDQsNSwxMiwxOSwyNiwzMyw0MCw0OCw0MSwzNCwyNywyMCwxMyw2LDcsMTQsMjEsMjgsMzUsNDIsNDksNTYsNTcsNTAsNDMsMzYsMjksMjIsMTUsMjMsMzAsMzcsNDQsNTEsNTgsNTksNTIsNDUsMzgsMzEsMzksNDYsNTMsNjAsNjEsNTQsNDcsNTUsNjIsNjNdKSxGcj00MDE3LElyPTc5OSxUcj0zNDA2LE9yPTIyNzYsTXI9MTU2NyxEcj0zNzg0LFJyPTU3OTMsRXI9Mjg5NjtmdW5jdGlvbiBidWlsZEh1ZmZtYW5UYWJsZShlLHQpe2xldCByLGEsbj0wLGk9MTY7Zm9yKDtpPjAmJiFlW2ktMV07KWktLTtjb25zdCBzPVt7Y2hpbGRyZW46W10saW5kZXg6MH1dO2xldCBvLGM9c1swXTtmb3Iocj0wO3I8aTtyKyspe2ZvcihhPTA7YTxlW3JdO2ErKyl7Yz1zLnBvcCgpO2MuY2hpbGRyZW5bYy5pbmRleF09dFtuXTtmb3IoO2MuaW5kZXg+MDspYz1zLnBvcCgpO2MuaW5kZXgrKztzLnB1c2goYyk7Zm9yKDtzLmxlbmd0aDw9cjspe3MucHVzaChvPXtjaGlsZHJlbjpbXSxpbmRleDowfSk7Yy5jaGlsZHJlbltjLmluZGV4XT1vLmNoaWxkcmVuO2M9b31uKyt9aWYocisxPGkpe3MucHVzaChvPXtjaGlsZHJlbjpbXSxpbmRleDowfSk7Yy5jaGlsZHJlbltjLmluZGV4XT1vLmNoaWxkcmVuO2M9b319cmV0dXJuIHNbMF0uY2hpbGRyZW59ZnVuY3Rpb24gZ2V0QmxvY2tCdWZmZXJPZmZzZXQoZSx0LHIpe3JldHVybiA2NCooKGUuYmxvY2tzUGVyTGluZSsxKSp0K3IpfWZ1bmN0aW9uIGRlY29kZVNjYW4oZSx0LHIsYSxuLGkscyxvLGMsbD0hMSl7Y29uc3QgaD1yLm1jdXNQZXJMaW5lLHU9ci5wcm9ncmVzc2l2ZSxkPXQ7bGV0IGY9MCxnPTA7ZnVuY3Rpb24gcmVhZEJpdCgpe2lmKGc+MCl7Zy0tO3JldHVybiBmPj5nJjF9Zj1lW3QrK107aWYoMjU1PT09Zil7Y29uc3QgYT1lW3QrK107aWYoYSl7aWYoMjIwPT09YSYmbCl7Y29uc3QgYT1yZWFkVWludDE2KGUsdCs9Mik7dCs9MjtpZihhPjAmJmEhPT1yLnNjYW5MaW5lcyl0aHJvdyBuZXcgRE5MTWFya2VyRXJyb3IoIkZvdW5kIEROTCBtYXJrZXIgKDB4RkZEQykgd2hpbGUgcGFyc2luZyBzY2FuIGRhdGEiLGEpfWVsc2UgaWYoMjE3PT09YSl7aWYobCl7Y29uc3QgZT15Kig4PT09ci5wcmVjaXNpb24/ODowKTtpZihlPjAmJk1hdGgucm91bmQoci5zY2FuTGluZXMvZSk+PTUpdGhyb3cgbmV3IEROTE1hcmtlckVycm9yKCJGb3VuZCBFT0kgbWFya2VyICgweEZGRDkpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhLCBwb3NzaWJseSBjYXVzZWQgYnkgaW5jb3JyZWN0IGBzY2FuTGluZXNgIHBhcmFtZXRlciIsZSl9dGhyb3cgbmV3IEVPSU1hcmtlckVycm9yKCJGb3VuZCBFT0kgbWFya2VyICgweEZGRDkpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhIil9dGhyb3cgbmV3IEpwZWdFcnJvcihgdW5leHBlY3RlZCBtYXJrZXIgJHsoZjw8OHxhKS50b1N0cmluZygxNil9YCl9fWc9NztyZXR1cm4gZj4+Pjd9ZnVuY3Rpb24gZGVjb2RlSHVmZm1hbihlKXtsZXQgdD1lO2Zvcig7Oyl7dD10W3JlYWRCaXQoKV07c3dpdGNoKHR5cGVvZiB0KXtjYXNlIm51bWJlciI6cmV0dXJuIHQ7Y2FzZSJvYmplY3QiOmNvbnRpbnVlfXRocm93IG5ldyBKcGVnRXJyb3IoImludmFsaWQgaHVmZm1hbiBzZXF1ZW5jZSIpfX1mdW5jdGlvbiByZWNlaXZlKGUpe2xldCB0PTA7Zm9yKDtlPjA7KXt0PXQ8PDF8cmVhZEJpdCgpO2UtLX1yZXR1cm4gdH1mdW5jdGlvbiByZWNlaXZlQW5kRXh0ZW5kKGUpe2lmKDE9PT1lKXJldHVybiAxPT09cmVhZEJpdCgpPzE6LTE7Y29uc3QgdD1yZWNlaXZlKGUpO3JldHVybiB0Pj0xPDxlLTE/dDp0KygtMTw8ZSkrMX1sZXQgcD0wO2xldCBtLGI9MDtsZXQgeT0wO2Z1bmN0aW9uIGRlY29kZU1jdShlLHQscixhLG4pe2NvbnN0IGk9ciVoO3k9KHIvaHwwKSplLnYrYTtjb25zdCBzPWkqZS5oK247dChlLGdldEJsb2NrQnVmZmVyT2Zmc2V0KGUseSxzKSl9ZnVuY3Rpb24gZGVjb2RlQmxvY2soZSx0LHIpe3k9ci9lLmJsb2Nrc1BlckxpbmV8MDtjb25zdCBhPXIlZS5ibG9ja3NQZXJMaW5lO3QoZSxnZXRCbG9ja0J1ZmZlck9mZnNldChlLHksYSkpfWNvbnN0IHc9YS5sZW5ndGg7bGV0IHgsUyxrLEMsdixUO1Q9dT8wPT09aT8wPT09bz9mdW5jdGlvbiBkZWNvZGVEQ0ZpcnN0KGUsdCl7Y29uc3Qgcj1kZWNvZGVIdWZmbWFuKGUuaHVmZm1hblRhYmxlREMpLGE9MD09PXI/MDpyZWNlaXZlQW5kRXh0ZW5kKHIpPDxjO2UuYmxvY2tEYXRhW3RdPWUucHJlZCs9YX06ZnVuY3Rpb24gZGVjb2RlRENTdWNjZXNzaXZlKGUsdCl7ZS5ibG9ja0RhdGFbdF18PXJlYWRCaXQoKTw8Y306MD09PW8/ZnVuY3Rpb24gZGVjb2RlQUNGaXJzdChlLHQpe2lmKHA+MCl7cC0tO3JldHVybn1sZXQgcj1pO2NvbnN0IGE9cztmb3IoO3I8PWE7KXtjb25zdCBhPWRlY29kZUh1ZmZtYW4oZS5odWZmbWFuVGFibGVBQyksbj0xNSZhLGk9YT4+NDtpZigwPT09bil7aWYoaTwxNSl7cD1yZWNlaXZlKGkpKygxPDxpKS0xO2JyZWFrfXIrPTE2O2NvbnRpbnVlfXIrPWk7Y29uc3Qgcz12cltyXTtlLmJsb2NrRGF0YVt0K3NdPXJlY2VpdmVBbmRFeHRlbmQobikqKDE8PGMpO3IrK319OmZ1bmN0aW9uIGRlY29kZUFDU3VjY2Vzc2l2ZShlLHQpe2xldCByPWk7Y29uc3QgYT1zO2xldCBuLG8sbD0wO2Zvcig7cjw9YTspe2NvbnN0IGE9dCt2cltyXSxpPWUuYmxvY2tEYXRhW2FdPDA/LTE6MTtzd2l0Y2goYil7Y2FzZSAwOm89ZGVjb2RlSHVmZm1hbihlLmh1ZmZtYW5UYWJsZUFDKTtuPTE1Jm87bD1vPj40O2lmKDA9PT1uKWlmKGw8MTUpe3A9cmVjZWl2ZShsKSsoMTw8bCk7Yj00fWVsc2V7bD0xNjtiPTF9ZWxzZXtpZigxIT09bil0aHJvdyBuZXcgSnBlZ0Vycm9yKCJpbnZhbGlkIEFDbiBlbmNvZGluZyIpO209cmVjZWl2ZUFuZEV4dGVuZChuKTtiPWw/MjozfWNvbnRpbnVlO2Nhc2UgMTpjYXNlIDI6aWYoZS5ibG9ja0RhdGFbYV0pZS5ibG9ja0RhdGFbYV0rPWkqKHJlYWRCaXQoKTw8Yyk7ZWxzZXtsLS07MD09PWwmJihiPTI9PT1iPzM6MCl9YnJlYWs7Y2FzZSAzOmlmKGUuYmxvY2tEYXRhW2FdKWUuYmxvY2tEYXRhW2FdKz1pKihyZWFkQml0KCk8PGMpO2Vsc2V7ZS5ibG9ja0RhdGFbYV09bTw8YztiPTB9YnJlYWs7Y2FzZSA0OmUuYmxvY2tEYXRhW2FdJiYoZS5ibG9ja0RhdGFbYV0rPWkqKHJlYWRCaXQoKTw8YykpfXIrK31pZig0PT09Yil7cC0tOzA9PT1wJiYoYj0wKX19OmZ1bmN0aW9uIGRlY29kZUJhc2VsaW5lKGUsdCl7Y29uc3Qgcj1kZWNvZGVIdWZmbWFuKGUuaHVmZm1hblRhYmxlREMpLGE9MD09PXI/MDpyZWNlaXZlQW5kRXh0ZW5kKHIpO2UuYmxvY2tEYXRhW3RdPWUucHJlZCs9YTtsZXQgbj0xO2Zvcig7bjw2NDspe2NvbnN0IHI9ZGVjb2RlSHVmZm1hbihlLmh1ZmZtYW5UYWJsZUFDKSxhPTE1JnIsaT1yPj40O2lmKDA9PT1hKXtpZihpPDE1KWJyZWFrO24rPTE2O2NvbnRpbnVlfW4rPWk7Y29uc3Qgcz12cltuXTtlLmJsb2NrRGF0YVt0K3NdPXJlY2VpdmVBbmRFeHRlbmQoYSk7bisrfX07bGV0IE8sTT0wO2NvbnN0IEQ9MT09PXc/YVswXS5ibG9ja3NQZXJMaW5lKmFbMF0uYmxvY2tzUGVyQ29sdW1uOmgqci5tY3VzUGVyQ29sdW1uO2xldCBSLEU7Zm9yKDtNPD1EOyl7Y29uc3Qgcj1uP01hdGgubWluKEQtTSxuKTpEO2lmKHI+MCl7Zm9yKFM9MDtTPHc7UysrKWFbU10ucHJlZD0wO3A9MDtpZigxPT09dyl7eD1hWzBdO2Zvcih2PTA7djxyO3YrKyl7ZGVjb2RlQmxvY2soeCxULE0pO00rK319ZWxzZSBmb3Iodj0wO3Y8cjt2Kyspe2ZvcihTPTA7Uzx3O1MrKyl7eD1hW1NdO1I9eC5oO0U9eC52O2ZvcihrPTA7azxFO2srKylmb3IoQz0wO0M8UjtDKyspZGVjb2RlTWN1KHgsVCxNLGssQyl9TSsrfX1nPTA7Tz1maW5kTmV4dEZpbGVNYXJrZXIoZSx0KTtpZighTylicmVhaztpZihPLmludmFsaWQpe3dhcm4oYGRlY29kZVNjYW4gLSAke3I+MD8idW5leHBlY3RlZCI6ImV4Y2Vzc2l2ZSJ9IE1DVSBkYXRhLCBjdXJyZW50IG1hcmtlciBpczogJHtPLmludmFsaWR9YCk7dD1PLm9mZnNldH1pZighKE8ubWFya2VyPj02NTQ4OCYmTy5tYXJrZXI8PTY1NDk1KSlicmVhazt0Kz0yfXJldHVybiB0LWR9ZnVuY3Rpb24gcXVhbnRpemVBbmRJbnZlcnNlKGUsdCxyKXtjb25zdCBhPWUucXVhbnRpemF0aW9uVGFibGUsbj1lLmJsb2NrRGF0YTtsZXQgaSxzLG8sYyxsLGgsdSxkLGYsZyxwLG0sYix5LHcseCxTO2lmKCFhKXRocm93IG5ldyBKcGVnRXJyb3IoIm1pc3NpbmcgcmVxdWlyZWQgUXVhbnRpemF0aW9uIFRhYmxlLiIpO2ZvcihsZXQgZT0wO2U8NjQ7ZSs9OCl7Zj1uW3QrZV07Zz1uW3QrZSsxXTtwPW5bdCtlKzJdO209blt0K2UrM107Yj1uW3QrZSs0XTt5PW5bdCtlKzVdO3c9blt0K2UrNl07eD1uW3QrZSs3XTtmKj1hW2VdO2lmKDAhPT0oZ3xwfG18Ynx5fHd8eCkpe2cqPWFbZSsxXTtwKj1hW2UrMl07bSo9YVtlKzNdO2IqPWFbZSs0XTt5Kj1hW2UrNV07dyo9YVtlKzZdO3gqPWFbZSs3XTtpPVJyKmYrMTI4Pj44O3M9UnIqYisxMjg+Pjg7bz1wO2M9dztsPUVyKihnLXgpKzEyOD4+ODtkPUVyKihnK3gpKzEyOD4+ODtoPW08PDQ7dT15PDw0O2k9aStzKzE+PjE7cz1pLXM7Uz1vKkRyK2MqTXIrMTI4Pj44O289bypNci1jKkRyKzEyOD4+ODtjPVM7bD1sK3UrMT4+MTt1PWwtdTtkPWQraCsxPj4xO2g9ZC1oO2k9aStjKzE+PjE7Yz1pLWM7cz1zK28rMT4+MTtvPXMtbztTPWwqT3IrZCpUcisyMDQ4Pj4xMjtsPWwqVHItZCpPcisyMDQ4Pj4xMjtkPVM7Uz1oKklyK3UqRnIrMjA0OD4+MTI7aD1oKkZyLXUqSXIrMjA0OD4+MTI7dT1TO3JbZV09aStkO3JbZSs3XT1pLWQ7cltlKzFdPXMrdTtyW2UrNl09cy11O3JbZSsyXT1vK2g7cltlKzVdPW8taDtyW2UrM109YytsO3JbZSs0XT1jLWx9ZWxzZXtTPVJyKmYrNTEyPj4xMDtyW2VdPVM7cltlKzFdPVM7cltlKzJdPVM7cltlKzNdPVM7cltlKzRdPVM7cltlKzVdPVM7cltlKzZdPVM7cltlKzddPVN9fWZvcihsZXQgZT0wO2U8ODsrK2Upe2Y9cltlXTtnPXJbZSs4XTtwPXJbZSsxNl07bT1yW2UrMjRdO2I9cltlKzMyXTt5PXJbZSs0MF07dz1yW2UrNDhdO3g9cltlKzU2XTtpZigwIT09KGd8cHxtfGJ8eXx3fHgpKXtpPVJyKmYrMjA0OD4+MTI7cz1ScipiKzIwNDg+PjEyO289cDtjPXc7bD1FciooZy14KSsyMDQ4Pj4xMjtkPUVyKihnK3gpKzIwNDg+PjEyO2g9bTt1PXk7aT00MTEyKyhpK3MrMT4+MSk7cz1pLXM7Uz1vKkRyK2MqTXIrMjA0OD4+MTI7bz1vKk1yLWMqRHIrMjA0OD4+MTI7Yz1TO2w9bCt1KzE+PjE7dT1sLXU7ZD1kK2grMT4+MTtoPWQtaDtpPWkrYysxPj4xO2M9aS1jO3M9cytvKzE+PjE7bz1zLW87Uz1sKk9yK2QqVHIrMjA0OD4+MTI7bD1sKlRyLWQqT3IrMjA0OD4+MTI7ZD1TO1M9aCpJcit1KkZyKzIwNDg+PjEyO2g9aCpGci11KklyKzIwNDg+PjEyO3U9UztmPWkrZDt4PWktZDtnPXMrdTt3PXMtdTtwPW8raDt5PW8taDttPWMrbDtiPWMtbDtmPDE2P2Y9MDpmPj00MDgwP2Y9MjU1OmY+Pj00O2c8MTY/Zz0wOmc+PTQwODA/Zz0yNTU6Zz4+PTQ7cDwxNj9wPTA6cD49NDA4MD9wPTI1NTpwPj49NDttPDE2P209MDptPj00MDgwP209MjU1Om0+Pj00O2I8MTY/Yj0wOmI+PTQwODA/Yj0yNTU6Yj4+PTQ7eTwxNj95PTA6eT49NDA4MD95PTI1NTp5Pj49NDt3PDE2P3c9MDp3Pj00MDgwP3c9MjU1Onc+Pj00O3g8MTY/eD0wOng+PTQwODA/eD0yNTU6eD4+PTQ7blt0K2VdPWY7blt0K2UrOF09ZztuW3QrZSsxNl09cDtuW3QrZSsyNF09bTtuW3QrZSszMl09YjtuW3QrZSs0MF09eTtuW3QrZSs0OF09dztuW3QrZSs1Nl09eH1lbHNle1M9UnIqZis4MTkyPj4xNDtTPVM8LTIwNDA/MDpTPj0yMDI0PzI1NTpTKzIwNTY+PjQ7blt0K2VdPVM7blt0K2UrOF09UztuW3QrZSsxNl09UztuW3QrZSsyNF09UztuW3QrZSszMl09UztuW3QrZSs0MF09UztuW3QrZSs0OF09UztuW3QrZSs1Nl09U319fWZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50RGF0YShlLHQpe2NvbnN0IHI9dC5ibG9ja3NQZXJMaW5lLGE9dC5ibG9ja3NQZXJDb2x1bW4sbj1uZXcgSW50MTZBcnJheSg2NCk7Zm9yKGxldCBlPTA7ZTxhO2UrKylmb3IobGV0IGE9MDthPHI7YSsrKXtxdWFudGl6ZUFuZEludmVyc2UodCxnZXRCbG9ja0J1ZmZlck9mZnNldCh0LGUsYSksbil9cmV0dXJuIHQuYmxvY2tEYXRhfWZ1bmN0aW9uIGZpbmROZXh0RmlsZU1hcmtlcihlLHQscj10KXtjb25zdCBhPWUubGVuZ3RoLTE7bGV0IG49cjx0P3I6dDtpZih0Pj1hKXJldHVybiBudWxsO2NvbnN0IGk9cmVhZFVpbnQxNihlLHQpO2lmKGk+PTY1NDcyJiZpPD02NTUzNClyZXR1cm57aW52YWxpZDpudWxsLG1hcmtlcjppLG9mZnNldDp0fTtsZXQgcz1yZWFkVWludDE2KGUsbik7Zm9yKDshKHM+PTY1NDcyJiZzPD02NTUzNCk7KXtpZigrK24+PWEpcmV0dXJuIG51bGw7cz1yZWFkVWludDE2KGUsbil9cmV0dXJue2ludmFsaWQ6aS50b1N0cmluZygxNiksbWFya2VyOnMsb2Zmc2V0Om59fWZ1bmN0aW9uIHByZXBhcmVDb21wb25lbnRzKGUpe2NvbnN0IHQ9TWF0aC5jZWlsKGUuc2FtcGxlc1BlckxpbmUvOC9lLm1heEgpLHI9TWF0aC5jZWlsKGUuc2NhbkxpbmVzLzgvZS5tYXhWKTtmb3IoY29uc3QgYSBvZiBlLmNvbXBvbmVudHMpe2NvbnN0IG49TWF0aC5jZWlsKE1hdGguY2VpbChlLnNhbXBsZXNQZXJMaW5lLzgpKmEuaC9lLm1heEgpLGk9TWF0aC5jZWlsKE1hdGguY2VpbChlLnNjYW5MaW5lcy84KSphLnYvZS5tYXhWKSxzPXQqYS5oLG89NjQqKHIqYS52KSoocysxKTthLmJsb2NrRGF0YT1uZXcgSW50MTZBcnJheShvKTthLmJsb2Nrc1BlckxpbmU9bjthLmJsb2Nrc1BlckNvbHVtbj1pfWUubWN1c1BlckxpbmU9dDtlLm1jdXNQZXJDb2x1bW49cn1mdW5jdGlvbiByZWFkRGF0YUJsb2NrKGUsdCl7Y29uc3Qgcj1yZWFkVWludDE2KGUsdCk7bGV0IGE9KHQrPTIpK3ItMjtjb25zdCBuPWZpbmROZXh0RmlsZU1hcmtlcihlLGEsdCk7aWYobj8uaW52YWxpZCl7d2FybigicmVhZERhdGFCbG9jayAtIGluY29ycmVjdCBsZW5ndGgsIGN1cnJlbnQgbWFya2VyIGlzOiAiK24uaW52YWxpZCk7YT1uLm9mZnNldH1jb25zdCBpPWUuc3ViYXJyYXkodCxhKTtyZXR1cm57YXBwRGF0YTppLG9sZE9mZnNldDp0LG5ld09mZnNldDp0K2kubGVuZ3RofX1mdW5jdGlvbiBza2lwRGF0YShlLHQpe2NvbnN0IHI9cmVhZFVpbnQxNihlLHQpLGE9KHQrPTIpK3ItMixuPWZpbmROZXh0RmlsZU1hcmtlcihlLGEsdCk7cmV0dXJuIG4/LmludmFsaWQ/bi5vZmZzZXQ6YX1jbGFzcyBKcGVnSW1hZ2V7Y29uc3RydWN0b3Ioe2RlY29kZVRyYW5zZm9ybTplPW51bGwsY29sb3JUcmFuc2Zvcm06dD0tMX09e30pe3RoaXMuX2RlY29kZVRyYW5zZm9ybT1lO3RoaXMuX2NvbG9yVHJhbnNmb3JtPXR9c3RhdGljIGNhblVzZUltYWdlRGVjb2RlcihlLHQ9LTEpe2xldCByPW51bGwsYT0wLG49bnVsbCxpPXJlYWRVaW50MTYoZSxhKTthKz0yO2lmKDY1NDk2IT09aSl0aHJvdyBuZXcgSnBlZ0Vycm9yKCJTT0kgbm90IGZvdW5kIik7aT1yZWFkVWludDE2KGUsYSk7YSs9MjtlOmZvcig7NjU0OTchPT1pOyl7c3dpdGNoKGkpe2Nhc2UgNjU1MDU6Y29uc3R7YXBwRGF0YTp0LG9sZE9mZnNldDpzLG5ld09mZnNldDpvfT1yZWFkRGF0YUJsb2NrKGUsYSk7YT1vO2lmKDY5PT09dFswXSYmMTIwPT09dFsxXSYmMTA1PT09dFsyXSYmMTAyPT09dFszXSYmMD09PXRbNF0mJjA9PT10WzVdKXtpZihyKXRocm93IG5ldyBKcGVnRXJyb3IoIkR1cGxpY2F0ZSBFWElGLWJsb2NrcyBmb3VuZC4iKTtyPXtleGlmU3RhcnQ6cys2LGV4aWZFbmQ6b319aT1yZWFkVWludDE2KGUsYSk7YSs9Mjtjb250aW51ZTtjYXNlIDY1NDcyOmNhc2UgNjU0NzM6Y2FzZSA2NTQ3NDpuPWVbYSs3XTticmVhayBlO2Nhc2UgNjU1MzU6MjU1IT09ZVthXSYmYS0tfWE9c2tpcERhdGEoZSxhKTtpPXJlYWRVaW50MTYoZSxhKTthKz0yfXJldHVybiA0PT09bnx8Mz09PW4mJjA9PT10P251bGw6cnx8e319cGFyc2UoZSx7ZG5sU2NhbkxpbmVzOnQ9bnVsbH09e30pe2xldCByLGEsbj0wLGk9bnVsbCxzPW51bGwsbz0wO2NvbnN0IGM9W10sbD1bXSxoPVtdO2xldCB1PXJlYWRVaW50MTYoZSxuKTtuKz0yO2lmKDY1NDk2IT09dSl0aHJvdyBuZXcgSnBlZ0Vycm9yKCJTT0kgbm90IGZvdW5kIik7dT1yZWFkVWludDE2KGUsbik7bis9MjtlOmZvcig7NjU0OTchPT11Oyl7bGV0IGQsZixnO3N3aXRjaCh1KXtjYXNlIDY1NTA0OmNhc2UgNjU1MDU6Y2FzZSA2NTUwNjpjYXNlIDY1NTA3OmNhc2UgNjU1MDg6Y2FzZSA2NTUwOTpjYXNlIDY1NTEwOmNhc2UgNjU1MTE6Y2FzZSA2NTUxMjpjYXNlIDY1NTEzOmNhc2UgNjU1MTQ6Y2FzZSA2NTUxNTpjYXNlIDY1NTE2OmNhc2UgNjU1MTc6Y2FzZSA2NTUxODpjYXNlIDY1NTE5OmNhc2UgNjU1MzQ6Y29uc3R7YXBwRGF0YTpwLG5ld09mZnNldDptfT1yZWFkRGF0YUJsb2NrKGUsbik7bj1tOzY1NTA0PT09dSYmNzQ9PT1wWzBdJiY3MD09PXBbMV0mJjczPT09cFsyXSYmNzA9PT1wWzNdJiYwPT09cFs0XSYmKGk9e3ZlcnNpb246e21ham9yOnBbNV0sbWlub3I6cFs2XX0sZGVuc2l0eVVuaXRzOnBbN10seERlbnNpdHk6cFs4XTw8OHxwWzldLHlEZW5zaXR5OnBbMTBdPDw4fHBbMTFdLHRodW1iV2lkdGg6cFsxMl0sdGh1bWJIZWlnaHQ6cFsxM10sdGh1bWJEYXRhOnAuc3ViYXJyYXkoMTQsMTQrMypwWzEyXSpwWzEzXSl9KTs2NTUxOD09PXUmJjY1PT09cFswXSYmMTAwPT09cFsxXSYmMTExPT09cFsyXSYmOTg9PT1wWzNdJiYxMDE9PT1wWzRdJiYocz17dmVyc2lvbjpwWzVdPDw4fHBbNl0sZmxhZ3MwOnBbN108PDh8cFs4XSxmbGFnczE6cFs5XTw8OHxwWzEwXSx0cmFuc2Zvcm1Db2RlOnBbMTFdfSk7YnJlYWs7Y2FzZSA2NTQ5OTpjb25zdCBiPXJlYWRVaW50MTYoZSxuKTtuKz0yO2NvbnN0IHk9YituLTI7bGV0IHc7Zm9yKDtuPHk7KXtjb25zdCB0PWVbbisrXSxyPW5ldyBVaW50MTZBcnJheSg2NCk7aWYodD4+NCl7aWYodD4+NCE9MSl0aHJvdyBuZXcgSnBlZ0Vycm9yKCJEUVQgLSBpbnZhbGlkIHRhYmxlIHNwZWMiKTtmb3IoZj0wO2Y8NjQ7ZisrKXt3PXZyW2ZdO3Jbd109cmVhZFVpbnQxNihlLG4pO24rPTJ9fWVsc2UgZm9yKGY9MDtmPDY0O2YrKyl7dz12cltmXTtyW3ddPWVbbisrXX1jWzE1JnRdPXJ9YnJlYWs7Y2FzZSA2NTQ3MjpjYXNlIDY1NDczOmNhc2UgNjU0NzQ6aWYocil0aHJvdyBuZXcgSnBlZ0Vycm9yKCJPbmx5IHNpbmdsZSBmcmFtZSBKUEVHcyBzdXBwb3J0ZWQiKTtuKz0yO3I9e307ci5leHRlbmRlZD02NTQ3Mz09PXU7ci5wcm9ncmVzc2l2ZT02NTQ3ND09PXU7ci5wcmVjaXNpb249ZVtuKytdO2NvbnN0IHg9cmVhZFVpbnQxNihlLG4pO24rPTI7ci5zY2FuTGluZXM9dHx8eDtyLnNhbXBsZXNQZXJMaW5lPXJlYWRVaW50MTYoZSxuKTtuKz0yO3IuY29tcG9uZW50cz1bXTtyLmNvbXBvbmVudElkcz17fTtjb25zdCBTPWVbbisrXTtsZXQgaz0wLEM9MDtmb3IoZD0wO2Q8UztkKyspe2NvbnN0IHQ9ZVtuXSxhPWVbbisxXT4+NCxpPTE1JmVbbisxXTtrPGEmJihrPWEpO0M8aSYmKEM9aSk7Y29uc3Qgcz1lW24rMl07Zz1yLmNvbXBvbmVudHMucHVzaCh7aDphLHY6aSxxdWFudGl6YXRpb25JZDpzLHF1YW50aXphdGlvblRhYmxlOm51bGx9KTtyLmNvbXBvbmVudElkc1t0XT1nLTE7bis9M31yLm1heEg9aztyLm1heFY9QztwcmVwYXJlQ29tcG9uZW50cyhyKTticmVhaztjYXNlIDY1NDc2OmNvbnN0IHY9cmVhZFVpbnQxNihlLG4pO24rPTI7Zm9yKGQ9MjtkPHY7KXtjb25zdCB0PWVbbisrXSxyPW5ldyBVaW50OEFycmF5KDE2KTtsZXQgYT0wO2ZvcihmPTA7ZjwxNjtmKyssbisrKWErPXJbZl09ZVtuXTtjb25zdCBpPW5ldyBVaW50OEFycmF5KGEpO2ZvcihmPTA7ZjxhO2YrKyxuKyspaVtmXT1lW25dO2QrPTE3K2E7KHQ+PjQ/bDpoKVsxNSZ0XT1idWlsZEh1ZmZtYW5UYWJsZShyLGkpfWJyZWFrO2Nhc2UgNjU1MDE6bis9MjthPXJlYWRVaW50MTYoZSxuKTtuKz0yO2JyZWFrO2Nhc2UgNjU0OTg6Y29uc3QgVD0xPT09KytvJiYhdDtuKz0yO2NvbnN0IE89ZVtuKytdLE09W107Zm9yKGQ9MDtkPE87ZCsrKXtjb25zdCB0PWVbbisrXSxhPXIuY29tcG9uZW50SWRzW3RdLGk9ci5jb21wb25lbnRzW2FdO2kuaW5kZXg9dDtjb25zdCBzPWVbbisrXTtpLmh1ZmZtYW5UYWJsZURDPWhbcz4+NF07aS5odWZmbWFuVGFibGVBQz1sWzE1JnNdO00ucHVzaChpKX1jb25zdCBEPWVbbisrXSxSPWVbbisrXSxFPWVbbisrXTt0cnl7bis9ZGVjb2RlU2NhbihlLG4scixNLGEsRCxSLEU+PjQsMTUmRSxUKX1jYXRjaCh0KXtpZih0IGluc3RhbmNlb2YgRE5MTWFya2VyRXJyb3Ipe3dhcm4oYCR7dC5tZXNzYWdlfSAtLSBhdHRlbXB0aW5nIHRvIHJlLXBhcnNlIHRoZSBKUEVHIGltYWdlLmApO3JldHVybiB0aGlzLnBhcnNlKGUse2RubFNjYW5MaW5lczp0LnNjYW5MaW5lc30pfWlmKHQgaW5zdGFuY2VvZiBFT0lNYXJrZXJFcnJvcil7d2FybihgJHt0Lm1lc3NhZ2V9IC0tIGlnbm9yaW5nIHRoZSByZXN0IG9mIHRoZSBpbWFnZSBkYXRhLmApO2JyZWFrIGV9dGhyb3cgdH1icmVhaztjYXNlIDY1NTAwOm4rPTQ7YnJlYWs7Y2FzZSA2NTUzNToyNTUhPT1lW25dJiZuLS07YnJlYWs7ZGVmYXVsdDpjb25zdCBOPWZpbmROZXh0RmlsZU1hcmtlcihlLG4tMixuLTMpO2lmKE4/LmludmFsaWQpe3dhcm4oIkpwZWdJbWFnZS5wYXJzZSAtIHVuZXhwZWN0ZWQgZGF0YSwgY3VycmVudCBtYXJrZXIgaXM6ICIrTi5pbnZhbGlkKTtuPU4ub2Zmc2V0O2JyZWFrfWlmKCFOfHxuPj1lLmxlbmd0aC0xKXt3YXJuKCJKcGVnSW1hZ2UucGFyc2UgLSByZWFjaGVkIHRoZSBlbmQgb2YgdGhlIGltYWdlIGRhdGEgd2l0aG91dCBmaW5kaW5nIGFuIEVPSSBtYXJrZXIgKDB4RkZEOSkuIik7YnJlYWsgZX10aHJvdyBuZXcgSnBlZ0Vycm9yKCJKcGVnSW1hZ2UucGFyc2UgLSB1bmtub3duIG1hcmtlcjogIit1LnRvU3RyaW5nKDE2KSl9dT1yZWFkVWludDE2KGUsbik7bis9Mn1pZighcil0aHJvdyBuZXcgSnBlZ0Vycm9yKCJKcGVnSW1hZ2UucGFyc2UgLSBubyBmcmFtZSBkYXRhIGZvdW5kLiIpO3RoaXMud2lkdGg9ci5zYW1wbGVzUGVyTGluZTt0aGlzLmhlaWdodD1yLnNjYW5MaW5lczt0aGlzLmpmaWY9aTt0aGlzLmFkb2JlPXM7dGhpcy5jb21wb25lbnRzPVtdO2Zvcihjb25zdCBlIG9mIHIuY29tcG9uZW50cyl7Y29uc3QgdD1jW2UucXVhbnRpemF0aW9uSWRdO3QmJihlLnF1YW50aXphdGlvblRhYmxlPXQpO3RoaXMuY29tcG9uZW50cy5wdXNoKHtpbmRleDplLmluZGV4LG91dHB1dDpidWlsZENvbXBvbmVudERhdGEoMCxlKSxzY2FsZVg6ZS5oL3IubWF4SCxzY2FsZVk6ZS52L3IubWF4VixibG9ja3NQZXJMaW5lOmUuYmxvY2tzUGVyTGluZSxibG9ja3NQZXJDb2x1bW46ZS5ibG9ja3NQZXJDb2x1bW59KX10aGlzLm51bUNvbXBvbmVudHM9dGhpcy5jb21wb25lbnRzLmxlbmd0aH1fZ2V0TGluZWFyaXplZEJsb2NrRGF0YShlLHQscj0hMSl7Y29uc3QgYT10aGlzLndpZHRoL2Usbj10aGlzLmhlaWdodC90O2xldCBpLHMsbyxjLGwsaCx1LGQsZixnLHAsbT0wO2NvbnN0IGI9dGhpcy5jb21wb25lbnRzLmxlbmd0aCx5PWUqdCpiLHc9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHkpLHg9bmV3IFVpbnQzMkFycmF5KGUpLFM9NDI5NDk2NzI4ODtsZXQgaztmb3IodT0wO3U8Yjt1Kyspe2k9dGhpcy5jb21wb25lbnRzW3VdO3M9aS5zY2FsZVgqYTtvPWkuc2NhbGVZKm47bT11O3A9aS5vdXRwdXQ7Yz1pLmJsb2Nrc1BlckxpbmUrMTw8MztpZihzIT09ayl7Zm9yKGw9MDtsPGU7bCsrKXtkPTB8bCpzO3hbbF09KGQmUyk8PDN8NyZkfWs9c31mb3IoaD0wO2g8dDtoKyspe2Q9MHxoKm87Zz1jKihkJlMpfCg3JmQpPDwzO2ZvcihsPTA7bDxlO2wrKyl7d1ttXT1wW2creFtsXV07bSs9Yn19fWxldCBDPXRoaXMuX2RlY29kZVRyYW5zZm9ybTtyfHw0IT09Ynx8Q3x8KEM9bmV3IEludDMyQXJyYXkoWy0yNTYsMjU1LC0yNTYsMjU1LC0yNTYsMjU1LC0yNTYsMjU1XSkpO2lmKEMpZm9yKHU9MDt1PHk7KWZvcihkPTAsZj0wO2Q8YjtkKyssdSsrLGYrPTIpd1t1XT0od1t1XSpDW2ZdPj44KStDW2YrMV07cmV0dXJuIHd9Z2V0IF9pc0NvbG9yQ29udmVyc2lvbk5lZWRlZCgpe3JldHVybiB0aGlzLmFkb2JlPyEhdGhpcy5hZG9iZS50cmFuc2Zvcm1Db2RlOjM9PT10aGlzLm51bUNvbXBvbmVudHM/MCE9PXRoaXMuX2NvbG9yVHJhbnNmb3JtJiYoODIhPT10aGlzLmNvbXBvbmVudHNbMF0uaW5kZXh8fDcxIT09dGhpcy5jb21wb25lbnRzWzFdLmluZGV4fHw2NiE9PXRoaXMuY29tcG9uZW50c1syXS5pbmRleCk6MT09PXRoaXMuX2NvbG9yVHJhbnNmb3JtfV9jb252ZXJ0WWNjVG9SZ2IoZSl7bGV0IHQscixhO2ZvcihsZXQgbj0wLGk9ZS5sZW5ndGg7bjxpO24rPTMpe3Q9ZVtuXTtyPWVbbisxXTthPWVbbisyXTtlW25dPXQtMTc5LjQ1NisxLjQwMiphO2VbbisxXT10KzEzNS40NTktLjM0NCpyLS43MTQqYTtlW24rMl09dC0yMjYuODE2KzEuNzcyKnJ9cmV0dXJuIGV9X2NvbnZlcnRZY2NUb1JnYmEoZSx0KXtmb3IobGV0IHI9MCxhPTAsbj1lLmxlbmd0aDtyPG47cis9MyxhKz00KXtjb25zdCBuPWVbcl0saT1lW3IrMV0scz1lW3IrMl07dFthXT1uLTE3OS40NTYrMS40MDIqczt0W2ErMV09bisxMzUuNDU5LS4zNDQqaS0uNzE0KnM7dFthKzJdPW4tMjI2LjgxNisxLjc3MippO3RbYSszXT0yNTV9cmV0dXJuIHR9X2NvbnZlcnRZY2NrVG9SZ2IoZSl7dGhpcy5fY29udmVydFljY2tUb0NteWsoZSk7cmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2IoZSl9X2NvbnZlcnRZY2NrVG9SZ2JhKGUpe3RoaXMuX2NvbnZlcnRZY2NrVG9DbXlrKGUpO3JldHVybiB0aGlzLl9jb252ZXJ0Q215a1RvUmdiYShlKX1fY29udmVydFljY2tUb0NteWsoZSl7bGV0IHQscixhO2ZvcihsZXQgbj0wLGk9ZS5sZW5ndGg7bjxpO24rPTQpe3Q9ZVtuXTtyPWVbbisxXTthPWVbbisyXTtlW25dPTQzNC40NTYtdC0xLjQwMiphO2VbbisxXT0xMTkuNTQxLXQrLjM0NCpyKy43MTQqYTtlW24rMl09NDgxLjgxNi10LTEuNzcyKnJ9cmV0dXJuIGV9X2NvbnZlcnRDbXlrVG9SZ2IoZSl7Y29uc3QgdD1lLmxlbmd0aC80O0NvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkJ1ZmZlcihlLDAsdCxlLDAsOCwwKTtyZXR1cm4gZS5zdWJhcnJheSgwLDMqdCl9X2NvbnZlcnRDbXlrVG9SZ2JhKGUpe0NvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkJ1ZmZlcihlLDAsZS5sZW5ndGgvNCxlLDAsOCwxKTtpZihDb2xvclNwYWNlVXRpbHMuY215ayBpbnN0YW5jZW9mIERldmljZUNteWtDUylmb3IobGV0IHQ9MyxyPWUubGVuZ3RoO3Q8cjt0Kz00KWVbdF09MjU1O3JldHVybiBlfWdldERhdGEoe3dpZHRoOmUsaGVpZ2h0OnQsZm9yY2VSR0JBOnI9ITEsZm9yY2VSR0I6YT0hMSxpc1NvdXJjZVBERjpuPSExfSl7aWYodGhpcy5udW1Db21wb25lbnRzPjQpdGhyb3cgbmV3IEpwZWdFcnJvcigiVW5zdXBwb3J0ZWQgY29sb3IgbW9kZSIpO2NvbnN0IGk9dGhpcy5fZ2V0TGluZWFyaXplZEJsb2NrRGF0YShlLHQsbik7aWYoMT09PXRoaXMubnVtQ29tcG9uZW50cyYmKHJ8fGEpKXtjb25zdCBlPWkubGVuZ3RoKihyPzQ6MyksdD1uZXcgVWludDhDbGFtcGVkQXJyYXkoZSk7bGV0IGE9MDtpZihyKSFmdW5jdGlvbiBncmF5VG9SR0JBKGUsdCl7aWYoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4pZm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKXRbcl09NjU3OTMqZVtyXXw0Mjc4MTkwMDgwO2Vsc2UgZm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKXRbcl09MTY4NDMwMDgqZVtyXXwyNTV9KGksbmV3IFVpbnQzMkFycmF5KHQuYnVmZmVyKSk7ZWxzZSBmb3IoY29uc3QgZSBvZiBpKXt0W2ErK109ZTt0W2ErK109ZTt0W2ErK109ZX1yZXR1cm4gdH1pZigzPT09dGhpcy5udW1Db21wb25lbnRzJiZ0aGlzLl9pc0NvbG9yQ29udmVyc2lvbk5lZWRlZCl7aWYocil7Y29uc3QgZT1uZXcgVWludDhDbGFtcGVkQXJyYXkoaS5sZW5ndGgvMyo0KTtyZXR1cm4gdGhpcy5fY29udmVydFljY1RvUmdiYShpLGUpfXJldHVybiB0aGlzLl9jb252ZXJ0WWNjVG9SZ2IoaSl9aWYoND09PXRoaXMubnVtQ29tcG9uZW50cyl7aWYodGhpcy5faXNDb2xvckNvbnZlcnNpb25OZWVkZWQpcmV0dXJuIHI/dGhpcy5fY29udmVydFljY2tUb1JnYmEoaSk6YT90aGlzLl9jb252ZXJ0WWNja1RvUmdiKGkpOnRoaXMuX2NvbnZlcnRZY2NrVG9DbXlrKGkpO2lmKHIpcmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2JhKGkpO2lmKGEpcmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2IoaSl9cmV0dXJuIGl9fWNsYXNzIEpwZWdTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17c3RhdGljI009RmVhdHVyZVRlc3QuaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKHQpO3RoaXMuc3RyZWFtPWU7dGhpcy5kaWN0PWUuZGljdDt0aGlzLm1heWJlTGVuZ3RoPXQ7dGhpcy5wYXJhbXM9cn1zdGF0aWMgZ2V0IGNhblVzZUltYWdlRGVjb2Rlcigpe3JldHVybiBzaGFkb3codGhpcywiY2FuVXNlSW1hZ2VEZWNvZGVyIix0aGlzLiNNP0ltYWdlRGVjb2Rlci5pc1R5cGVTdXBwb3J0ZWQoImltYWdlL2pwZWciKTpQcm9taXNlLnJlc29sdmUoITEpKX1zdGF0aWMgc2V0T3B0aW9ucyh7aXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ6ZT0hMX0pe3RoaXMuI009ZX1nZXQgYnl0ZXMoKXtyZXR1cm4gc2hhZG93KHRoaXMsImJ5dGVzIix0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSl9ZW5zdXJlQnVmZmVyKGUpe31yZWFkQmxvY2soKXt0aGlzLmRlY29kZUltYWdlKCl9Z2V0IGpwZWdPcHRpb25zKCl7Y29uc3QgZT17ZGVjb2RlVHJhbnNmb3JtOnZvaWQgMCxjb2xvclRyYW5zZm9ybTp2b2lkIDB9LHQ9dGhpcy5kaWN0LmdldEFycmF5KCJEIiwiRGVjb2RlIik7aWYoKHRoaXMuZm9yY2VSR0JBfHx0aGlzLmZvcmNlUkdCKSYmQXJyYXkuaXNBcnJheSh0KSl7Y29uc3Qgcj10aGlzLmRpY3QuZ2V0KCJCUEMiLCJCaXRzUGVyQ29tcG9uZW50Iil8fDgsYT10Lmxlbmd0aCxuPW5ldyBJbnQzMkFycmF5KGEpO2xldCBpPSExO2NvbnN0IHM9KDE8PHIpLTE7Zm9yKGxldCBlPTA7ZTxhO2UrPTIpe25bZV09MjU2Kih0W2UrMV0tdFtlXSl8MDtuW2UrMV09dFtlXSpzfDA7MjU2PT09bltlXSYmMD09PW5bZSsxXXx8KGk9ITApfWkmJihlLmRlY29kZVRyYW5zZm9ybT1uKX1pZih0aGlzLnBhcmFtcyBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IHQ9dGhpcy5wYXJhbXMuZ2V0KCJDb2xvclRyYW5zZm9ybSIpO051bWJlci5pc0ludGVnZXIodCkmJihlLmNvbG9yVHJhbnNmb3JtPXQpfXJldHVybiBzaGFkb3codGhpcywianBlZ09wdGlvbnMiLGUpfSNFKGUpe2ZvcihsZXQgdD0wLHI9ZS5sZW5ndGgtMTt0PHI7dCsrKWlmKDI1NT09PWVbdF0mJjIxNj09PWVbdCsxXSl7dD4wJiYoZT1lLnN1YmFycmF5KHQpKTticmVha31yZXR1cm4gZX1kZWNvZGVJbWFnZShlKXtpZih0aGlzLmVvZilyZXR1cm4gdGhpcy5idWZmZXI7ZT10aGlzLiNFKGV8fHRoaXMuYnl0ZXMpO2NvbnN0IHQ9bmV3IEpwZWdJbWFnZSh0aGlzLmpwZWdPcHRpb25zKTt0LnBhcnNlKGUpO2NvbnN0IHI9dC5nZXREYXRhKHt3aWR0aDp0aGlzLmRyYXdXaWR0aCxoZWlnaHQ6dGhpcy5kcmF3SGVpZ2h0LGZvcmNlUkdCQTp0aGlzLmZvcmNlUkdCQSxmb3JjZVJHQjp0aGlzLmZvcmNlUkdCLGlzU291cmNlUERGOiEwfSk7dGhpcy5idWZmZXI9cjt0aGlzLmJ1ZmZlckxlbmd0aD1yLmxlbmd0aDt0aGlzLmVvZj0hMDtyZXR1cm4gdGhpcy5idWZmZXJ9Z2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCl7cmV0dXJuIHRoaXMuc3RyZWFtLmlzQXN5bmN9YXN5bmMgZ2V0VHJhbnNmZXJhYmxlSW1hZ2UoKXtpZighYXdhaXQgSnBlZ1N0cmVhbS5jYW5Vc2VJbWFnZURlY29kZXIpcmV0dXJuIG51bGw7Y29uc3QgZT10aGlzLmpwZWdPcHRpb25zO2lmKGUuZGVjb2RlVHJhbnNmb3JtKXJldHVybiBudWxsO2xldCB0O3RyeXtjb25zdCByPXRoaXMuY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXImJmF3YWl0IHRoaXMuc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKXx8dGhpcy5ieXRlcztpZighcilyZXR1cm4gbnVsbDtsZXQgYT10aGlzLiNFKHIpO2NvbnN0IG49SnBlZ0ltYWdlLmNhblVzZUltYWdlRGVjb2RlcihhLGUuY29sb3JUcmFuc2Zvcm0pO2lmKCFuKXJldHVybiBudWxsO2lmKG4uZXhpZlN0YXJ0KXthPWEuc2xpY2UoKTthLmZpbGwoMCxuLmV4aWZTdGFydCxuLmV4aWZFbmQpfXQ9bmV3IEltYWdlRGVjb2Rlcih7ZGF0YTphLHR5cGU6ImltYWdlL2pwZWciLHByZWZlckFuaW1hdGlvbjohMX0pO3JldHVybihhd2FpdCB0LmRlY29kZSgpKS5pbWFnZX1jYXRjaChlKXt3YXJuKGBnZXRUcmFuc2ZlcmFibGVJbWFnZSAtIGZhaWxlZDogIiR7ZX0iLmApO3JldHVybiBudWxsfWZpbmFsbHl7dD8uY2xvc2UoKX19fWNvbnN0IE5yPWFzeW5jIGZ1bmN0aW9uIE9wZW5KUEVHKGU9e30pe3ZhciB0PWUscj0iLi90aGlzLnByb2dyYW0iLHF1aXRfPShlLHQpPT57dGhyb3cgdH0sYT1pbXBvcnQubWV0YS51cmw7dHJ5e25ldyBVUkwoIi4iLGEpLmhyZWZ9Y2F0Y2h7fTA7dmFyIG4saSxzLG8sYyxsLGgsdSxkPWNvbnNvbGUubG9nLmJpbmQoY29uc29sZSksZj1jb25zb2xlLmVycm9yLmJpbmQoY29uc29sZSksZz0hMSxwPSExO2Z1bmN0aW9uIHVwZGF0ZU1lbW9yeVZpZXdzKCl7dmFyIGU9by5idWZmZXI7Yz1uZXcgSW50OEFycmF5KGUpO25ldyBJbnQxNkFycmF5KGUpO2w9bmV3IFVpbnQ4QXJyYXkoZSk7bmV3IFVpbnQxNkFycmF5KGUpO2g9bmV3IEludDMyQXJyYXkoZSk7dT1uZXcgVWludDMyQXJyYXkoZSk7bmV3IEZsb2F0MzJBcnJheShlKTtuZXcgRmxvYXQ2NEFycmF5KGUpO25ldyBCaWdJbnQ2NEFycmF5KGUpO25ldyBCaWdVaW50NjRBcnJheShlKX1jbGFzcyBFeGl0U3RhdHVze25hbWU9IkV4aXRTdGF0dXMiO2NvbnN0cnVjdG9yKGUpe3RoaXMubWVzc2FnZT1gUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdCgke2V9KWA7dGhpcy5zdGF0dXM9ZX19dmFyIG0sY2FsbFJ1bnRpbWVDYWxsYmFja3M9ZT0+e2Zvcig7ZS5sZW5ndGg+MDspZS5zaGlmdCgpKHQpfSxiPVtdLGFkZE9uUG9zdFJ1bj1lPT5iLnB1c2goZSkseT1bXSxhZGRPblByZVJ1bj1lPT55LnB1c2goZSksdz0hMCx4PTAsUz17fSxoYW5kbGVFeGNlcHRpb249ZT0+e2lmKGUgaW5zdGFuY2VvZiBFeGl0U3RhdHVzfHwidW53aW5kIj09ZSlyZXR1cm4gbjtxdWl0XygwLGUpfSxrZWVwUnVudGltZUFsaXZlPSgpPT53fHx4PjAsX3Byb2NfZXhpdD1lPT57bj1lO2lmKCFrZWVwUnVudGltZUFsaXZlKCkpe3Qub25FeGl0Py4oZSk7Zz0hMH1xdWl0XygwLG5ldyBFeGl0U3RhdHVzKGUpKX0sX2V4aXQ9KGUsdCk9PntuPWU7X3Byb2NfZXhpdChlKX0sY2FsbFVzZXJDYWxsYmFjaz1lPT57aWYoIWcpdHJ5e2UoKTsoKCk9PntpZigha2VlcFJ1bnRpbWVBbGl2ZSgpKXRyeXtfZXhpdChuKX1jYXRjaChlKXtoYW5kbGVFeGNlcHRpb24oZSl9fSkoKX1jYXRjaChlKXtoYW5kbGVFeGNlcHRpb24oZSl9fSxhbGlnbk1lbW9yeT0oZSx0KT0+TWF0aC5jZWlsKGUvdCkqdCxncm93TWVtb3J5PWU9Pnt2YXIgdD0oZS1vLmJ1ZmZlci5ieXRlTGVuZ3RoKzY1NTM1KS82NTUzNnwwO3RyeXtvLmdyb3codCk7dXBkYXRlTWVtb3J5Vmlld3MoKTtyZXR1cm4gMX1jYXRjaChlKXt9fSxrPXt9LGdldEVudlN0cmluZ3M9KCk9PntpZighZ2V0RW52U3RyaW5ncy5zdHJpbmdzKXt2YXIgZT17VVNFUjoid2ViX3VzZXIiLExPR05BTUU6IndlYl91c2VyIixQQVRIOiIvIixQV0Q6Ii8iLEhPTUU6Ii9ob21lL3dlYl91c2VyIixMQU5HOigib2JqZWN0Ij09dHlwZW9mIG5hdmlnYXRvciYmbmF2aWdhdG9yLmxhbmd1YWdlfHwiQyIpLnJlcGxhY2UoIi0iLCJfIikrIi5VVEYtOCIsXzpyfHwiLi90aGlzLnByb2dyYW0ifTtmb3IodmFyIHQgaW4gayl2b2lkIDA9PT1rW3RdP2RlbGV0ZSBlW3RdOmVbdF09a1t0XTt2YXIgYT1bXTtmb3IodmFyIHQgaW4gZSlhLnB1c2goYCR7dH09JHtlW3RdfWApO2dldEVudlN0cmluZ3Muc3RyaW5ncz1hfXJldHVybiBnZXRFbnZTdHJpbmdzLnN0cmluZ3N9LHN0cmluZ1RvVVRGOD0oZSx0LHIpPT4oKGUsdCxyLGEpPT57aWYoIShhPjApKXJldHVybiAwO2Zvcih2YXIgbj1yLGk9cithLTEscz0wO3M8ZS5sZW5ndGg7KytzKXt2YXIgbz1lLmNvZGVQb2ludEF0KHMpO2lmKG88PTEyNyl7aWYocj49aSlicmVhazt0W3IrK109b31lbHNlIGlmKG88PTIwNDcpe2lmKHIrMT49aSlicmVhazt0W3IrK109MTkyfG8+PjY7dFtyKytdPTEyOHw2MyZvfWVsc2UgaWYobzw9NjU1MzUpe2lmKHIrMj49aSlicmVhazt0W3IrK109MjI0fG8+PjEyO3RbcisrXT0xMjh8bz4+NiY2Mzt0W3IrK109MTI4fDYzJm99ZWxzZXtpZihyKzM+PWkpYnJlYWs7dFtyKytdPTI0MHxvPj4xODt0W3IrK109MTI4fG8+PjEyJjYzO3RbcisrXT0xMjh8bz4+NiY2Mzt0W3IrK109MTI4fDYzJm87cysrfX10W3JdPTA7cmV0dXJuIHItbn0pKGUsbCx0LHIpLGxlbmd0aEJ5dGVzVVRGOD1lPT57Zm9yKHZhciB0PTAscj0wO3I8ZS5sZW5ndGg7KytyKXt2YXIgYT1lLmNoYXJDb2RlQXQocik7aWYoYTw9MTI3KXQrKztlbHNlIGlmKGE8PTIwNDcpdCs9MjtlbHNlIGlmKGE+PTU1Mjk2JiZhPD01NzM0Myl7dCs9NDsrK3J9ZWxzZSB0Kz0zfXJldHVybiB0fSxDPVtudWxsLFtdLFtdXSx2PSJ1bmRlZmluZWQiIT10eXBlb2YgVGV4dERlY29kZXI/bmV3IFRleHREZWNvZGVyOnZvaWQgMCxVVEY4QXJyYXlUb1N0cmluZz0oZSx0PTAscixhKT0+e3ZhciBuPSgoZSx0LHIsYSk9Pnt2YXIgbj10K3I7aWYoYSlyZXR1cm4gbjtmb3IoO2VbdF0mJiEodD49bik7KSsrdDtyZXR1cm4gdH0pKGUsdCxyLGEpO2lmKG4tdD4xNiYmZS5idWZmZXImJnYpcmV0dXJuIHYuZGVjb2RlKGUuc3ViYXJyYXkodCxuKSk7Zm9yKHZhciBpPSIiO3Q8bjspe3ZhciBzPWVbdCsrXTtpZigxMjgmcyl7dmFyIG89NjMmZVt0KytdO2lmKDE5MiE9KDIyNCZzKSl7dmFyIGM9NjMmZVt0KytdO2lmKChzPTIyND09KDI0MCZzKT8oMTUmcyk8PDEyfG88PDZ8YzooNyZzKTw8MTh8bzw8MTJ8Yzw8Nnw2MyZlW3QrK10pPDY1NTM2KWkrPVN0cmluZy5mcm9tQ2hhckNvZGUocyk7ZWxzZXt2YXIgbD1zLTY1NTM2O2krPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8bD4+MTAsNTYzMjB8MTAyMyZsKX19ZWxzZSBpKz1TdHJpbmcuZnJvbUNoYXJDb2RlKCgzMSZzKTw8NnxvKX1lbHNlIGkrPVN0cmluZy5mcm9tQ2hhckNvZGUocyl9cmV0dXJuIGl9LHByaW50Q2hhcj0oZSx0KT0+e3ZhciByPUNbZV07aWYoMD09PXR8fDEwPT09dCl7KDE9PT1lP2Q6ZikoVVRGOEFycmF5VG9TdHJpbmcocikpO3IubGVuZ3RoPTB9ZWxzZSByLnB1c2godCl9LFVURjhUb1N0cmluZz0oZSx0LHIpPT5lP1VURjhBcnJheVRvU3RyaW5nKGwsZSx0LHIpOiIiO3Qubm9FeGl0UnVudGltZSYmKHc9dC5ub0V4aXRSdW50aW1lKTt0LnByaW50JiYoZD10LnByaW50KTt0LnByaW50RXJyJiYoZj10LnByaW50RXJyKTt0Lndhc21CaW5hcnkmJnQud2FzbUJpbmFyeTt0LmFyZ3VtZW50cyYmdC5hcmd1bWVudHM7dC50aGlzUHJvZ3JhbSYmKHI9dC50aGlzUHJvZ3JhbSk7aWYodC5wcmVJbml0KXsiZnVuY3Rpb24iPT10eXBlb2YgdC5wcmVJbml0JiYodC5wcmVJbml0PVt0LnByZUluaXRdKTtmb3IoO3QucHJlSW5pdC5sZW5ndGg+MDspdC5wcmVJbml0LnNoaWZ0KCkoKX10LndyaXRlQXJyYXlUb01lbW9yeT0oZSx0KT0+e2Muc2V0KGUsdCl9O3ZhciBULE89e2s6KCk9PmZ1bmN0aW9uIGFib3J0KGUpe3Qub25BYm9ydD8uKGUpO2YoZT0iQWJvcnRlZCgiK2UrIikiKTtnPSEwO2UrPSIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uIjt2YXIgcj1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKGUpO3M/LihyKTt0aHJvdyByfSgiIiksajooKT0+e3c9ITE7eD0wfSxsOihlLHQpPT57aWYoU1tlXSl7Y2xlYXJUaW1lb3V0KFNbZV0uaWQpO2RlbGV0ZSBTW2VdfWlmKCF0KXJldHVybiAwO3ZhciByPXNldFRpbWVvdXQoKCk9PntkZWxldGUgU1tlXTtjYWxsVXNlckNhbGxiYWNrKCgpPT5tKGUscGVyZm9ybWFuY2Uubm93KCkpKX0sdCk7U1tlXT17aWQ6cix0aW1lb3V0X21zOnR9O3JldHVybiAwfSxmOmZ1bmN0aW9uIF9jb3B5X3BpeGVsc18xKGUscil7ZT4+PTI7Y29uc3QgYT10LmltYWdlRGF0YT1uZXcgVWludDhDbGFtcGVkQXJyYXkociksbj1oLnN1YmFycmF5KGUsZStyKTthLnNldChuKX0sZTpmdW5jdGlvbiBfY29weV9waXhlbHNfMyhlLHIsYSxuKXtlPj49MjtyPj49MjthPj49Mjtjb25zdCBpPXQuaW1hZ2VEYXRhPW5ldyBVaW50OENsYW1wZWRBcnJheSgzKm4pLHM9aC5zdWJhcnJheShlLGUrbiksbz1oLnN1YmFycmF5KHIscituKSxjPWguc3ViYXJyYXkoYSxhK24pO2ZvcihsZXQgZT0wO2U8bjtlKyspe2lbMyplXT1zW2VdO2lbMyplKzFdPW9bZV07aVszKmUrMl09Y1tlXX19LGQ6ZnVuY3Rpb24gX2NvcHlfcGl4ZWxzXzQoZSxyLGEsbixpKXtlPj49MjtyPj49MjthPj49MjtuPj49Mjtjb25zdCBzPXQuaW1hZ2VEYXRhPW5ldyBVaW50OENsYW1wZWRBcnJheSg0KmkpLG89aC5zdWJhcnJheShlLGUraSksYz1oLnN1YmFycmF5KHIscitpKSxsPWguc3ViYXJyYXkoYSxhK2kpLHU9aC5zdWJhcnJheShuLG4raSk7Zm9yKGxldCBlPTA7ZTxpO2UrKyl7c1s0KmVdPW9bZV07c1s0KmUrMV09Y1tlXTtzWzQqZSsyXT1sW2VdO3NbNCplKzNdPXVbZV19fSxtOmU9Pnt2YXIgdD1sLmxlbmd0aCxyPTIxNDc0ODM2NDg7aWYoKGU+Pj49MCk+cilyZXR1cm4hMTtmb3IodmFyIGE9MTthPD00O2EqPTIpe3ZhciBuPXQqKDErLjIvYSk7bj1NYXRoLm1pbihuLGUrMTAwNjYzMjk2KTt2YXIgaT1NYXRoLm1pbihyLGFsaWduTWVtb3J5KE1hdGgubWF4KGUsbiksNjU1MzYpKTtpZihncm93TWVtb3J5KGkpKXJldHVybiEwfXJldHVybiExfSxvOihlLHQpPT57dmFyIHI9MCxhPTA7Zm9yKHZhciBuIG9mIGdldEVudlN0cmluZ3MoKSl7dmFyIGk9dCtyO3VbZSthPj4yXT1pO3IrPXN0cmluZ1RvVVRGOChuLGksMS8wKSsxO2ErPTR9cmV0dXJuIDB9LHA6KGUsdCk9Pnt2YXIgcj1nZXRFbnZTdHJpbmdzKCk7dVtlPj4yXT1yLmxlbmd0aDt2YXIgYT0wO2Zvcih2YXIgbiBvZiByKWErPWxlbmd0aEJ5dGVzVVRGOChuKSsxO3VbdD4+Ml09YTtyZXR1cm4gMH0sbjpmdW5jdGlvbiBfZmRfc2VlayhlLHQscixhKXt0PShuPXQpPC05MDA3MTk5MjU0NzQwOTkyfHxuPjkwMDcxOTkyNTQ3NDA5OTI/TmFOOk51bWJlcihuKTt2YXIgbjtyZXR1cm4gNzB9LGI6KGUsdCxyLGEpPT57Zm9yKHZhciBuPTAsaT0wO2k8cjtpKyspe3ZhciBzPXVbdD4+Ml0sbz11W3QrND4+Ml07dCs9ODtmb3IodmFyIGM9MDtjPG87YysrKXByaW50Q2hhcihlLGxbcytjXSk7bis9b311W2E+PjJdPW47cmV0dXJuIDB9LHE6ZnVuY3Rpb24gX2dyYXlfdG9fcmdiYShlLHIpe2U+Pj0yO2NvbnN0IGE9dC5pbWFnZURhdGE9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDQqciksbj1oLnN1YmFycmF5KGUsZStyKTtmb3IobGV0IGU9MDtlPHI7ZSsrKXthWzQqZV09YVs0KmUrMV09YVs0KmUrMl09bltlXTthWzQqZSszXT0yNTV9fSxoOmZ1bmN0aW9uIF9ncmF5YV90b19yZ2JhKGUscixhKXtlPj49MjtyPj49Mjtjb25zdCBuPXQuaW1hZ2VEYXRhPW5ldyBVaW50OENsYW1wZWRBcnJheSg0KmEpLGk9aC5zdWJhcnJheShlLGUrYSkscz1oLnN1YmFycmF5KHIscithKTtmb3IobGV0IGU9MDtlPGE7ZSsrKXtuWzQqZV09bls0KmUrMV09bls0KmUrMl09aVtlXTtuWzQqZSszXT1zW2VdfX0sYzpmdW5jdGlvbiBfanNQcmludFdhcm5pbmcoZSl7Y29uc3Qgcj1VVEY4VG9TdHJpbmcoZSk7KHQud2Fybnx8Y29uc29sZS53YXJuKShgT3BlbkpQRUc6ICR7cn1gKX0saTpfcHJvY19leGl0LGc6ZnVuY3Rpb24gX3JnYl90b19yZ2JhKGUscixhLG4pe2U+Pj0yO3I+Pj0yO2E+Pj0yO2NvbnN0IGk9dC5pbWFnZURhdGE9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDQqbikscz1oLnN1YmFycmF5KGUsZStuKSxvPWguc3ViYXJyYXkocixyK24pLGM9aC5zdWJhcnJheShhLGErbik7Zm9yKGxldCBlPTA7ZTxuO2UrKyl7aVs0KmVdPXNbZV07aVs0KmUrMV09b1tlXTtpWzQqZSsyXT1jW2VdO2lbNCplKzNdPTI1NX19LGE6ZnVuY3Rpb24gX3N0b3JlRXJyb3JNZXNzYWdlKGUpe2NvbnN0IHI9VVRGOFRvU3RyaW5nKGUpO3QuZXJyb3JNZXNzYWdlcz90LmVycm9yTWVzc2FnZXMrPSJcbiIrcjp0LmVycm9yTWVzc2FnZXM9cn19O1Q9YXdhaXQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlV2FzbSgpe2Z1bmN0aW9uIHJlY2VpdmVJbnN0YW5jZShlLHIpe1Q9ZS5leHBvcnRzO289VC5yO3VwZGF0ZU1lbW9yeVZpZXdzKCk7IWZ1bmN0aW9uIGFzc2lnbldhc21FeHBvcnRzKGUpe3QuX21hbGxvYz1lLnQ7dC5fZnJlZT1lLnU7dC5fanAyX2RlY29kZT1lLnY7bT1lLnd9KFQpO3JldHVybiBUfXZhciBlPWZ1bmN0aW9uIGdldFdhc21JbXBvcnRzKCl7cmV0dXJue2E6T319KCk7cmV0dXJuIG5ldyBQcm9taXNlKChyLGEpPT57dC5pbnN0YW50aWF0ZVdhc20oZSwoZSx0KT0+e3IocmVjZWl2ZUluc3RhbmNlKGUpKX0pfSl9KCk7IWZ1bmN0aW9uIHJ1bigpeyFmdW5jdGlvbiBwcmVSdW4oKXtpZih0LnByZVJ1bil7ImZ1bmN0aW9uIj09dHlwZW9mIHQucHJlUnVuJiYodC5wcmVSdW49W3QucHJlUnVuXSk7Zm9yKDt0LnByZVJ1bi5sZW5ndGg7KWFkZE9uUHJlUnVuKHQucHJlUnVuLnNoaWZ0KCkpfWNhbGxSdW50aW1lQ2FsbGJhY2tzKHkpfSgpO2Z1bmN0aW9uIGRvUnVuKCl7dC5jYWxsZWRSdW49ITA7aWYoIWcpeyFmdW5jdGlvbiBpbml0UnVudGltZSgpe3A9ITA7VC5zKCl9KCk7aT8uKHQpO3Qub25SdW50aW1lSW5pdGlhbGl6ZWQ/LigpOyFmdW5jdGlvbiBwb3N0UnVuKCl7aWYodC5wb3N0UnVuKXsiZnVuY3Rpb24iPT10eXBlb2YgdC5wb3N0UnVuJiYodC5wb3N0UnVuPVt0LnBvc3RSdW5dKTtmb3IoO3QucG9zdFJ1bi5sZW5ndGg7KWFkZE9uUG9zdFJ1bih0LnBvc3RSdW4uc2hpZnQoKSl9Y2FsbFJ1bnRpbWVDYWxsYmFja3MoYil9KCl9fWlmKHQuc2V0U3RhdHVzKXt0LnNldFN0YXR1cygiUnVubmluZy4uLiIpO3NldFRpbWVvdXQoKCk9PntzZXRUaW1lb3V0KCgpPT50LnNldFN0YXR1cygiIiksMSk7ZG9SdW4oKX0sMSl9ZWxzZSBkb1J1bigpfSgpO3JldHVybiBwP3Q6bmV3IFByb21pc2UoKGUsdCk9PntpPWU7cz10fSl9O2NsYXNzIEpweEVycm9yIGV4dGVuZHMgZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiSnB4RXJyb3IiKX19Y2xhc3MgSnB4SW1hZ2V7c3RhdGljI049bnVsbDtzdGF0aWMjUD1udWxsO3N0YXRpYyNfPW51bGw7c3RhdGljI3Y9ITA7c3RhdGljI0w9ITA7c3RhdGljI0Y9bnVsbDtzdGF0aWMgc2V0T3B0aW9ucyh7aGFuZGxlcjplLHVzZVdhc206dCx1c2VXb3JrZXJGZXRjaDpyLHdhc21Vcmw6YX0pe3RoaXMuI3Y9dDt0aGlzLiNMPXI7dGhpcy4jRj1hO3J8fCh0aGlzLiNQPWUpfXN0YXRpYyBhc3luYyNqKGUpe2NvbnN0IHQ9YCR7dGhpcy4jRn1vcGVuanBlZ19ub3dhc21fZmFsbGJhY2suanNgO2xldCByPW51bGw7dHJ5e3I9KGF3YWl0IGltcG9ydCgKLyp3ZWJwYWNrSWdub3JlOiB0cnVlKi8KLypAdml0ZS1pZ25vcmUqLwp0KSkuZGVmYXVsdCgpfWNhdGNoKGUpe3dhcm4oYEpweEltYWdlI2dldEpzTW9kdWxlOiAke2V9YCl9ZShyKX1zdGF0aWMgYXN5bmMjVShlLHQscil7Y29uc3QgYT0ib3BlbmpwZWcud2FzbSI7dHJ5e3RoaXMuI058fCh0aGlzLiNMP3RoaXMuI049YXdhaXQgZmV0Y2hCaW5hcnlEYXRhKGAke3RoaXMuI0Z9JHthfWApOnRoaXMuI049YXdhaXQgdGhpcy4jUC5zZW5kV2l0aFByb21pc2UoIkZldGNoQmluYXJ5RGF0YSIse3R5cGU6Indhc21GYWN0b3J5IixmaWxlbmFtZTphfSkpO3JldHVybiByKChhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZSh0aGlzLiNOLHQpKS5pbnN0YW5jZSl9Y2F0Y2godCl7d2FybihgSnB4SW1hZ2UjaW5zdGFudGlhdGVXYXNtOiAke3R9YCk7dGhpcy4jaihlKTtyZXR1cm4gbnVsbH1maW5hbGx5e3RoaXMuI1A9bnVsbH19c3RhdGljIGFzeW5jIGRlY29kZShlLHtudW1Db21wb25lbnRzOnQ9NCxpc0luZGV4ZWRDb2xvcm1hcDpyPSExLHNtYXNrSW5EYXRhOmE9ITEscmVkdWNlUG93ZXI6bj0wfT17fSl7aWYoIXRoaXMuI18pe2NvbnN0e3Byb21pc2U6ZSxyZXNvbHZlOnR9PVByb21pc2Uud2l0aFJlc29sdmVycygpLHI9W2VdO3RoaXMuI3Y/ci5wdXNoKE5yKHt3YXJuLGluc3RhbnRpYXRlV2FzbTp0aGlzLiNVLmJpbmQodGhpcyx0KX0pKTp0aGlzLiNqKHQpO3RoaXMuI189UHJvbWlzZS5yYWNlKHIpfWNvbnN0IGk9YXdhaXQgdGhpcy4jXztpZighaSl0aHJvdyBuZXcgSnB4RXJyb3IoIk9wZW5KUEVHIGZhaWxlZCB0byBpbml0aWFsaXplIik7bGV0IHM7dHJ5e2NvbnN0IG89ZS5sZW5ndGg7cz1pLl9tYWxsb2Mobyk7aS53cml0ZUFycmF5VG9NZW1vcnkoZSxzKTtpZihpLl9qcDJfZGVjb2RlKHMsbyx0PjA/dDowLCEhciwhIWEsbikpe2NvbnN0e2Vycm9yTWVzc2FnZXM6ZX09aTtpZihlKXtkZWxldGUgaS5lcnJvck1lc3NhZ2VzO3Rocm93IG5ldyBKcHhFcnJvcihlKX10aHJvdyBuZXcgSnB4RXJyb3IoIlVua25vd24gZXJyb3IiKX1jb25zdHtpbWFnZURhdGE6Y309aTtpLmltYWdlRGF0YT1udWxsO3JldHVybiBjfWZpbmFsbHl7cyYmaS5fZnJlZShzKX19c3RhdGljIGNsZWFudXAoKXt0aGlzLiNfPW51bGx9c3RhdGljIHBhcnNlSW1hZ2VQcm9wZXJ0aWVzKGUpe2xldCB0PWUuZ2V0Qnl0ZSgpO2Zvcig7dD49MDspe2NvbnN0IHI9dDt0PWUuZ2V0Qnl0ZSgpO2lmKDY1MzYxPT09KHI8PDh8dCkpe2Uuc2tpcCg0KTtjb25zdCB0PWUuZ2V0SW50MzIoKT4+PjAscj1lLmdldEludDMyKCk+Pj4wLGE9ZS5nZXRJbnQzMigpPj4+MCxuPWUuZ2V0SW50MzIoKT4+PjA7ZS5za2lwKDE2KTtyZXR1cm57d2lkdGg6dC1hLGhlaWdodDpyLW4sYml0c1BlckNvbXBvbmVudDo4LGNvbXBvbmVudHNDb3VudDplLmdldFVpbnQxNigpfX19dGhyb3cgbmV3IEpweEVycm9yKCJObyBzaXplIG1hcmtlciBmb3VuZCBpbiBKUFggc3RyZWFtIil9fWZ1bmN0aW9uIGFkZFN0YXRlKGUsdCxyLGEsbil7bGV0IGk9ZTtmb3IobGV0IGU9MCxyPXQubGVuZ3RoLTE7ZTxyO2UrKyl7Y29uc3Qgcj10W2VdO2k9aVtyXXx8PVtdfWlbdC5hdCgtMSldPXtjaGVja0ZuOnIsaXRlcmF0ZUZuOmEscHJvY2Vzc0ZuOm59fWNvbnN0IFByPVtdO2FkZFN0YXRlKFByLFt5ZSx4ZSxMdCx3ZV0sbnVsbCxmdW5jdGlvbiBpdGVyYXRlSW5saW5lSW1hZ2VHcm91cChlLHQpe2NvbnN0IHI9ZS5mbkFycmF5LGE9KHQtKGUuaUN1cnItMykpJTQ7c3dpdGNoKGEpe2Nhc2UgMDpyZXR1cm4gclt0XT09PXllO2Nhc2UgMTpyZXR1cm4gclt0XT09PXhlO2Nhc2UgMjpyZXR1cm4gclt0XT09PUx0O2Nhc2UgMzpyZXR1cm4gclt0XT09PXdlfXRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUlubGluZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHthfWApfSxmdW5jdGlvbiBmb3VuZElubGluZUltYWdlR3JvdXAoZSx0KXtjb25zdCByPWUuZm5BcnJheSxhPWUuYXJnc0FycmF5LG49ZS5pQ3VycixpPW4tMyxzPW4tMixvPW4tMSxjPU1hdGgubWluKE1hdGguZmxvb3IoKHQtaSkvNCksMjAwKTtpZihjPDEwKXJldHVybiB0LSh0LWkpJTQ7bGV0IGw9MDtjb25zdCBoPVtdO2xldCB1PTAsZD0xLGY9MTtmb3IobGV0IGU9MDtlPGM7ZSsrKXtjb25zdCB0PWFbcysoZTw8MildLHI9YVtvKyhlPDwyKV1bMF07aWYoZCtyLndpZHRoPjFlMyl7bD1NYXRoLm1heChsLGQpO2YrPXUrMjtkPTA7dT0wfWgucHVzaCh7dHJhbnNmb3JtOnQseDpkLHk6Zix3OnIud2lkdGgsaDpyLmhlaWdodH0pO2QrPXIud2lkdGgrMjt1PU1hdGgubWF4KHUsci5oZWlnaHQpfWNvbnN0IGc9TWF0aC5tYXgobCxkKSsxLHA9Zit1KzEsbT1uZXcgVWludDhBcnJheShnKnAqNCksYj1nPDwyO2ZvcihsZXQgZT0wO2U8YztlKyspe2NvbnN0IHQ9YVtvKyhlPDwyKV1bMF0uZGF0YSxyPWhbZV0udzw8MjtsZXQgbj0wLGk9aFtlXS54K2hbZV0ueSpnPDwyO20uc2V0KHQuc3ViYXJyYXkoMCxyKSxpLWIpO2ZvcihsZXQgYT0wLHM9aFtlXS5oO2E8czthKyspe20uc2V0KHQuc3ViYXJyYXkobixuK3IpLGkpO24rPXI7aSs9Yn1tLnNldCh0LnN1YmFycmF5KG4tcixuKSxpKTtmb3IoO2k+PTA7KXt0W2ktNF09dFtpXTt0W2ktM109dFtpKzFdO3RbaS0yXT10W2krMl07dFtpLTFdPXRbaSszXTt0W2krcl09dFtpK3ItNF07dFtpK3IrMV09dFtpK3ItM107dFtpK3IrMl09dFtpK3ItMl07dFtpK3IrM109dFtpK3ItMV07aS09Yn19Y29uc3QgeT17d2lkdGg6ZyxoZWlnaHQ6cH07aWYoZS5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCl7Y29uc3QgZT1uZXcgT2Zmc2NyZWVuQ2FudmFzKGcscCk7ZS5nZXRDb250ZXh0KCIyZCIpLnB1dEltYWdlRGF0YShuZXcgSW1hZ2VEYXRhKG5ldyBVaW50OENsYW1wZWRBcnJheShtLmJ1ZmZlciksZyxwKSwwLDApO3kuYml0bWFwPWUudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7eS5kYXRhPW51bGx9ZWxzZXt5LmtpbmQ9Tzt5LmRhdGE9bX1yLnNwbGljZShpLDQqYyxqdCk7YS5zcGxpY2UoaSw0KmMsW3ksaF0pO3JldHVybiBpKzF9KTthZGRTdGF0ZShQcixbeWUseGUsTnQsd2VdLG51bGwsZnVuY3Rpb24gaXRlcmF0ZUltYWdlTWFza0dyb3VwKGUsdCl7Y29uc3Qgcj1lLmZuQXJyYXksYT0odC0oZS5pQ3Vyci0zKSklNDtzd2l0Y2goYSl7Y2FzZSAwOnJldHVybiByW3RdPT09eWU7Y2FzZSAxOnJldHVybiByW3RdPT09eGU7Y2FzZSAyOnJldHVybiByW3RdPT09TnQ7Y2FzZSAzOnJldHVybiByW3RdPT09d2V9dGhyb3cgbmV3IEVycm9yKGBpdGVyYXRlSW1hZ2VNYXNrR3JvdXAgLSBpbnZhbGlkIHBvczogJHthfWApfSxmdW5jdGlvbiBmb3VuZEltYWdlTWFza0dyb3VwKGUsdCl7Y29uc3Qgcj1lLmZuQXJyYXksYT1lLmFyZ3NBcnJheSxuPWUuaUN1cnIsaT1uLTMscz1uLTIsbz1uLTE7bGV0IGM9TWF0aC5mbG9vcigodC1pKS80KTtpZihjPDEwKXJldHVybiB0LSh0LWkpJTQ7bGV0IGwsaCx1PSExO2NvbnN0IGQ9YVtvXVswXSxmPWFbc11bMF0sZz1hW3NdWzFdLHA9YVtzXVsyXSxtPWFbc11bM107aWYoZz09PXApe3U9ITA7bD1zKzQ7bGV0IGU9bys0O2ZvcihsZXQgdD0xO3Q8Yzt0KyssbCs9NCxlKz00KXtoPWFbbF07aWYoYVtlXVswXSE9PWR8fGhbMF0hPT1mfHxoWzFdIT09Z3x8aFsyXSE9PXB8fGhbM10hPT1tKXt0PDEwP3U9ITE6Yz10O2JyZWFrfX19aWYodSl7Yz1NYXRoLm1pbihjLDFlMyk7Y29uc3QgZT1uZXcgRmxvYXQzMkFycmF5KDIqYyk7bD1zO2ZvcihsZXQgdD0wO3Q8Yzt0KyssbCs9NCl7aD1hW2xdO2VbdDw8MV09aFs0XTtlWzErKHQ8PDEpXT1oWzVdfXIuc3BsaWNlKGksNCpjLHF0KTthLnNwbGljZShpLDQqYyxbZCxmLGcscCxtLGVdKX1lbHNle2M9TWF0aC5taW4oYywxMDApO2NvbnN0IGU9W107Zm9yKGxldCB0PTA7dDxjO3QrKyl7aD1hW3MrKHQ8PDIpXTtjb25zdCByPWFbbysodDw8MildWzBdO2UucHVzaCh7ZGF0YTpyLmRhdGEsd2lkdGg6ci53aWR0aCxoZWlnaHQ6ci5oZWlnaHQsaW50ZXJwb2xhdGU6ci5pbnRlcnBvbGF0ZSxjb3VudDpyLmNvdW50LHRyYW5zZm9ybTpofSl9ci5zcGxpY2UoaSw0KmMsUHQpO2Euc3BsaWNlKGksNCpjLFtlXSl9cmV0dXJuIGkrMX0pO2FkZFN0YXRlKFByLFt5ZSx4ZSxfdCx3ZV0sZnVuY3Rpb24oZSl7Y29uc3QgdD1lLmFyZ3NBcnJheSxyPWUuaUN1cnItMjtyZXR1cm4gMD09PXRbcl1bMV0mJjA9PT10W3JdWzJdfSxmdW5jdGlvbiBpdGVyYXRlSW1hZ2VHcm91cChlLHQpe2NvbnN0IHI9ZS5mbkFycmF5LGE9ZS5hcmdzQXJyYXksbj0odC0oZS5pQ3Vyci0zKSklNDtzd2l0Y2gobil7Y2FzZSAwOnJldHVybiByW3RdPT09eWU7Y2FzZSAxOmlmKHJbdF0hPT14ZSlyZXR1cm4hMTtjb25zdCBuPWUuaUN1cnItMixpPWFbbl1bMF0scz1hW25dWzNdO3JldHVybiBhW3RdWzBdPT09aSYmMD09PWFbdF1bMV0mJjA9PT1hW3RdWzJdJiZhW3RdWzNdPT09cztjYXNlIDI6aWYoclt0XSE9PV90KXJldHVybiExO2NvbnN0IG89YVtlLmlDdXJyLTFdWzBdO3JldHVybiBhW3RdWzBdPT09bztjYXNlIDM6cmV0dXJuIHJbdF09PT13ZX10aHJvdyBuZXcgRXJyb3IoYGl0ZXJhdGVJbWFnZUdyb3VwIC0gaW52YWxpZCBwb3M6ICR7bn1gKX0sZnVuY3Rpb24oZSx0KXtjb25zdCByPWUuZm5BcnJheSxhPWUuYXJnc0FycmF5LG49ZS5pQ3VycixpPW4tMyxzPW4tMixvPWFbbi0xXVswXSxjPWFbc11bMF0sbD1hW3NdWzNdLGg9TWF0aC5taW4oTWF0aC5mbG9vcigodC1pKS80KSwxZTMpO2lmKGg8MylyZXR1cm4gdC0odC1pKSU0O2NvbnN0IHU9bmV3IEZsb2F0MzJBcnJheSgyKmgpO2xldCBkPXM7Zm9yKGxldCBlPTA7ZTxoO2UrKyxkKz00KXtjb25zdCB0PWFbZF07dVtlPDwxXT10WzRdO3VbMSsoZTw8MSldPXRbNV19Y29uc3QgZj1bbyxjLGwsdV07ci5zcGxpY2UoaSw0KmgsVXQpO2Euc3BsaWNlKGksNCpoLGYpO3JldHVybiBpKzF9KTthZGRTdGF0ZShQcixbamUsemUsSmUsWmUsVWVdLG51bGwsZnVuY3Rpb24gaXRlcmF0ZVNob3dUZXh0R3JvdXAoZSx0KXtjb25zdCByPWUuZm5BcnJheSxhPWUuYXJnc0FycmF5LG49KHQtKGUuaUN1cnItNCkpJTU7c3dpdGNoKG4pe2Nhc2UgMDpyZXR1cm4gclt0XT09PWplO2Nhc2UgMTpyZXR1cm4gclt0XT09PXplO2Nhc2UgMjpyZXR1cm4gclt0XT09PUplO2Nhc2UgMzppZihyW3RdIT09WmUpcmV0dXJuITE7Y29uc3Qgbj1lLmlDdXJyLTMsaT1hW25dWzBdLHM9YVtuXVsxXTtyZXR1cm4gYVt0XVswXT09PWkmJmFbdF1bMV09PT1zO2Nhc2UgNDpyZXR1cm4gclt0XT09PVVlfXRocm93IG5ldyBFcnJvcihgaXRlcmF0ZVNob3dUZXh0R3JvdXAgLSBpbnZhbGlkIHBvczogJHtufWApfSxmdW5jdGlvbihlLHQpe2NvbnN0IHI9ZS5mbkFycmF5LGE9ZS5hcmdzQXJyYXksbj1lLmlDdXJyLGk9bi00LHM9bi0zLG89bi0yLGM9bi0xLGw9bixoPWFbc11bMF0sdT1hW3NdWzFdO2xldCBkPU1hdGgubWluKE1hdGguZmxvb3IoKHQtaSkvNSksMWUzKTtpZihkPDMpcmV0dXJuIHQtKHQtaSklNTtsZXQgZj1pO2lmKGk+PTQmJnJbaS00XT09PXJbc10mJnJbaS0zXT09PXJbb10mJnJbaS0yXT09PXJbY10mJnJbaS0xXT09PXJbbF0mJmFbaS00XVswXT09PWgmJmFbaS00XVsxXT09PXUpe2QrKztmLT01fWxldCBnPWYrNDtmb3IobGV0IGU9MTtlPGQ7ZSsrKXtyLnNwbGljZShnLDMpO2Euc3BsaWNlKGcsMyk7Zys9Mn1yZXR1cm4gZysxfSk7YWRkU3RhdGUoUHIsW3llLHhlLEh0LHdlXSxlPT57Y29uc3QgdD1lLmFyZ3NBcnJheSxyPXRbZS5pQ3Vyci0xXVswXTtpZihyIT09VGUmJnIhPT1PZSYmciE9PUJlJiZyIT09UmUmJnIhPT1FZSYmciE9PU5lKXJldHVybiEwO2NvbnN0IGE9dFtlLmlDdXJyLTJdO3JldHVybiAxPT09YVswXSYmMD09PWFbMV0mJjA9PT1hWzJdJiYxPT09YVszXX0sKCk9PiExLChlLHQpPT57Y29uc3R7Zm5BcnJheTpyLGFyZ3NBcnJheTphfT1lLG49ZS5pQ3VycixpPW4tMyxzPW4tMixvPWFbbi0xXSxjPWFbc10sWyxbbF0saF09bztpZihoKXtVdGlsLnNjYWxlTWluTWF4KGMsaCk7Zm9yKGxldCBlPTAsdD1sLmxlbmd0aDtlPHQ7KXN3aXRjaChsW2UrK10pe2Nhc2UgJHQ6Y2FzZSBWdDpVdGlsLmFwcGx5VHJhbnNmb3JtKGwsYyxlKTtlKz0yO2JyZWFrO2Nhc2UgS3Q6VXRpbC5hcHBseVRyYW5zZm9ybVRvQmV6aWVyKGwsYyxlKTtlKz02fX1yLnNwbGljZShpLDQsSHQpO2Euc3BsaWNlKGksNCxvKTtyZXR1cm4gaSsxfSk7Y2xhc3MgTnVsbE9wdGltaXplcntjb25zdHJ1Y3RvcihlKXt0aGlzLnF1ZXVlPWV9X29wdGltaXplKCl7fXB1c2goZSx0KXt0aGlzLnF1ZXVlLmZuQXJyYXkucHVzaChlKTt0aGlzLnF1ZXVlLmFyZ3NBcnJheS5wdXNoKHQpO3RoaXMuX29wdGltaXplKCl9Zmx1c2goKXt9cmVzZXQoKXt9fWNsYXNzIFF1ZXVlT3B0aW1pemVyIGV4dGVuZHMgTnVsbE9wdGltaXplcntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTt0aGlzLnN0YXRlPW51bGw7dGhpcy5jb250ZXh0PXtpQ3VycjowLGZuQXJyYXk6ZS5mbkFycmF5LGFyZ3NBcnJheTplLmFyZ3NBcnJheSxpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDpPcGVyYXRvckxpc3QuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWR9O3RoaXMubWF0Y2g9bnVsbDt0aGlzLmxhc3RQcm9jZXNzZWQ9MH1fb3B0aW1pemUoKXtjb25zdCBlPXRoaXMucXVldWUuZm5BcnJheTtsZXQgdD10aGlzLmxhc3RQcm9jZXNzZWQscj1lLmxlbmd0aCxhPXRoaXMuc3RhdGUsbj10aGlzLm1hdGNoO2lmKCFhJiYhbiYmdCsxPT09ciYmIVByW2VbdF1dKXt0aGlzLmxhc3RQcm9jZXNzZWQ9cjtyZXR1cm59Y29uc3QgaT10aGlzLmNvbnRleHQ7Zm9yKDt0PHI7KXtpZihuKXtpZigoMCxuLml0ZXJhdGVGbikoaSx0KSl7dCsrO2NvbnRpbnVlfXQ9KDAsbi5wcm9jZXNzRm4pKGksdCsxKTtyPWUubGVuZ3RoO249bnVsbDthPW51bGw7aWYodD49cilicmVha31hPShhfHxQcilbZVt0XV07aWYoYSYmIUFycmF5LmlzQXJyYXkoYSkpe2kuaUN1cnI9dDt0Kys7aWYoIWEuY2hlY2tGbnx8KDAsYS5jaGVja0ZuKShpKSl7bj1hO2E9bnVsbH1lbHNlIGE9bnVsbH1lbHNlIHQrK310aGlzLnN0YXRlPWE7dGhpcy5tYXRjaD1uO3RoaXMubGFzdFByb2Nlc3NlZD10fWZsdXNoKCl7Zm9yKDt0aGlzLm1hdGNoOyl7Y29uc3QgZT10aGlzLnF1ZXVlLmZuQXJyYXkubGVuZ3RoO3RoaXMubGFzdFByb2Nlc3NlZD0oMCx0aGlzLm1hdGNoLnByb2Nlc3NGbikodGhpcy5jb250ZXh0LGUpO3RoaXMubWF0Y2g9bnVsbDt0aGlzLnN0YXRlPW51bGw7dGhpcy5fb3B0aW1pemUoKX19cmVzZXQoKXt0aGlzLnN0YXRlPW51bGw7dGhpcy5tYXRjaD1udWxsO3RoaXMubGFzdFByb2Nlc3NlZD0wfX1jbGFzcyBPcGVyYXRvckxpc3R7c3RhdGljIENIVU5LX1NJWkU9MWUzO3N0YXRpYyBDSFVOS19TSVpFX0FCT1VUPXRoaXMuQ0hVTktfU0laRS01O3N0YXRpYyBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZD0hMTtjb25zdHJ1Y3RvcihlPTAsdCl7dGhpcy5fc3RyZWFtU2luaz10O3RoaXMuZm5BcnJheT1bXTt0aGlzLmFyZ3NBcnJheT1bXTt0aGlzLm9wdGltaXplcj0hdHx8ZSZnP25ldyBOdWxsT3B0aW1pemVyKHRoaXMpOm5ldyBRdWV1ZU9wdGltaXplcih0aGlzKTt0aGlzLmRlcGVuZGVuY2llcz1uZXcgU2V0O3RoaXMuX3RvdGFsTGVuZ3RoPTA7dGhpcy53ZWlnaHQ9MDt0aGlzLl9yZXNvbHZlZD10P251bGw6UHJvbWlzZS5yZXNvbHZlKCl9c3RhdGljIHNldE9wdGlvbnMoe2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOmV9KXt0aGlzLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkPWV9Z2V0IGxlbmd0aCgpe3JldHVybiB0aGlzLmFyZ3NBcnJheS5sZW5ndGh9Z2V0IHJlYWR5KCl7cmV0dXJuIHRoaXMuX3Jlc29sdmVkfHx0aGlzLl9zdHJlYW1TaW5rLnJlYWR5fWdldCB0b3RhbExlbmd0aCgpe3JldHVybiB0aGlzLl90b3RhbExlbmd0aCt0aGlzLmxlbmd0aH1hZGRPcChlLHQpe3RoaXMub3B0aW1pemVyLnB1c2goZSx0KTt0aGlzLndlaWdodCsrO3RoaXMuX3N0cmVhbVNpbmsmJih0aGlzLndlaWdodD49T3BlcmF0b3JMaXN0LkNIVU5LX1NJWkV8fHRoaXMud2VpZ2h0Pj1PcGVyYXRvckxpc3QuQ0hVTktfU0laRV9BQk9VVCYmKGU9PT13ZXx8ZT09PVVlKSkmJnRoaXMuZmx1c2goKX1hZGRJbWFnZU9wcyhlLHQscixhPSExKXtpZihhKXt0aGlzLmFkZE9wKHllKTt0aGlzLmFkZE9wKGJlLFtbWyJTTWFzayIsITFdXV0pfXZvaWQgMCE9PXImJnRoaXMuYWRkT3AodnQsWyJPQyIscl0pO3RoaXMuYWRkT3AoZSx0KTt2b2lkIDAhPT1yJiZ0aGlzLmFkZE9wKEZ0LFtdKTthJiZ0aGlzLmFkZE9wKHdlKX1hZGREZXBlbmRlbmN5KGUpe2lmKCF0aGlzLmRlcGVuZGVuY2llcy5oYXMoZSkpe3RoaXMuZGVwZW5kZW5jaWVzLmFkZChlKTt0aGlzLmFkZE9wKGxlLFtlXSl9fWFkZERlcGVuZGVuY2llcyhlKXtmb3IoY29uc3QgdCBvZiBlKXRoaXMuYWRkRGVwZW5kZW5jeSh0KX1hZGRPcExpc3QoZSl7aWYoZSBpbnN0YW5jZW9mIE9wZXJhdG9yTGlzdCl7Zm9yKGNvbnN0IHQgb2YgZS5kZXBlbmRlbmNpZXMpdGhpcy5kZXBlbmRlbmNpZXMuYWRkKHQpO2ZvcihsZXQgdD0wLHI9ZS5sZW5ndGg7dDxyO3QrKyl0aGlzLmFkZE9wKGUuZm5BcnJheVt0XSxlLmFyZ3NBcnJheVt0XSl9ZWxzZSB3YXJuKCdhZGRPcExpc3QgLSBpZ25vcmluZyBpbnZhbGlkICJvcExpc3QiIHBhcmFtZXRlci4nKX1nZXRJUigpe3JldHVybntmbkFycmF5OnRoaXMuZm5BcnJheSxhcmdzQXJyYXk6dGhpcy5hcmdzQXJyYXksbGVuZ3RoOnRoaXMubGVuZ3RofX1nZXQgX3RyYW5zZmVycygpe2NvbnN0IGU9W10se2ZuQXJyYXk6dCxhcmdzQXJyYXk6cixsZW5ndGg6YX09dGhpcztmb3IobGV0IG49MDtuPGE7bisrKXN3aXRjaCh0W25dKXtjYXNlIEx0OmNhc2UganQ6Y2FzZSBOdDp7Y29uc3R7Yml0bWFwOnQsZGF0YTphfT1yW25dWzBdOyh0fHxhPy5idWZmZXIpJiZlLnB1c2godHx8YS5idWZmZXIpO2JyZWFrfWNhc2UgSHQ6e2NvbnN0WyxbdF0sYV09cltuXTt0JiZlLnB1c2godC5idWZmZXIsYS5idWZmZXIpO2JyZWFrfWNhc2UgT3Q6Y29uc3RbdCxhXT1yW25dO3QmJmUucHVzaCh0LmJ1ZmZlcik7YSYmZS5wdXNoKGEuYnVmZmVyKTticmVhaztjYXNlIEplOmUucHVzaChyW25dWzBdLmJ1ZmZlcil9cmV0dXJuIGV9Zmx1c2goZT0hMSx0PW51bGwpe3RoaXMub3B0aW1pemVyLmZsdXNoKCk7Y29uc3Qgcj10aGlzLmxlbmd0aDt0aGlzLl90b3RhbExlbmd0aCs9cjt0aGlzLl9zdHJlYW1TaW5rLmVucXVldWUoe2ZuQXJyYXk6dGhpcy5mbkFycmF5LGFyZ3NBcnJheTp0aGlzLmFyZ3NBcnJheSxsYXN0Q2h1bms6ZSxzZXBhcmF0ZUFubm90czp0LGxlbmd0aDpyfSwxLHRoaXMuX3RyYW5zZmVycyk7dGhpcy5kZXBlbmRlbmNpZXMuY2xlYXIoKTt0aGlzLmZuQXJyYXkubGVuZ3RoPTA7dGhpcy5hcmdzQXJyYXkubGVuZ3RoPTA7dGhpcy53ZWlnaHQ9MDt0aGlzLm9wdGltaXplci5yZXNldCgpfX1fX3dlYnBhY2tfcmVxdWlyZV9fKDExNiksX193ZWJwYWNrX3JlcXVpcmVfXyg5NDc5KSxfX3dlYnBhY2tfcmVxdWlyZV9fKDc1ODgpO2Z1bmN0aW9uIGhleFRvSW50KGUsdCl7bGV0IHI9MDtmb3IobGV0IGE9MDthPD10O2ErKylyPXI8PDh8ZVthXTtyZXR1cm4gcj4+PjB9ZnVuY3Rpb24gaGV4VG9TdHIoZSx0KXtyZXR1cm4gMT09PXQ/U3RyaW5nLmZyb21DaGFyQ29kZShlWzBdLGVbMV0pOjM9PT10P1N0cmluZy5mcm9tQ2hhckNvZGUoZVswXSxlWzFdLGVbMl0sZVszXSk6U3RyaW5nLmZyb21DaGFyQ29kZSguLi5lLnN1YmFycmF5KDAsdCsxKSl9ZnVuY3Rpb24gYWRkSGV4KGUsdCxyKXtsZXQgYT0wO2ZvcihsZXQgbj1yO24+PTA7bi0tKXthKz1lW25dK3Rbbl07ZVtuXT0yNTUmYTthPj49OH19ZnVuY3Rpb24gaW5jSGV4KGUsdCl7bGV0IHI9MTtmb3IobGV0IGE9dDthPj0wJiZyPjA7YS0tKXtyKz1lW2FdO2VbYV09MjU1JnI7cj4+PTh9fWNvbnN0IF9yPTE2O2NsYXNzIEJpbmFyeUNNYXBTdHJlYW17Y29uc3RydWN0b3IoZSl7dGhpcy5idWZmZXI9ZTt0aGlzLnBvcz0wO3RoaXMuZW5kPWUubGVuZ3RoO3RoaXMudG1wQnVmPW5ldyBVaW50OEFycmF5KDE5KX1yZWFkQnl0ZSgpe3JldHVybiB0aGlzLnBvcz49dGhpcy5lbmQ/LTE6dGhpcy5idWZmZXJbdGhpcy5wb3MrK119cmVhZE51bWJlcigpe2xldCBlLHQ9MDtkb3tjb25zdCByPXRoaXMucmVhZEJ5dGUoKTtpZihyPDApdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJ1bmV4cGVjdGVkIEVPRiBpbiBiY21hcCIpO2U9ISgxMjgmcik7dD10PDw3fDEyNyZyfXdoaWxlKCFlKTtyZXR1cm4gdH1yZWFkU2lnbmVkKCl7Y29uc3QgZT10aGlzLnJlYWROdW1iZXIoKTtyZXR1cm4gMSZlP34oZT4+PjEpOmU+Pj4xfXJlYWRIZXgoZSx0KXtlLnNldCh0aGlzLmJ1ZmZlci5zdWJhcnJheSh0aGlzLnBvcyx0aGlzLnBvcyt0KzEpKTt0aGlzLnBvcys9dCsxfXJlYWRIZXhOdW1iZXIoZSx0KXtsZXQgcjtjb25zdCBhPXRoaXMudG1wQnVmO2xldCBuPTA7ZG97Y29uc3QgZT10aGlzLnJlYWRCeXRlKCk7aWYoZTwwKXRocm93IG5ldyBGb3JtYXRFcnJvcigidW5leHBlY3RlZCBFT0YgaW4gYmNtYXAiKTtyPSEoMTI4JmUpO2FbbisrXT0xMjcmZX13aGlsZSghcik7bGV0IGk9dCxzPTAsbz0wO2Zvcig7aT49MDspe2Zvcig7bzw4JiZhLmxlbmd0aD4wOyl7c3w9YVstLW5dPDxvO28rPTd9ZVtpXT0yNTUmcztpLS07cz4+PTg7by09OH19cmVhZEhleFNpZ25lZChlLHQpe3RoaXMucmVhZEhleE51bWJlcihlLHQpO2NvbnN0IHI9MSZlW3RdPzI1NTowO2xldCBhPTA7Zm9yKGxldCBuPTA7bjw9dDtuKyspe2E9KDEmYSk8PDh8ZVtuXTtlW25dPWE+PjFecn19cmVhZFN0cmluZygpe2NvbnN0IGU9dGhpcy5yZWFkTnVtYmVyKCksdD1uZXcgQXJyYXkoZSk7Zm9yKGxldCByPTA7cjxlO3IrKyl0W3JdPXRoaXMucmVhZE51bWJlcigpO3JldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKC4uLnQpfX1jbGFzcyBCaW5hcnlDTWFwUmVhZGVye2FzeW5jIHByb2Nlc3MoZSx0LHIpe2NvbnN0IGE9bmV3IEJpbmFyeUNNYXBTdHJlYW0oZSksbj1hLnJlYWRCeXRlKCk7dC52ZXJ0aWNhbD0hISgxJm4pO2xldCBpPW51bGw7Y29uc3Qgcz1uZXcgVWludDhBcnJheShfciksbz1uZXcgVWludDhBcnJheShfciksYz1uZXcgVWludDhBcnJheShfciksbD1uZXcgVWludDhBcnJheShfciksaD1uZXcgVWludDhBcnJheShfcik7bGV0IHUsZDtmb3IoOyhkPWEucmVhZEJ5dGUoKSk+PTA7KXtjb25zdCBlPWQ+PjU7aWYoNz09PWUpe3N3aXRjaCgzMSZkKXtjYXNlIDA6YS5yZWFkU3RyaW5nKCk7YnJlYWs7Y2FzZSAxOmk9YS5yZWFkU3RyaW5nKCl9Y29udGludWV9Y29uc3Qgcj0hISgxNiZkKSxuPTE1JmQ7aWYobisxPl9yKXRocm93IG5ldyBFcnJvcigiQmluYXJ5Q01hcFJlYWRlci5wcm9jZXNzOiBJbnZhbGlkIGRhdGFTaXplLiIpO2NvbnN0IGY9MSxnPWEucmVhZE51bWJlcigpO3N3aXRjaChlKXtjYXNlIDA6YS5yZWFkSGV4KHMsbik7YS5yZWFkSGV4TnVtYmVyKG8sbik7YWRkSGV4KG8scyxuKTt0LmFkZENvZGVzcGFjZVJhbmdlKG4rMSxoZXhUb0ludChzLG4pLGhleFRvSW50KG8sbikpO2ZvcihsZXQgZT0xO2U8ZztlKyspe2luY0hleChvLG4pO2EucmVhZEhleE51bWJlcihzLG4pO2FkZEhleChzLG8sbik7YS5yZWFkSGV4TnVtYmVyKG8sbik7YWRkSGV4KG8scyxuKTt0LmFkZENvZGVzcGFjZVJhbmdlKG4rMSxoZXhUb0ludChzLG4pLGhleFRvSW50KG8sbikpfWJyZWFrO2Nhc2UgMTphLnJlYWRIZXgocyxuKTthLnJlYWRIZXhOdW1iZXIobyxuKTthZGRIZXgobyxzLG4pO2EucmVhZE51bWJlcigpO2ZvcihsZXQgZT0xO2U8ZztlKyspe2luY0hleChvLG4pO2EucmVhZEhleE51bWJlcihzLG4pO2FkZEhleChzLG8sbik7YS5yZWFkSGV4TnVtYmVyKG8sbik7YWRkSGV4KG8scyxuKTthLnJlYWROdW1iZXIoKX1icmVhaztjYXNlIDI6YS5yZWFkSGV4KGMsbik7dT1hLnJlYWROdW1iZXIoKTt0Lm1hcE9uZShoZXhUb0ludChjLG4pLHUpO2ZvcihsZXQgZT0xO2U8ZztlKyspe2luY0hleChjLG4pO2lmKCFyKXthLnJlYWRIZXhOdW1iZXIoaCxuKTthZGRIZXgoYyxoLG4pfXU9YS5yZWFkU2lnbmVkKCkrKHUrMSk7dC5tYXBPbmUoaGV4VG9JbnQoYyxuKSx1KX1icmVhaztjYXNlIDM6YS5yZWFkSGV4KHMsbik7YS5yZWFkSGV4TnVtYmVyKG8sbik7YWRkSGV4KG8scyxuKTt1PWEucmVhZE51bWJlcigpO3QubWFwQ2lkUmFuZ2UoaGV4VG9JbnQocyxuKSxoZXhUb0ludChvLG4pLHUpO2ZvcihsZXQgZT0xO2U8ZztlKyspe2luY0hleChvLG4pO2lmKHIpcy5zZXQobyk7ZWxzZXthLnJlYWRIZXhOdW1iZXIocyxuKTthZGRIZXgocyxvLG4pfWEucmVhZEhleE51bWJlcihvLG4pO2FkZEhleChvLHMsbik7dT1hLnJlYWROdW1iZXIoKTt0Lm1hcENpZFJhbmdlKGhleFRvSW50KHMsbiksaGV4VG9JbnQobyxuKSx1KX1icmVhaztjYXNlIDQ6YS5yZWFkSGV4KGMsZik7YS5yZWFkSGV4KGwsbik7dC5tYXBPbmUoaGV4VG9JbnQoYyxmKSxoZXhUb1N0cihsLG4pKTtmb3IobGV0IGU9MTtlPGc7ZSsrKXtpbmNIZXgoYyxmKTtpZighcil7YS5yZWFkSGV4TnVtYmVyKGgsZik7YWRkSGV4KGMsaCxmKX1pbmNIZXgobCxuKTthLnJlYWRIZXhTaWduZWQoaCxuKTthZGRIZXgobCxoLG4pO3QubWFwT25lKGhleFRvSW50KGMsZiksaGV4VG9TdHIobCxuKSl9YnJlYWs7Y2FzZSA1OmEucmVhZEhleChzLGYpO2EucmVhZEhleE51bWJlcihvLGYpO2FkZEhleChvLHMsZik7YS5yZWFkSGV4KGwsbik7dC5tYXBCZlJhbmdlKGhleFRvSW50KHMsZiksaGV4VG9JbnQobyxmKSxoZXhUb1N0cihsLG4pKTtmb3IobGV0IGU9MTtlPGc7ZSsrKXtpbmNIZXgobyxmKTtpZihyKXMuc2V0KG8pO2Vsc2V7YS5yZWFkSGV4TnVtYmVyKHMsZik7YWRkSGV4KHMsbyxmKX1hLnJlYWRIZXhOdW1iZXIobyxmKTthZGRIZXgobyxzLGYpO2EucmVhZEhleChsLG4pO3QubWFwQmZSYW5nZShoZXhUb0ludChzLGYpLGhleFRvSW50KG8sZiksaGV4VG9TdHIobCxuKSl9YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYEJpbmFyeUNNYXBSZWFkZXIucHJvY2VzcyAtIHVua25vd24gdHlwZTogJHtlfWApfX1yZXR1cm4gaT9yKGkpOnR9fWNsYXNzIEFzY2lpODVTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17Y29uc3RydWN0b3IoZSx0KXt0JiYodCo9LjgpO3N1cGVyKHQpO3RoaXMuc3RyPWU7dGhpcy5kaWN0PWUuZGljdDt0aGlzLmlucHV0PW5ldyBVaW50OEFycmF5KDUpfXJlYWRCbG9jaygpe2NvbnN0IGU9dGhpcy5zdHI7bGV0IHQ9ZS5nZXRCeXRlKCk7Zm9yKDtpc1doaXRlU3BhY2UodCk7KXQ9ZS5nZXRCeXRlKCk7aWYoLTE9PT10fHwxMjY9PT10KXt0aGlzLmVvZj0hMDtyZXR1cm59Y29uc3Qgcj10aGlzLmJ1ZmZlckxlbmd0aDtsZXQgYSxuO2lmKDEyMj09PXQpe2E9dGhpcy5lbnN1cmVCdWZmZXIocis0KTtmb3Iobj0wO248NDsrK24pYVtyK25dPTA7dGhpcy5idWZmZXJMZW5ndGgrPTR9ZWxzZXtjb25zdCBpPXRoaXMuaW5wdXQ7aVswXT10O2ZvcihuPTE7bjw1Oysrbil7dD1lLmdldEJ5dGUoKTtmb3IoO2lzV2hpdGVTcGFjZSh0KTspdD1lLmdldEJ5dGUoKTtpW25dPXQ7aWYoLTE9PT10fHwxMjY9PT10KWJyZWFrfWE9dGhpcy5lbnN1cmVCdWZmZXIocituLTEpO3RoaXMuYnVmZmVyTGVuZ3RoKz1uLTE7aWYobjw1KXtmb3IoO248NTsrK24paVtuXT0xMTc7dGhpcy5lb2Y9ITB9bGV0IHM9MDtmb3Iobj0wO248NTsrK24pcz04NSpzKyhpW25dLTMzKTtmb3Iobj0zO24+PTA7LS1uKXthW3Irbl09MjU1JnM7cz4+PTh9fX19Y2xhc3MgQXNjaWlIZXhTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17Y29uc3RydWN0b3IoZSx0KXt0JiYodCo9LjUpO3N1cGVyKHQpO3RoaXMuc3RyPWU7dGhpcy5kaWN0PWUuZGljdDt0aGlzLmZpcnN0RGlnaXQ9LTF9cmVhZEJsb2NrKCl7Y29uc3QgZT10aGlzLnN0ci5nZXRCeXRlcyg4ZTMpO2lmKCFlLmxlbmd0aCl7dGhpcy5lb2Y9ITA7cmV0dXJufWNvbnN0IHQ9ZS5sZW5ndGgrMT4+MSxyPXRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoK3QpO2xldCBhPXRoaXMuYnVmZmVyTGVuZ3RoLG49dGhpcy5maXJzdERpZ2l0O2Zvcihjb25zdCB0IG9mIGUpe2xldCBlO2lmKHQ+PTQ4JiZ0PD01NyllPTE1JnQ7ZWxzZXtpZighKHQ+PTY1JiZ0PD03MHx8dD49OTcmJnQ8PTEwMikpe2lmKDYyPT09dCl7dGhpcy5lb2Y9ITA7YnJlYWt9Y29udGludWV9ZT05KygxNSZ0KX1pZihuPDApbj1lO2Vsc2V7clthKytdPW48PDR8ZTtuPS0xfX1pZihuPj0wJiZ0aGlzLmVvZil7clthKytdPW48PDQ7bj0tMX10aGlzLmZpcnN0RGlnaXQ9bjt0aGlzLmJ1ZmZlckxlbmd0aD1hfX1jb25zdCBMcj0tMSxqcj1bWy0xLC0xXSxbLTEsLTFdLFs3LDhdLFs3LDddLFs2LDZdLFs2LDZdLFs2LDVdLFs2LDVdLFs0LDBdLFs0LDBdLFs0LDBdLFs0LDBdLFs0LDBdLFs0LDBdLFs0LDBdLFs0LDBdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDFdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDRdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFszLDNdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdLFsxLDJdXSxVcj1bWy0xLC0xXSxbMTIsLTJdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbMTEsMTc5Ml0sWzExLDE3OTJdLFsxMiwxOTg0XSxbMTIsMjA0OF0sWzEyLDIxMTJdLFsxMiwyMTc2XSxbMTIsMjI0MF0sWzEyLDIzMDRdLFsxMSwxODU2XSxbMTEsMTg1Nl0sWzExLDE5MjBdLFsxMSwxOTIwXSxbMTIsMjM2OF0sWzEyLDI0MzJdLFsxMiwyNDk2XSxbMTIsMjU2MF1dLHFyPVtbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFs4LDI5XSxbOCwyOV0sWzgsMzBdLFs4LDMwXSxbOCw0NV0sWzgsNDVdLFs4LDQ2XSxbOCw0Nl0sWzcsMjJdLFs3LDIyXSxbNywyMl0sWzcsMjJdLFs3LDIzXSxbNywyM10sWzcsMjNdLFs3LDIzXSxbOCw0N10sWzgsNDddLFs4LDQ4XSxbOCw0OF0sWzYsMTNdLFs2LDEzXSxbNiwxM10sWzYsMTNdLFs2LDEzXSxbNiwxM10sWzYsMTNdLFs2LDEzXSxbNywyMF0sWzcsMjBdLFs3LDIwXSxbNywyMF0sWzgsMzNdLFs4LDMzXSxbOCwzNF0sWzgsMzRdLFs4LDM1XSxbOCwzNV0sWzgsMzZdLFs4LDM2XSxbOCwzN10sWzgsMzddLFs4LDM4XSxbOCwzOF0sWzcsMTldLFs3LDE5XSxbNywxOV0sWzcsMTldLFs4LDMxXSxbOCwzMV0sWzgsMzJdLFs4LDMyXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxXSxbNiwxMl0sWzYsMTJdLFs2LDEyXSxbNiwxMl0sWzYsMTJdLFs2LDEyXSxbNiwxMl0sWzYsMTJdLFs4LDUzXSxbOCw1M10sWzgsNTRdLFs4LDU0XSxbNywyNl0sWzcsMjZdLFs3LDI2XSxbNywyNl0sWzgsMzldLFs4LDM5XSxbOCw0MF0sWzgsNDBdLFs4LDQxXSxbOCw0MV0sWzgsNDJdLFs4LDQyXSxbOCw0M10sWzgsNDNdLFs4LDQ0XSxbOCw0NF0sWzcsMjFdLFs3LDIxXSxbNywyMV0sWzcsMjFdLFs3LDI4XSxbNywyOF0sWzcsMjhdLFs3LDI4XSxbOCw2MV0sWzgsNjFdLFs4LDYyXSxbOCw2Ml0sWzgsNjNdLFs4LDYzXSxbOCwwXSxbOCwwXSxbOCwzMjBdLFs4LDMyMF0sWzgsMzg0XSxbOCwzODRdLFs1LDEwXSxbNSwxMF0sWzUsMTBdLFs1LDEwXSxbNSwxMF0sWzUsMTBdLFs1LDEwXSxbNSwxMF0sWzUsMTBdLFs1LDEwXSxbNSwxMF0sWzUsMTBdLFs1LDEwXSxbNSwxMF0sWzUsMTBdLFs1LDEwXSxbNSwxMV0sWzUsMTFdLFs1LDExXSxbNSwxMV0sWzUsMTFdLFs1LDExXSxbNSwxMV0sWzUsMTFdLFs1LDExXSxbNSwxMV0sWzUsMTFdLFs1LDExXSxbNSwxMV0sWzUsMTFdLFs1LDExXSxbNSwxMV0sWzcsMjddLFs3LDI3XSxbNywyN10sWzcsMjddLFs4LDU5XSxbOCw1OV0sWzgsNjBdLFs4LDYwXSxbOSwxNDcyXSxbOSwxNTM2XSxbOSwxNjAwXSxbOSwxNzI4XSxbNywxOF0sWzcsMThdLFs3LDE4XSxbNywxOF0sWzcsMjRdLFs3LDI0XSxbNywyNF0sWzcsMjRdLFs4LDQ5XSxbOCw0OV0sWzgsNTBdLFs4LDUwXSxbOCw1MV0sWzgsNTFdLFs4LDUyXSxbOCw1Ml0sWzcsMjVdLFs3LDI1XSxbNywyNV0sWzcsMjVdLFs4LDU1XSxbOCw1NV0sWzgsNTZdLFs4LDU2XSxbOCw1N10sWzgsNTddLFs4LDU4XSxbOCw1OF0sWzYsMTkyXSxbNiwxOTJdLFs2LDE5Ml0sWzYsMTkyXSxbNiwxOTJdLFs2LDE5Ml0sWzYsMTkyXSxbNiwxOTJdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs2LDE2NjRdLFs4LDQ0OF0sWzgsNDQ4XSxbOCw1MTJdLFs4LDUxMl0sWzksNzA0XSxbOSw3NjhdLFs4LDY0MF0sWzgsNjQwXSxbOCw1NzZdLFs4LDU3Nl0sWzksODMyXSxbOSw4OTZdLFs5LDk2MF0sWzksMTAyNF0sWzksMTA4OF0sWzksMTE1Ml0sWzksMTIxNl0sWzksMTI4MF0sWzksMTM0NF0sWzksMTQwOF0sWzcsMjU2XSxbNywyNTZdLFs3LDI1Nl0sWzcsMjU2XSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwyXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNSwxMjhdLFs1LDEyOF0sWzUsMTI4XSxbNSwxMjhdLFs1LDEyOF0sWzUsMTI4XSxbNSwxMjhdLFs1LDEyOF0sWzUsMTI4XSxbNSwxMjhdLFs1LDEyOF0sWzUsMTI4XSxbNSwxMjhdLFs1LDEyOF0sWzUsMTI4XSxbNSwxMjhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDhdLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs1LDldLFs2LDE2XSxbNiwxNl0sWzYsMTZdLFs2LDE2XSxbNiwxNl0sWzYsMTZdLFs2LDE2XSxbNiwxNl0sWzYsMTddLFs2LDE3XSxbNiwxN10sWzYsMTddLFs2LDE3XSxbNiwxN10sWzYsMTddLFs2LDE3XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw0XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbNiwxNF0sWzYsMTRdLFs2LDE0XSxbNiwxNF0sWzYsMTRdLFs2LDE0XSxbNiwxNF0sWzYsMTRdLFs2LDE1XSxbNiwxNV0sWzYsMTVdLFs2LDE1XSxbNiwxNV0sWzYsMTVdLFs2LDE1XSxbNiwxNV0sWzUsNjRdLFs1LDY0XSxbNSw2NF0sWzUsNjRdLFs1LDY0XSxbNSw2NF0sWzUsNjRdLFs1LDY0XSxbNSw2NF0sWzUsNjRdLFs1LDY0XSxbNSw2NF0sWzUsNjRdLFs1LDY0XSxbNSw2NF0sWzUsNjRdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDZdLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddLFs0LDddXSxYcj1bWy0xLC0xXSxbLTEsLTFdLFsxMiwtMl0sWzEyLC0yXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbLTEsLTFdLFsxMSwxNzkyXSxbMTEsMTc5Ml0sWzExLDE3OTJdLFsxMSwxNzkyXSxbMTIsMTk4NF0sWzEyLDE5ODRdLFsxMiwyMDQ4XSxbMTIsMjA0OF0sWzEyLDIxMTJdLFsxMiwyMTEyXSxbMTIsMjE3Nl0sWzEyLDIxNzZdLFsxMiwyMjQwXSxbMTIsMjI0MF0sWzEyLDIzMDRdLFsxMiwyMzA0XSxbMTEsMTg1Nl0sWzExLDE4NTZdLFsxMSwxODU2XSxbMTEsMTg1Nl0sWzExLDE5MjBdLFsxMSwxOTIwXSxbMTEsMTkyMF0sWzExLDE5MjBdLFsxMiwyMzY4XSxbMTIsMjM2OF0sWzEyLDI0MzJdLFsxMiwyNDMyXSxbMTIsMjQ5Nl0sWzEyLDI0OTZdLFsxMiwyNTYwXSxbMTIsMjU2MF0sWzEwLDE4XSxbMTAsMThdLFsxMCwxOF0sWzEwLDE4XSxbMTAsMThdLFsxMCwxOF0sWzEwLDE4XSxbMTAsMThdLFsxMiw1Ml0sWzEyLDUyXSxbMTMsNjQwXSxbMTMsNzA0XSxbMTMsNzY4XSxbMTMsODMyXSxbMTIsNTVdLFsxMiw1NV0sWzEyLDU2XSxbMTIsNTZdLFsxMywxMjgwXSxbMTMsMTM0NF0sWzEzLDE0MDhdLFsxMywxNDcyXSxbMTIsNTldLFsxMiw1OV0sWzEyLDYwXSxbMTIsNjBdLFsxMywxNTM2XSxbMTMsMTYwMF0sWzExLDI0XSxbMTEsMjRdLFsxMSwyNF0sWzExLDI0XSxbMTEsMjVdLFsxMSwyNV0sWzExLDI1XSxbMTEsMjVdLFsxMywxNjY0XSxbMTMsMTcyOF0sWzEyLDMyMF0sWzEyLDMyMF0sWzEyLDM4NF0sWzEyLDM4NF0sWzEyLDQ0OF0sWzEyLDQ0OF0sWzEzLDUxMl0sWzEzLDU3Nl0sWzEyLDUzXSxbMTIsNTNdLFsxMiw1NF0sWzEyLDU0XSxbMTMsODk2XSxbMTMsOTYwXSxbMTMsMTAyNF0sWzEzLDEwODhdLFsxMywxMTUyXSxbMTMsMTIxNl0sWzEwLDY0XSxbMTAsNjRdLFsxMCw2NF0sWzEwLDY0XSxbMTAsNjRdLFsxMCw2NF0sWzEwLDY0XSxbMTAsNjRdXSxIcj1bWzgsMTNdLFs4LDEzXSxbOCwxM10sWzgsMTNdLFs4LDEzXSxbOCwxM10sWzgsMTNdLFs4LDEzXSxbOCwxM10sWzgsMTNdLFs4LDEzXSxbOCwxM10sWzgsMTNdLFs4LDEzXSxbOCwxM10sWzgsMTNdLFsxMSwyM10sWzExLDIzXSxbMTIsNTBdLFsxMiw1MV0sWzEyLDQ0XSxbMTIsNDVdLFsxMiw0Nl0sWzEyLDQ3XSxbMTIsNTddLFsxMiw1OF0sWzEyLDYxXSxbMTIsMjU2XSxbMTAsMTZdLFsxMCwxNl0sWzEwLDE2XSxbMTAsMTZdLFsxMCwxN10sWzEwLDE3XSxbMTAsMTddLFsxMCwxN10sWzEyLDQ4XSxbMTIsNDldLFsxMiw2Ml0sWzEyLDYzXSxbMTIsMzBdLFsxMiwzMV0sWzEyLDMyXSxbMTIsMzNdLFsxMiw0MF0sWzEyLDQxXSxbMTEsMjJdLFsxMSwyMl0sWzgsMTRdLFs4LDE0XSxbOCwxNF0sWzgsMTRdLFs4LDE0XSxbOCwxNF0sWzgsMTRdLFs4LDE0XSxbOCwxNF0sWzgsMTRdLFs4LDE0XSxbOCwxNF0sWzgsMTRdLFs4LDE0XSxbOCwxNF0sWzgsMTRdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTBdLFs3LDEwXSxbNywxMF0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbNywxMV0sWzcsMTFdLFs3LDExXSxbOSwxNV0sWzksMTVdLFs5LDE1XSxbOSwxNV0sWzksMTVdLFs5LDE1XSxbOSwxNV0sWzksMTVdLFsxMiwxMjhdLFsxMiwxOTJdLFsxMiwyNl0sWzEyLDI3XSxbMTIsMjhdLFsxMiwyOV0sWzExLDE5XSxbMTEsMTldLFsxMSwyMF0sWzExLDIwXSxbMTIsMzRdLFsxMiwzNV0sWzEyLDM2XSxbMTIsMzddLFsxMiwzOF0sWzEyLDM5XSxbMTEsMjFdLFsxMSwyMV0sWzEyLDQyXSxbMTIsNDNdLFsxMCwwXSxbMTAsMF0sWzEwLDBdLFsxMCwwXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdLFs3LDEyXSxbNywxMl0sWzcsMTJdXSxXcj1bWy0xLC0xXSxbLTEsLTFdLFstMSwtMV0sWy0xLC0xXSxbNiw5XSxbNiw4XSxbNSw3XSxbNSw3XSxbNCw2XSxbNCw2XSxbNCw2XSxbNCw2XSxbNCw1XSxbNCw1XSxbNCw1XSxbNCw1XSxbMywxXSxbMywxXSxbMywxXSxbMywxXSxbMywxXSxbMywxXSxbMywxXSxbMywxXSxbMyw0XSxbMyw0XSxbMyw0XSxbMyw0XSxbMyw0XSxbMyw0XSxbMyw0XSxbMyw0XSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwzXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXSxbMiwyXV07Y2xhc3MgQ0NJVFRGYXhEZWNvZGVye2NvbnN0cnVjdG9yKGUsdD17fSl7aWYoImZ1bmN0aW9uIiE9dHlwZW9mIGU/Lm5leHQpdGhyb3cgbmV3IEVycm9yKCdDQ0lUVEZheERlY29kZXIgLSBpbnZhbGlkICJzb3VyY2UiIHBhcmFtZXRlci4nKTt0aGlzLnNvdXJjZT1lO3RoaXMuZW9mPSExO3RoaXMuZW5jb2Rpbmc9dC5LfHwwO3RoaXMuZW9saW5lPXQuRW5kT2ZMaW5lfHwhMTt0aGlzLmJ5dGVBbGlnbj10LkVuY29kZWRCeXRlQWxpZ258fCExO3RoaXMuY29sdW1ucz10LkNvbHVtbnN8fDE3Mjg7dGhpcy5yb3dzPXQuUm93c3x8MDt0aGlzLmVvYmxvY2s9dC5FbmRPZkJsb2NrPz8hMDt0aGlzLmJsYWNrPXQuQmxhY2tJczF8fCExO3RoaXMuY29kaW5nTGluZT1uZXcgVWludDMyQXJyYXkodGhpcy5jb2x1bW5zKzEpO3RoaXMucmVmTGluZT1uZXcgVWludDMyQXJyYXkodGhpcy5jb2x1bW5zKzIpO3RoaXMuY29kaW5nTGluZVswXT10aGlzLmNvbHVtbnM7dGhpcy5jb2RpbmdQb3M9MDt0aGlzLnJvdz0wO3RoaXMubmV4dExpbmUyRD10aGlzLmVuY29kaW5nPDA7dGhpcy5pbnB1dEJpdHM9MDt0aGlzLmlucHV0QnVmPTA7dGhpcy5vdXRwdXRCaXRzPTA7dGhpcy5yb3dzRG9uZT0hMTtsZXQgcjtmb3IoOzA9PT0ocj10aGlzLl9sb29rQml0cygxMikpOyl0aGlzLl9lYXRCaXRzKDEpOzE9PT1yJiZ0aGlzLl9lYXRCaXRzKDEyKTtpZih0aGlzLmVuY29kaW5nPjApe3RoaXMubmV4dExpbmUyRD0hdGhpcy5fbG9va0JpdHMoMSk7dGhpcy5fZWF0Qml0cygxKX19cmVhZE5leHRDaGFyKCl7aWYodGhpcy5lb2YpcmV0dXJuLTE7Y29uc3QgZT10aGlzLnJlZkxpbmUsdD10aGlzLmNvZGluZ0xpbmUscj10aGlzLmNvbHVtbnM7bGV0IGEsbixpLHMsbztpZigwPT09dGhpcy5vdXRwdXRCaXRzKXt0aGlzLnJvd3NEb25lJiYodGhpcy5lb2Y9ITApO2lmKHRoaXMuZW9mKXJldHVybi0xO3RoaXMuZXJyPSExO2xldCBpLG8sYztpZih0aGlzLm5leHRMaW5lMkQpe2ZvcihzPTA7dFtzXTxyOysrcyllW3NdPXRbc107ZVtzKytdPXI7ZVtzXT1yO3RbMF09MDt0aGlzLmNvZGluZ1Bvcz0wO2E9MDtuPTA7Zm9yKDt0W3RoaXMuY29kaW5nUG9zXTxyOyl7aT10aGlzLl9nZXRUd29EaW1Db2RlKCk7c3dpdGNoKGkpe2Nhc2UgMDp0aGlzLl9hZGRQaXhlbHMoZVthKzFdLG4pO2VbYSsxXTxyJiYoYSs9Mik7YnJlYWs7Y2FzZSAxOmk9bz0wO2lmKG4pe2Rve2krPWM9dGhpcy5fZ2V0QmxhY2tDb2RlKCl9d2hpbGUoYz49NjQpO2Rve28rPWM9dGhpcy5fZ2V0V2hpdGVDb2RlKCl9d2hpbGUoYz49NjQpfWVsc2V7ZG97aSs9Yz10aGlzLl9nZXRXaGl0ZUNvZGUoKX13aGlsZShjPj02NCk7ZG97bys9Yz10aGlzLl9nZXRCbGFja0NvZGUoKX13aGlsZShjPj02NCl9dGhpcy5fYWRkUGl4ZWxzKHRbdGhpcy5jb2RpbmdQb3NdK2ksbik7dFt0aGlzLmNvZGluZ1Bvc108ciYmdGhpcy5fYWRkUGl4ZWxzKHRbdGhpcy5jb2RpbmdQb3NdK28sMV5uKTtmb3IoO2VbYV08PXRbdGhpcy5jb2RpbmdQb3NdJiZlW2FdPHI7KWErPTI7YnJlYWs7Y2FzZSA3OnRoaXMuX2FkZFBpeGVscyhlW2FdKzMsbik7bl49MTtpZih0W3RoaXMuY29kaW5nUG9zXTxyKXsrK2E7Zm9yKDtlW2FdPD10W3RoaXMuY29kaW5nUG9zXSYmZVthXTxyOylhKz0yfWJyZWFrO2Nhc2UgNTp0aGlzLl9hZGRQaXhlbHMoZVthXSsyLG4pO25ePTE7aWYodFt0aGlzLmNvZGluZ1Bvc108cil7KythO2Zvcig7ZVthXTw9dFt0aGlzLmNvZGluZ1Bvc10mJmVbYV08cjspYSs9Mn1icmVhaztjYXNlIDM6dGhpcy5fYWRkUGl4ZWxzKGVbYV0rMSxuKTtuXj0xO2lmKHRbdGhpcy5jb2RpbmdQb3NdPHIpeysrYTtmb3IoO2VbYV08PXRbdGhpcy5jb2RpbmdQb3NdJiZlW2FdPHI7KWErPTJ9YnJlYWs7Y2FzZSAyOnRoaXMuX2FkZFBpeGVscyhlW2FdLG4pO25ePTE7aWYodFt0aGlzLmNvZGluZ1Bvc108cil7KythO2Zvcig7ZVthXTw9dFt0aGlzLmNvZGluZ1Bvc10mJmVbYV08cjspYSs9Mn1icmVhaztjYXNlIDg6dGhpcy5fYWRkUGl4ZWxzTmVnKGVbYV0tMyxuKTtuXj0xO2lmKHRbdGhpcy5jb2RpbmdQb3NdPHIpe2E+MD8tLWE6KythO2Zvcig7ZVthXTw9dFt0aGlzLmNvZGluZ1Bvc10mJmVbYV08cjspYSs9Mn1icmVhaztjYXNlIDY6dGhpcy5fYWRkUGl4ZWxzTmVnKGVbYV0tMixuKTtuXj0xO2lmKHRbdGhpcy5jb2RpbmdQb3NdPHIpe2E+MD8tLWE6KythO2Zvcig7ZVthXTw9dFt0aGlzLmNvZGluZ1Bvc10mJmVbYV08cjspYSs9Mn1icmVhaztjYXNlIDQ6dGhpcy5fYWRkUGl4ZWxzTmVnKGVbYV0tMSxuKTtuXj0xO2lmKHRbdGhpcy5jb2RpbmdQb3NdPHIpe2E+MD8tLWE6KythO2Zvcig7ZVthXTw9dFt0aGlzLmNvZGluZ1Bvc10mJmVbYV08cjspYSs9Mn1icmVhaztjYXNlIExyOnRoaXMuX2FkZFBpeGVscyhyLDApO3RoaXMuZW9mPSEwO2JyZWFrO2RlZmF1bHQ6aW5mbygiYmFkIDJkIGNvZGUiKTt0aGlzLl9hZGRQaXhlbHMociwwKTt0aGlzLmVycj0hMH19fWVsc2V7dFswXT0wO3RoaXMuY29kaW5nUG9zPTA7bj0wO2Zvcig7dFt0aGlzLmNvZGluZ1Bvc108cjspe2k9MDtpZihuKWRve2krPWM9dGhpcy5fZ2V0QmxhY2tDb2RlKCl9d2hpbGUoYz49NjQpO2Vsc2UgZG97aSs9Yz10aGlzLl9nZXRXaGl0ZUNvZGUoKX13aGlsZShjPj02NCk7dGhpcy5fYWRkUGl4ZWxzKHRbdGhpcy5jb2RpbmdQb3NdK2ksbik7bl49MX19bGV0IGw9ITE7dGhpcy5ieXRlQWxpZ24mJih0aGlzLmlucHV0Qml0cyY9LTgpO2lmKHRoaXMuZW9ibG9ja3x8dGhpcy5yb3chPT10aGlzLnJvd3MtMSl7aT10aGlzLl9sb29rQml0cygxMik7aWYodGhpcy5lb2xpbmUpZm9yKDtpIT09THImJjEhPT1pOyl7dGhpcy5fZWF0Qml0cygxKTtpPXRoaXMuX2xvb2tCaXRzKDEyKX1lbHNlIGZvcig7MD09PWk7KXt0aGlzLl9lYXRCaXRzKDEpO2k9dGhpcy5fbG9va0JpdHMoMTIpfWlmKDE9PT1pKXt0aGlzLl9lYXRCaXRzKDEyKTtsPSEwfWVsc2UgaT09PUxyJiYodGhpcy5lb2Y9ITApfWVsc2UgdGhpcy5yb3dzRG9uZT0hMDtpZighdGhpcy5lb2YmJnRoaXMuZW5jb2Rpbmc+MCYmIXRoaXMucm93c0RvbmUpe3RoaXMubmV4dExpbmUyRD0hdGhpcy5fbG9va0JpdHMoMSk7dGhpcy5fZWF0Qml0cygxKX1pZih0aGlzLmVvYmxvY2smJmwmJnRoaXMuYnl0ZUFsaWduKXtpPXRoaXMuX2xvb2tCaXRzKDEyKTtpZigxPT09aSl7dGhpcy5fZWF0Qml0cygxMik7aWYodGhpcy5lbmNvZGluZz4wKXt0aGlzLl9sb29rQml0cygxKTt0aGlzLl9lYXRCaXRzKDEpfWlmKHRoaXMuZW5jb2Rpbmc+PTApZm9yKHM9MDtzPDQ7KytzKXtpPXRoaXMuX2xvb2tCaXRzKDEyKTsxIT09aSYmaW5mbygiYmFkIHJ0YyBjb2RlOiAiK2kpO3RoaXMuX2VhdEJpdHMoMTIpO2lmKHRoaXMuZW5jb2Rpbmc+MCl7dGhpcy5fbG9va0JpdHMoMSk7dGhpcy5fZWF0Qml0cygxKX19dGhpcy5lb2Y9ITB9fWVsc2UgaWYodGhpcy5lcnImJnRoaXMuZW9saW5lKXtmb3IoOzspe2k9dGhpcy5fbG9va0JpdHMoMTMpO2lmKGk9PT1Mcil7dGhpcy5lb2Y9ITA7cmV0dXJuLTF9aWYoaT4+MT09MSlicmVhazt0aGlzLl9lYXRCaXRzKDEpfXRoaXMuX2VhdEJpdHMoMTIpO2lmKHRoaXMuZW5jb2Rpbmc+MCl7dGhpcy5fZWF0Qml0cygxKTt0aGlzLm5leHRMaW5lMkQ9ISgxJmkpfX10aGlzLm91dHB1dEJpdHM9dFswXT4wP3RbdGhpcy5jb2RpbmdQb3M9MF06dFt0aGlzLmNvZGluZ1Bvcz0xXTt0aGlzLnJvdysrfWlmKHRoaXMub3V0cHV0Qml0cz49OCl7bz0xJnRoaXMuY29kaW5nUG9zPzA6MjU1O3RoaXMub3V0cHV0Qml0cy09ODtpZigwPT09dGhpcy5vdXRwdXRCaXRzJiZ0W3RoaXMuY29kaW5nUG9zXTxyKXt0aGlzLmNvZGluZ1BvcysrO3RoaXMub3V0cHV0Qml0cz10W3RoaXMuY29kaW5nUG9zXS10W3RoaXMuY29kaW5nUG9zLTFdfX1lbHNle2k9ODtvPTA7ZG97aWYoIm51bWJlciIhPXR5cGVvZiB0aGlzLm91dHB1dEJpdHMpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdJbnZhbGlkIC9DQ0lUVEZheERlY29kZSBkYXRhLCAib3V0cHV0Qml0cyIgbXVzdCBiZSBhIG51bWJlci4nKTtpZih0aGlzLm91dHB1dEJpdHM+aSl7bzw8PWk7MSZ0aGlzLmNvZGluZ1Bvc3x8KG98PTI1NT4+OC1pKTt0aGlzLm91dHB1dEJpdHMtPWk7aT0wfWVsc2V7bzw8PXRoaXMub3V0cHV0Qml0czsxJnRoaXMuY29kaW5nUG9zfHwob3w9MjU1Pj44LXRoaXMub3V0cHV0Qml0cyk7aS09dGhpcy5vdXRwdXRCaXRzO3RoaXMub3V0cHV0Qml0cz0wO2lmKHRbdGhpcy5jb2RpbmdQb3NdPHIpe3RoaXMuY29kaW5nUG9zKys7dGhpcy5vdXRwdXRCaXRzPXRbdGhpcy5jb2RpbmdQb3NdLXRbdGhpcy5jb2RpbmdQb3MtMV19ZWxzZSBpZihpPjApe288PD1pO2k9MH19fXdoaWxlKGkpfXRoaXMuYmxhY2smJihvXj0yNTUpO3JldHVybiBvfV9hZGRQaXhlbHMoZSx0KXtjb25zdCByPXRoaXMuY29kaW5nTGluZTtsZXQgYT10aGlzLmNvZGluZ1BvcztpZihlPnJbYV0pe2lmKGU+dGhpcy5jb2x1bW5zKXtpbmZvKCJyb3cgaXMgd3JvbmcgbGVuZ3RoIik7dGhpcy5lcnI9ITA7ZT10aGlzLmNvbHVtbnN9MSZhXnQmJisrYTtyW2FdPWV9dGhpcy5jb2RpbmdQb3M9YX1fYWRkUGl4ZWxzTmVnKGUsdCl7Y29uc3Qgcj10aGlzLmNvZGluZ0xpbmU7bGV0IGE9dGhpcy5jb2RpbmdQb3M7aWYoZT5yW2FdKXtpZihlPnRoaXMuY29sdW1ucyl7aW5mbygicm93IGlzIHdyb25nIGxlbmd0aCIpO3RoaXMuZXJyPSEwO2U9dGhpcy5jb2x1bW5zfTEmYV50JiYrK2E7clthXT1lfWVsc2UgaWYoZTxyW2FdKXtpZihlPDApe2luZm8oImludmFsaWQgY29kZSIpO3RoaXMuZXJyPSEwO2U9MH1mb3IoO2E+MCYmZTxyW2EtMV07KS0tYTtyW2FdPWV9dGhpcy5jb2RpbmdQb3M9YX1fZmluZFRhYmxlQ29kZShlLHQscixhKXtjb25zdCBuPWF8fDA7Zm9yKGxldCBhPWU7YTw9dDsrK2Epe2xldCBlPXRoaXMuX2xvb2tCaXRzKGEpO2lmKGU9PT1McilyZXR1cm5bITAsMSwhMV07YTx0JiYoZTw8PXQtYSk7aWYoIW58fGU+PW4pe2NvbnN0IHQ9cltlLW5dO2lmKHRbMF09PT1hKXt0aGlzLl9lYXRCaXRzKGEpO3JldHVyblshMCx0WzFdLCEwXX19fXJldHVyblshMSwwLCExXX1fZ2V0VHdvRGltQ29kZSgpe2xldCBlLHQ9MDtpZih0aGlzLmVvYmxvY2spe3Q9dGhpcy5fbG9va0JpdHMoNyk7ZT1qclt0XTtpZihlPy5bMF0+MCl7dGhpcy5fZWF0Qml0cyhlWzBdKTtyZXR1cm4gZVsxXX19ZWxzZXtjb25zdCBlPXRoaXMuX2ZpbmRUYWJsZUNvZGUoMSw3LGpyKTtpZihlWzBdJiZlWzJdKXJldHVybiBlWzFdfWluZm8oIkJhZCB0d28gZGltIGNvZGUiKTtyZXR1cm4gTHJ9X2dldFdoaXRlQ29kZSgpe2xldCBlLHQ9MDtpZih0aGlzLmVvYmxvY2spe3Q9dGhpcy5fbG9va0JpdHMoMTIpO2lmKHQ9PT1McilyZXR1cm4gMTtlPXQ+PjU/cXJbdD4+M106VXJbdF07aWYoZVswXT4wKXt0aGlzLl9lYXRCaXRzKGVbMF0pO3JldHVybiBlWzFdfX1lbHNle2xldCBlPXRoaXMuX2ZpbmRUYWJsZUNvZGUoMSw5LHFyKTtpZihlWzBdKXJldHVybiBlWzFdO2U9dGhpcy5fZmluZFRhYmxlQ29kZSgxMSwxMixVcik7aWYoZVswXSlyZXR1cm4gZVsxXX1pbmZvKCJiYWQgd2hpdGUgY29kZSIpO3RoaXMuX2VhdEJpdHMoMSk7cmV0dXJuIDF9X2dldEJsYWNrQ29kZSgpe2xldCBlLHQ7aWYodGhpcy5lb2Jsb2NrKXtlPXRoaXMuX2xvb2tCaXRzKDEzKTtpZihlPT09THIpcmV0dXJuIDE7dD1lPj43PyEoZT4+OSkmJmU+Pjc/SHJbKGU+PjEpLTY0XTpXcltlPj43XTpYcltlXTtpZih0WzBdPjApe3RoaXMuX2VhdEJpdHModFswXSk7cmV0dXJuIHRbMV19fWVsc2V7bGV0IGU9dGhpcy5fZmluZFRhYmxlQ29kZSgyLDYsV3IpO2lmKGVbMF0pcmV0dXJuIGVbMV07ZT10aGlzLl9maW5kVGFibGVDb2RlKDcsMTIsSHIsNjQpO2lmKGVbMF0pcmV0dXJuIGVbMV07ZT10aGlzLl9maW5kVGFibGVDb2RlKDEwLDEzLFhyKTtpZihlWzBdKXJldHVybiBlWzFdfWluZm8oImJhZCBibGFjayBjb2RlIik7dGhpcy5fZWF0Qml0cygxKTtyZXR1cm4gMX1fbG9va0JpdHMoZSl7bGV0IHQ7Zm9yKDt0aGlzLmlucHV0Qml0czxlOyl7aWYoLTE9PT0odD10aGlzLnNvdXJjZS5uZXh0KCkpKXJldHVybiAwPT09dGhpcy5pbnB1dEJpdHM/THI6dGhpcy5pbnB1dEJ1Zjw8ZS10aGlzLmlucHV0Qml0cyY2NTUzNT4+MTYtZTt0aGlzLmlucHV0QnVmPXRoaXMuaW5wdXRCdWY8PDh8dDt0aGlzLmlucHV0Qml0cys9OH1yZXR1cm4gdGhpcy5pbnB1dEJ1Zj4+dGhpcy5pbnB1dEJpdHMtZSY2NTUzNT4+MTYtZX1fZWF0Qml0cyhlKXsodGhpcy5pbnB1dEJpdHMtPWUpPDAmJih0aGlzLmlucHV0Qml0cz0wKX19Y2xhc3MgQ0NJVFRGYXhTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKHQpO3RoaXMuc3RyPWU7dGhpcy5kaWN0PWUuZGljdDtyIGluc3RhbmNlb2YgRGljdHx8KHI9RGljdC5lbXB0eSk7Y29uc3QgYT17bmV4dDooKT0+ZS5nZXRCeXRlKCl9O3RoaXMuY2NpdHRGYXhEZWNvZGVyPW5ldyBDQ0lUVEZheERlY29kZXIoYSx7SzpyLmdldCgiSyIpLEVuZE9mTGluZTpyLmdldCgiRW5kT2ZMaW5lIiksRW5jb2RlZEJ5dGVBbGlnbjpyLmdldCgiRW5jb2RlZEJ5dGVBbGlnbiIpLENvbHVtbnM6ci5nZXQoIkNvbHVtbnMiKSxSb3dzOnIuZ2V0KCJSb3dzIiksRW5kT2ZCbG9jazpyLmdldCgiRW5kT2ZCbG9jayIpLEJsYWNrSXMxOnIuZ2V0KCJCbGFja0lzMSIpfSl9cmVhZEJsb2NrKCl7Zm9yKDshdGhpcy5lb2Y7KXtjb25zdCBlPXRoaXMuY2NpdHRGYXhEZWNvZGVyLnJlYWROZXh0Q2hhcigpO2lmKC0xPT09ZSl7dGhpcy5lb2Y9ITA7cmV0dXJufXRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoKzEpO3RoaXMuYnVmZmVyW3RoaXMuYnVmZmVyTGVuZ3RoKytdPWV9fX1jb25zdCB6cj1uZXcgSW50MzJBcnJheShbMTYsMTcsMTgsMCw4LDcsOSw2LDEwLDUsMTEsNCwxMiwzLDEzLDIsMTQsMSwxNV0pLEdyPW5ldyBJbnQzMkFycmF5KFszLDQsNSw2LDcsOCw5LDEwLDY1NTQ3LDY1NTQ5LDY1NTUxLDY1NTUzLDEzMTA5MSwxMzEwOTUsMTMxMDk5LDEzMTEwMywxOTY2NDMsMTk2NjUxLDE5NjY1OSwxOTY2NjcsMjYyMjExLDI2MjIyNywyNjIyNDMsMjYyMjU5LDMyNzgxMSwzMjc4NDMsMzI3ODc1LDMyNzkwNywyNTgsMjU4LDI1OF0pLCRyPW5ldyBJbnQzMkFycmF5KFsxLDIsMyw0LDY1NTQxLDY1NTQzLDEzMTA4MSwxMzEwODUsMTk2NjI1LDE5NjYzMywyNjIxNzcsMjYyMTkzLDMyNzc0NSwzMjc3NzcsMzkzMzQ1LDM5MzQwOSw0NTkwMDksNDU5MTM3LDUyNDgwMSw1MjUwNTcsNTkwODQ5LDU5MTM2MSw2NTc0MDksNjU4NDMzLDcyNDk5Myw3MjcwNDEsNzk0NjI1LDc5ODcyMSw4NjgzNTMsODc2NTQ1XSksVnI9W25ldyBJbnQzMkFycmF5KFs0NTkwMDgsNTI0MzY4LDUyNDMwNCw1MjQ1NjgsNDU5MDI0LDUyNDQwMCw1MjQzMzYsNTkwMDE2LDQ1OTAxNiw1MjQzODQsNTI0MzIwLDU4OTk4NCw1MjQyODgsNTI0NDE2LDUyNDM1Miw1OTAwNDgsNDU5MDEyLDUyNDM3Niw1MjQzMTIsNTg5OTY4LDQ1OTAyOCw1MjQ0MDgsNTI0MzQ0LDU5MDAzMiw0NTkwMjAsNTI0MzkyLDUyNDMyOCw1OWU0LDUyNDI5Niw1MjQ0MjQsNTI0MzYwLDU5MDA2NCw0NTkwMTAsNTI0MzcyLDUyNDMwOCw1MjQ1NzIsNDU5MDI2LDUyNDQwNCw1MjQzNDAsNTkwMDI0LDQ1OTAxOCw1MjQzODgsNTI0MzI0LDU4OTk5Miw1MjQyOTIsNTI0NDIwLDUyNDM1Niw1OTAwNTYsNDU5MDE0LDUyNDM4MCw1MjQzMTYsNTg5OTc2LDQ1OTAzMCw1MjQ0MTIsNTI0MzQ4LDU5MDA0MCw0NTkwMjIsNTI0Mzk2LDUyNDMzMiw1OTAwMDgsNTI0MzAwLDUyNDQyOCw1MjQzNjQsNTkwMDcyLDQ1OTAwOSw1MjQzNzAsNTI0MzA2LDUyNDU3MCw0NTkwMjUsNTI0NDAyLDUyNDMzOCw1OTAwMjAsNDU5MDE3LDUyNDM4Niw1MjQzMjIsNTg5OTg4LDUyNDI5MCw1MjQ0MTgsNTI0MzU0LDU5MDA1Miw0NTkwMTMsNTI0Mzc4LDUyNDMxNCw1ODk5NzIsNDU5MDI5LDUyNDQxMCw1MjQzNDYsNTkwMDM2LDQ1OTAyMSw1MjQzOTQsNTI0MzMwLDU5MDAwNCw1MjQyOTgsNTI0NDI2LDUyNDM2Miw1OTAwNjgsNDU5MDExLDUyNDM3NCw1MjQzMTAsNTI0NTc0LDQ1OTAyNyw1MjQ0MDYsNTI0MzQyLDU5MDAyOCw0NTkwMTksNTI0MzkwLDUyNDMyNiw1ODk5OTYsNTI0Mjk0LDUyNDQyMiw1MjQzNTgsNTkwMDYwLDQ1OTAxNSw1MjQzODIsNTI0MzE4LDU4OTk4MCw0NTkwMzEsNTI0NDE0LDUyNDM1MCw1OTAwNDQsNDU5MDIzLDUyNDM5OCw1MjQzMzQsNTkwMDEyLDUyNDMwMiw1MjQ0MzAsNTI0MzY2LDU5MDA3Niw0NTkwMDgsNTI0MzY5LDUyNDMwNSw1MjQ1NjksNDU5MDI0LDUyNDQwMSw1MjQzMzcsNTkwMDE4LDQ1OTAxNiw1MjQzODUsNTI0MzIxLDU4OTk4Niw1MjQyODksNTI0NDE3LDUyNDM1Myw1OTAwNTAsNDU5MDEyLDUyNDM3Nyw1MjQzMTMsNTg5OTcwLDQ1OTAyOCw1MjQ0MDksNTI0MzQ1LDU5MDAzNCw0NTkwMjAsNTI0MzkzLDUyNDMyOSw1OTAwMDIsNTI0Mjk3LDUyNDQyNSw1MjQzNjEsNTkwMDY2LDQ1OTAxMCw1MjQzNzMsNTI0MzA5LDUyNDU3Myw0NTkwMjYsNTI0NDA1LDUyNDM0MSw1OTAwMjYsNDU5MDE4LDUyNDM4OSw1MjQzMjUsNTg5OTk0LDUyNDI5Myw1MjQ0MjEsNTI0MzU3LDU5MDA1OCw0NTkwMTQsNTI0MzgxLDUyNDMxNyw1ODk5NzgsNDU5MDMwLDUyNDQxMyw1MjQzNDksNTkwMDQyLDQ1OTAyMiw1MjQzOTcsNTI0MzMzLDU5MDAxMCw1MjQzMDEsNTI0NDI5LDUyNDM2NSw1OTAwNzQsNDU5MDA5LDUyNDM3MSw1MjQzMDcsNTI0NTcxLDQ1OTAyNSw1MjQ0MDMsNTI0MzM5LDU5MDAyMiw0NTkwMTcsNTI0Mzg3LDUyNDMyMyw1ODk5OTAsNTI0MjkxLDUyNDQxOSw1MjQzNTUsNTkwMDU0LDQ1OTAxMyw1MjQzNzksNTI0MzE1LDU4OTk3NCw0NTkwMjksNTI0NDExLDUyNDM0Nyw1OTAwMzgsNDU5MDIxLDUyNDM5NSw1MjQzMzEsNTkwMDA2LDUyNDI5OSw1MjQ0MjcsNTI0MzYzLDU5MDA3MCw0NTkwMTEsNTI0Mzc1LDUyNDMxMSw1MjQ1NzUsNDU5MDI3LDUyNDQwNyw1MjQzNDMsNTkwMDMwLDQ1OTAxOSw1MjQzOTEsNTI0MzI3LDU4OTk5OCw1MjQyOTUsNTI0NDIzLDUyNDM1OSw1OTAwNjIsNDU5MDE1LDUyNDM4Myw1MjQzMTksNTg5OTgyLDQ1OTAzMSw1MjQ0MTUsNTI0MzUxLDU5MDA0Niw0NTkwMjMsNTI0Mzk5LDUyNDMzNSw1OTAwMTQsNTI0MzAzLDUyNDQzMSw1MjQzNjcsNTkwMDc4LDQ1OTAwOCw1MjQzNjgsNTI0MzA0LDUyNDU2OCw0NTkwMjQsNTI0NDAwLDUyNDMzNiw1OTAwMTcsNDU5MDE2LDUyNDM4NCw1MjQzMjAsNTg5OTg1LDUyNDI4OCw1MjQ0MTYsNTI0MzUyLDU5MDA0OSw0NTkwMTIsNTI0Mzc2LDUyNDMxMiw1ODk5NjksNDU5MDI4LDUyNDQwOCw1MjQzNDQsNTkwMDMzLDQ1OTAyMCw1MjQzOTIsNTI0MzI4LDU5MDAwMSw1MjQyOTYsNTI0NDI0LDUyNDM2MCw1OTAwNjUsNDU5MDEwLDUyNDM3Miw1MjQzMDgsNTI0NTcyLDQ1OTAyNiw1MjQ0MDQsNTI0MzQwLDU5MDAyNSw0NTkwMTgsNTI0Mzg4LDUyNDMyNCw1ODk5OTMsNTI0MjkyLDUyNDQyMCw1MjQzNTYsNTkwMDU3LDQ1OTAxNCw1MjQzODAsNTI0MzE2LDU4OTk3Nyw0NTkwMzAsNTI0NDEyLDUyNDM0OCw1OTAwNDEsNDU5MDIyLDUyNDM5Niw1MjQzMzIsNTkwMDA5LDUyNDMwMCw1MjQ0MjgsNTI0MzY0LDU5MDA3Myw0NTkwMDksNTI0MzcwLDUyNDMwNiw1MjQ1NzAsNDU5MDI1LDUyNDQwMiw1MjQzMzgsNTkwMDIxLDQ1OTAxNyw1MjQzODYsNTI0MzIyLDU4OTk4OSw1MjQyOTAsNTI0NDE4LDUyNDM1NCw1OTAwNTMsNDU5MDEzLDUyNDM3OCw1MjQzMTQsNTg5OTczLDQ1OTAyOSw1MjQ0MTAsNTI0MzQ2LDU5MDAzNyw0NTkwMjEsNTI0Mzk0LDUyNDMzMCw1OTAwMDUsNTI0Mjk4LDUyNDQyNiw1MjQzNjIsNTkwMDY5LDQ1OTAxMSw1MjQzNzQsNTI0MzEwLDUyNDU3NCw0NTkwMjcsNTI0NDA2LDUyNDM0Miw1OTAwMjksNDU5MDE5LDUyNDM5MCw1MjQzMjYsNTg5OTk3LDUyNDI5NCw1MjQ0MjIsNTI0MzU4LDU5MDA2MSw0NTkwMTUsNTI0MzgyLDUyNDMxOCw1ODk5ODEsNDU5MDMxLDUyNDQxNCw1MjQzNTAsNTkwMDQ1LDQ1OTAyMyw1MjQzOTgsNTI0MzM0LDU5MDAxMyw1MjQzMDIsNTI0NDMwLDUyNDM2Niw1OTAwNzcsNDU5MDA4LDUyNDM2OSw1MjQzMDUsNTI0NTY5LDQ1OTAyNCw1MjQ0MDEsNTI0MzM3LDU5MDAxOSw0NTkwMTYsNTI0Mzg1LDUyNDMyMSw1ODk5ODcsNTI0Mjg5LDUyNDQxNyw1MjQzNTMsNTkwMDUxLDQ1OTAxMiw1MjQzNzcsNTI0MzEzLDU4OTk3MSw0NTkwMjgsNTI0NDA5LDUyNDM0NSw1OTAwMzUsNDU5MDIwLDUyNDM5Myw1MjQzMjksNTkwMDAzLDUyNDI5Nyw1MjQ0MjUsNTI0MzYxLDU5MDA2Nyw0NTkwMTAsNTI0MzczLDUyNDMwOSw1MjQ1NzMsNDU5MDI2LDUyNDQwNSw1MjQzNDEsNTkwMDI3LDQ1OTAxOCw1MjQzODksNTI0MzI1LDU4OTk5NSw1MjQyOTMsNTI0NDIxLDUyNDM1Nyw1OTAwNTksNDU5MDE0LDUyNDM4MSw1MjQzMTcsNTg5OTc5LDQ1OTAzMCw1MjQ0MTMsNTI0MzQ5LDU5MDA0Myw0NTkwMjIsNTI0Mzk3LDUyNDMzMyw1OTAwMTEsNTI0MzAxLDUyNDQyOSw1MjQzNjUsNTkwMDc1LDQ1OTAwOSw1MjQzNzEsNTI0MzA3LDUyNDU3MSw0NTkwMjUsNTI0NDAzLDUyNDMzOSw1OTAwMjMsNDU5MDE3LDUyNDM4Nyw1MjQzMjMsNTg5OTkxLDUyNDI5MSw1MjQ0MTksNTI0MzU1LDU5MDA1NSw0NTkwMTMsNTI0Mzc5LDUyNDMxNSw1ODk5NzUsNDU5MDI5LDUyNDQxMSw1MjQzNDcsNTkwMDM5LDQ1OTAyMSw1MjQzOTUsNTI0MzMxLDU5MDAwNyw1MjQyOTksNTI0NDI3LDUyNDM2Myw1OTAwNzEsNDU5MDExLDUyNDM3NSw1MjQzMTEsNTI0NTc1LDQ1OTAyNyw1MjQ0MDcsNTI0MzQzLDU5MDAzMSw0NTkwMTksNTI0MzkxLDUyNDMyNyw1ODk5OTksNTI0Mjk1LDUyNDQyMyw1MjQzNTksNTkwMDYzLDQ1OTAxNSw1MjQzODMsNTI0MzE5LDU4OTk4Myw0NTkwMzEsNTI0NDE1LDUyNDM1MSw1OTAwNDcsNDU5MDIzLDUyNDM5OSw1MjQzMzUsNTkwMDE1LDUyNDMwMyw1MjQ0MzEsNTI0MzY3LDU5MDA3OV0pLDldLEtyPVtuZXcgSW50MzJBcnJheShbMzI3NjgwLDMyNzY5NiwzMjc2ODgsMzI3NzA0LDMyNzY4NCwzMjc3MDAsMzI3NjkyLDMyNzcwOCwzMjc2ODIsMzI3Njk4LDMyNzY5MCwzMjc3MDYsMzI3Njg2LDMyNzcwMiwzMjc2OTQsMCwzMjc2ODEsMzI3Njk3LDMyNzY4OSwzMjc3MDUsMzI3Njg1LDMyNzcwMSwzMjc2OTMsMzI3NzA5LDMyNzY4MywzMjc2OTksMzI3NjkxLDMyNzcwNywzMjc2ODcsMzI3NzAzLDMyNzY5NSwwXSksNV07Y2xhc3MgRmxhdGVTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17Y29uc3RydWN0b3IoZSx0KXtzdXBlcih0KTt0aGlzLnN0cj1lO3RoaXMuZGljdD1lLmRpY3Q7Y29uc3Qgcj1lLmdldEJ5dGUoKSxhPWUuZ2V0Qnl0ZSgpO2lmKC0xPT09cnx8LTE9PT1hKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtOiAke3J9LCAke2F9YCk7aWYoOCE9KDE1JnIpKXRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBjb21wcmVzc2lvbiBtZXRob2QgaW4gZmxhdGUgc3RyZWFtOiAke3J9LCAke2F9YCk7aWYoKChyPDw4KSthKSUzMSE9MCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEJhZCBGQ0hFQ0sgaW4gZmxhdGUgc3RyZWFtOiAke3J9LCAke2F9YCk7aWYoMzImYSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEZESUNUIGJpdCBzZXQgaW4gZmxhdGUgc3RyZWFtOiAke3J9LCAke2F9YCk7dGhpcy5jb2RlU2l6ZT0wO3RoaXMuY29kZUJ1Zj0wfWFzeW5jIGdldEltYWdlRGF0YShlLHQpe2NvbnN0IHI9YXdhaXQgdGhpcy5hc3luY0dldEJ5dGVzKCk7cmV0dXJuIHI/ci5sZW5ndGg8PWU/cjpyLnN1YmFycmF5KDAsZSk6dGhpcy5nZXRCeXRlcyhlKX1hc3luYyBhc3luY0dldEJ5dGVzKCl7dGhpcy5zdHIucmVzZXQoKTtjb25zdCBlPXRoaXMuc3RyLmdldEJ5dGVzKCk7dHJ5e2NvbnN0e3JlYWRhYmxlOnQsd3JpdGFibGU6cn09bmV3IERlY29tcHJlc3Npb25TdHJlYW0oImRlZmxhdGUiKSxhPXIuZ2V0V3JpdGVyKCk7YXdhaXQgYS5yZWFkeTthLndyaXRlKGUpLnRoZW4oYXN5bmMoKT0+e2F3YWl0IGEucmVhZHk7YXdhaXQgYS5jbG9zZSgpfSkuY2F0Y2goKCk9Pnt9KTtjb25zdCBuPVtdO2xldCBpPTA7Zm9yIGF3YWl0KGNvbnN0IGUgb2YgdCl7bi5wdXNoKGUpO2krPWUuYnl0ZUxlbmd0aH1jb25zdCBzPW5ldyBVaW50OEFycmF5KGkpO2xldCBvPTA7Zm9yKGNvbnN0IGUgb2Ygbil7cy5zZXQoZSxvKTtvKz1lLmJ5dGVMZW5ndGh9cmV0dXJuIHN9Y2F0Y2h7dGhpcy5zdHI9bmV3IFN0cmVhbShlLDIsZS5sZW5ndGgsdGhpcy5zdHIuZGljdCk7dGhpcy5yZXNldCgpO3JldHVybiBudWxsfX1nZXQgaXNBc3luYygpe3JldHVybiEwfWdldEJpdHMoZSl7Y29uc3QgdD10aGlzLnN0cjtsZXQgcixhPXRoaXMuY29kZVNpemUsbj10aGlzLmNvZGVCdWY7Zm9yKDthPGU7KXtpZigtMT09PShyPXQuZ2V0Qnl0ZSgpKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkJhZCBlbmNvZGluZyBpbiBmbGF0ZSBzdHJlYW0iKTtufD1yPDxhO2ErPTh9cj1uJigxPDxlKS0xO3RoaXMuY29kZUJ1Zj1uPj5lO3RoaXMuY29kZVNpemU9YS09ZTtyZXR1cm4gcn1nZXRDb2RlKGUpe2NvbnN0IHQ9dGhpcy5zdHIscj1lWzBdLGE9ZVsxXTtsZXQgbixpPXRoaXMuY29kZVNpemUscz10aGlzLmNvZGVCdWY7Zm9yKDtpPGEmJi0xIT09KG49dC5nZXRCeXRlKCkpOyl7c3w9bjw8aTtpKz04fWNvbnN0IG89cltzJigxPDxhKS0xXSxjPW8+PjE2LGw9NjU1MzUmbztpZihjPDF8fGk8Yyl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkJhZCBlbmNvZGluZyBpbiBmbGF0ZSBzdHJlYW0iKTt0aGlzLmNvZGVCdWY9cz4+Yzt0aGlzLmNvZGVTaXplPWktYztyZXR1cm4gbH1nZW5lcmF0ZUh1ZmZtYW5UYWJsZShlKXtjb25zdCB0PWUubGVuZ3RoO2xldCByLGE9MDtmb3Iocj0wO3I8dDsrK3IpZVtyXT5hJiYoYT1lW3JdKTtjb25zdCBuPTE8PGEsaT1uZXcgSW50MzJBcnJheShuKTtmb3IobGV0IHM9MSxvPTAsYz0yO3M8PWE7KytzLG88PD0xLGM8PD0xKWZvcihsZXQgYT0wO2E8dDsrK2EpaWYoZVthXT09PXMpe2xldCBlPTAsdD1vO2ZvcihyPTA7cjxzOysrcil7ZT1lPDwxfDEmdDt0Pj49MX1mb3Iocj1lO3I8bjtyKz1jKWlbcl09czw8MTZ8YTsrK299cmV0dXJuW2ksYV19I3EoZSl7aW5mbyhlKTt0aGlzLmVvZj0hMH1yZWFkQmxvY2soKXtsZXQgZSx0LHI7Y29uc3QgYT10aGlzLnN0cjt0cnl7dD10aGlzLmdldEJpdHMoMyl9Y2F0Y2goZSl7dGhpcy4jcShlLm1lc3NhZ2UpO3JldHVybn0xJnQmJih0aGlzLmVvZj0hMCk7dD4+PTE7aWYoMD09PXQpe2xldCB0O2lmKC0xPT09KHQ9YS5nZXRCeXRlKCkpKXt0aGlzLiNxKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpO3JldHVybn1sZXQgcj10O2lmKC0xPT09KHQ9YS5nZXRCeXRlKCkpKXt0aGlzLiNxKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpO3JldHVybn1yfD10PDw4O2lmKC0xPT09KHQ9YS5nZXRCeXRlKCkpKXt0aGlzLiNxKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpO3JldHVybn1sZXQgbj10O2lmKC0xPT09KHQ9YS5nZXRCeXRlKCkpKXt0aGlzLiNxKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpO3JldHVybn1ufD10PDw4O2lmKG4hPT0oNjU1MzUmfnIpJiYoMCE9PXJ8fDAhPT1uKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkJhZCB1bmNvbXByZXNzZWQgYmxvY2sgbGVuZ3RoIGluIGZsYXRlIHN0cmVhbSIpO3RoaXMuY29kZUJ1Zj0wO3RoaXMuY29kZVNpemU9MDtjb25zdCBpPXRoaXMuYnVmZmVyTGVuZ3RoLHM9aStyO2U9dGhpcy5lbnN1cmVCdWZmZXIocyk7dGhpcy5idWZmZXJMZW5ndGg9cztpZigwPT09ciktMT09PWEucGVla0J5dGUoKSYmKHRoaXMuZW9mPSEwKTtlbHNle2NvbnN0IHQ9YS5nZXRCeXRlcyhyKTtlLnNldCh0LGkpO3QubGVuZ3RoPHImJih0aGlzLmVvZj0hMCl9cmV0dXJufWxldCBuLGk7aWYoMT09PXQpe249VnI7aT1Lcn1lbHNle2lmKDIhPT10KXRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biBibG9jayB0eXBlIGluIGZsYXRlIHN0cmVhbSIpO3tjb25zdCBlPXRoaXMuZ2V0Qml0cyg1KSsyNTcsdD10aGlzLmdldEJpdHMoNSkrMSxhPXRoaXMuZ2V0Qml0cyg0KSs0LHM9bmV3IFVpbnQ4QXJyYXkoenIubGVuZ3RoKTtsZXQgbztmb3Iobz0wO288YTsrK28pc1t6cltvXV09dGhpcy5nZXRCaXRzKDMpO2NvbnN0IGM9dGhpcy5nZW5lcmF0ZUh1ZmZtYW5UYWJsZShzKTtyPTA7bz0wO2NvbnN0IGw9ZSt0LGg9bmV3IFVpbnQ4QXJyYXkobCk7bGV0IHUsZCxmO2Zvcig7bzxsOyl7Y29uc3QgZT10aGlzLmdldENvZGUoYyk7aWYoMTY9PT1lKXt1PTI7ZD0zO2Y9cn1lbHNlIGlmKDE3PT09ZSl7dT0zO2Q9MztmPXI9MH1lbHNle2lmKDE4IT09ZSl7aFtvKytdPXI9ZTtjb250aW51ZX11PTc7ZD0xMTtmPXI9MH1sZXQgdD10aGlzLmdldEJpdHModSkrZDtmb3IoO3QtLSA+MDspaFtvKytdPWZ9bj10aGlzLmdlbmVyYXRlSHVmZm1hblRhYmxlKGguc3ViYXJyYXkoMCxlKSk7aT10aGlzLmdlbmVyYXRlSHVmZm1hblRhYmxlKGguc3ViYXJyYXkoZSxsKSl9fWU9dGhpcy5idWZmZXI7bGV0IHM9ZT9lLmxlbmd0aDowLG89dGhpcy5idWZmZXJMZW5ndGg7Zm9yKDs7KXtsZXQgdD10aGlzLmdldENvZGUobik7aWYodDwyNTYpe2lmKG8rMT49cyl7ZT10aGlzLmVuc3VyZUJ1ZmZlcihvKzEpO3M9ZS5sZW5ndGh9ZVtvKytdPXQ7Y29udGludWV9aWYoMjU2PT09dCl7dGhpcy5idWZmZXJMZW5ndGg9bztyZXR1cm59dC09MjU3O3Q9R3JbdF07bGV0IGE9dD4+MTY7YT4wJiYoYT10aGlzLmdldEJpdHMoYSkpO3I9KDY1NTM1JnQpK2E7dD10aGlzLmdldENvZGUoaSk7dD0kclt0XTthPXQ+PjE2O2E+MCYmKGE9dGhpcy5nZXRCaXRzKGEpKTtjb25zdCBjPSg2NTUzNSZ0KSthO2lmKG8rcj49cyl7ZT10aGlzLmVuc3VyZUJ1ZmZlcihvK3IpO3M9ZS5sZW5ndGh9Zm9yKGxldCB0PTA7dDxyOysrdCwrK28pZVtvXT1lW28tY119fX1jb25zdCBKcj1be3FlOjIyMDE3LG5tcHM6MSxubHBzOjEsc3dpdGNoRmxhZzoxfSx7cWU6MTMzMTMsbm1wczoyLG5scHM6Nixzd2l0Y2hGbGFnOjB9LHtxZTo2MTQ1LG5tcHM6MyxubHBzOjksc3dpdGNoRmxhZzowfSx7cWU6Mjc1MyxubXBzOjQsbmxwczoxMixzd2l0Y2hGbGFnOjB9LHtxZToxMzEzLG5tcHM6NSxubHBzOjI5LHN3aXRjaEZsYWc6MH0se3FlOjU0NSxubXBzOjM4LG5scHM6MzMsc3dpdGNoRmxhZzowfSx7cWU6MjIwMTcsbm1wczo3LG5scHM6Nixzd2l0Y2hGbGFnOjF9LHtxZToyMTUwNSxubXBzOjgsbmxwczoxNCxzd2l0Y2hGbGFnOjB9LHtxZToxODQzMyxubXBzOjksbmxwczoxNCxzd2l0Y2hGbGFnOjB9LHtxZToxNDMzNyxubXBzOjEwLG5scHM6MTQsc3dpdGNoRmxhZzowfSx7cWU6MTIyODksbm1wczoxMSxubHBzOjE3LHN3aXRjaEZsYWc6MH0se3FlOjkyMTcsbm1wczoxMixubHBzOjE4LHN3aXRjaEZsYWc6MH0se3FlOjcxNjksbm1wczoxMyxubHBzOjIwLHN3aXRjaEZsYWc6MH0se3FlOjU2MzMsbm1wczoyOSxubHBzOjIxLHN3aXRjaEZsYWc6MH0se3FlOjIyMDE3LG5tcHM6MTUsbmxwczoxNCxzd2l0Y2hGbGFnOjF9LHtxZToyMTUwNSxubXBzOjE2LG5scHM6MTQsc3dpdGNoRmxhZzowfSx7cWU6MjA3Mzcsbm1wczoxNyxubHBzOjE1LHN3aXRjaEZsYWc6MH0se3FlOjE4NDMzLG5tcHM6MTgsbmxwczoxNixzd2l0Y2hGbGFnOjB9LHtxZToxNDMzNyxubXBzOjE5LG5scHM6MTcsc3dpdGNoRmxhZzowfSx7cWU6MTMzMTMsbm1wczoyMCxubHBzOjE4LHN3aXRjaEZsYWc6MH0se3FlOjEyMjg5LG5tcHM6MjEsbmxwczoxOSxzd2l0Y2hGbGFnOjB9LHtxZToxMDI0MSxubXBzOjIyLG5scHM6MTksc3dpdGNoRmxhZzowfSx7cWU6OTIxNyxubXBzOjIzLG5scHM6MjAsc3dpdGNoRmxhZzowfSx7cWU6ODcwNSxubXBzOjI0LG5scHM6MjEsc3dpdGNoRmxhZzowfSx7cWU6NzE2OSxubXBzOjI1LG5scHM6MjIsc3dpdGNoRmxhZzowfSx7cWU6NjE0NSxubXBzOjI2LG5scHM6MjMsc3dpdGNoRmxhZzowfSx7cWU6NTYzMyxubXBzOjI3LG5scHM6MjQsc3dpdGNoRmxhZzowfSx7cWU6NTEyMSxubXBzOjI4LG5scHM6MjUsc3dpdGNoRmxhZzowfSx7cWU6NDYwOSxubXBzOjI5LG5scHM6MjYsc3dpdGNoRmxhZzowfSx7cWU6NDM1MyxubXBzOjMwLG5scHM6Mjcsc3dpdGNoRmxhZzowfSx7cWU6Mjc1MyxubXBzOjMxLG5scHM6Mjgsc3dpdGNoRmxhZzowfSx7cWU6MjQ5NyxubXBzOjMyLG5scHM6Mjksc3dpdGNoRmxhZzowfSx7cWU6MjIwOSxubXBzOjMzLG5scHM6MzAsc3dpdGNoRmxhZzowfSx7cWU6MTMxMyxubXBzOjM0LG5scHM6MzEsc3dpdGNoRmxhZzowfSx7cWU6MTA4OSxubXBzOjM1LG5scHM6MzIsc3dpdGNoRmxhZzowfSx7cWU6NjczLG5tcHM6MzYsbmxwczozMyxzd2l0Y2hGbGFnOjB9LHtxZTo1NDUsbm1wczozNyxubHBzOjM0LHN3aXRjaEZsYWc6MH0se3FlOjMyMSxubXBzOjM4LG5scHM6MzUsc3dpdGNoRmxhZzowfSx7cWU6MjczLG5tcHM6MzksbmxwczozNixzd2l0Y2hGbGFnOjB9LHtxZToxMzMsbm1wczo0MCxubHBzOjM3LHN3aXRjaEZsYWc6MH0se3FlOjczLG5tcHM6NDEsbmxwczozOCxzd2l0Y2hGbGFnOjB9LHtxZTozNyxubXBzOjQyLG5scHM6Mzksc3dpdGNoRmxhZzowfSx7cWU6MjEsbm1wczo0MyxubHBzOjQwLHN3aXRjaEZsYWc6MH0se3FlOjksbm1wczo0NCxubHBzOjQxLHN3aXRjaEZsYWc6MH0se3FlOjUsbm1wczo0NSxubHBzOjQyLHN3aXRjaEZsYWc6MH0se3FlOjEsbm1wczo0NSxubHBzOjQzLHN3aXRjaEZsYWc6MH0se3FlOjIyMDE3LG5tcHM6NDYsbmxwczo0Nixzd2l0Y2hGbGFnOjB9XTtjbGFzcyBBcml0aG1ldGljRGVjb2Rlcntjb25zdHJ1Y3RvcihlLHQscil7dGhpcy5kYXRhPWU7dGhpcy5icD10O3RoaXMuZGF0YUVuZD1yO3RoaXMuY2hpZ2g9ZVt0XTt0aGlzLmNsb3c9MDt0aGlzLmJ5dGVJbigpO3RoaXMuY2hpZ2g9dGhpcy5jaGlnaDw8NyY2NTUzNXx0aGlzLmNsb3c+PjkmMTI3O3RoaXMuY2xvdz10aGlzLmNsb3c8PDcmNjU1MzU7dGhpcy5jdC09Nzt0aGlzLmE9MzI3Njh9Ynl0ZUluKCl7Y29uc3QgZT10aGlzLmRhdGE7bGV0IHQ9dGhpcy5icDtpZigyNTU9PT1lW3RdKWlmKGVbdCsxXT4xNDMpe3RoaXMuY2xvdys9NjUyODA7dGhpcy5jdD04fWVsc2V7dCsrO3RoaXMuY2xvdys9ZVt0XTw8OTt0aGlzLmN0PTc7dGhpcy5icD10fWVsc2V7dCsrO3RoaXMuY2xvdys9dDx0aGlzLmRhdGFFbmQ/ZVt0XTw8ODo2NTI4MDt0aGlzLmN0PTg7dGhpcy5icD10fWlmKHRoaXMuY2xvdz42NTUzNSl7dGhpcy5jaGlnaCs9dGhpcy5jbG93Pj4xNjt0aGlzLmNsb3cmPTY1NTM1fX1yZWFkQml0KGUsdCl7bGV0IHI9ZVt0XT4+MSxhPTEmZVt0XTtjb25zdCBuPUpyW3JdLGk9bi5xZTtsZXQgcyxvPXRoaXMuYS1pO2lmKHRoaXMuY2hpZ2g8aSlpZihvPGkpe289aTtzPWE7cj1uLm5tcHN9ZWxzZXtvPWk7cz0xXmE7MT09PW4uc3dpdGNoRmxhZyYmKGE9cyk7cj1uLm5scHN9ZWxzZXt0aGlzLmNoaWdoLT1pO2lmKDMyNzY4Jm8pe3RoaXMuYT1vO3JldHVybiBhfWlmKG88aSl7cz0xXmE7MT09PW4uc3dpdGNoRmxhZyYmKGE9cyk7cj1uLm5scHN9ZWxzZXtzPWE7cj1uLm5tcHN9fWRvezA9PT10aGlzLmN0JiZ0aGlzLmJ5dGVJbigpO288PD0xO3RoaXMuY2hpZ2g9dGhpcy5jaGlnaDw8MSY2NTUzNXx0aGlzLmNsb3c+PjE1JjE7dGhpcy5jbG93PXRoaXMuY2xvdzw8MSY2NTUzNTt0aGlzLmN0LS19d2hpbGUoISgzMjc2OCZvKSk7dGhpcy5hPW87ZVt0XT1yPDwxfGE7cmV0dXJuIHN9fWNsYXNzIEpiaWcyRXJyb3IgZXh0ZW5kcyBlcntjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJKYmlnMkVycm9yIil9fWNsYXNzIENvbnRleHRDYWNoZXtnZXRDb250ZXh0cyhlKXtyZXR1cm4gZSBpbiB0aGlzP3RoaXNbZV06dGhpc1tlXT1uZXcgSW50OEFycmF5KDY1NTM2KX19Y2xhc3MgRGVjb2RpbmdDb250ZXh0e2NvbnN0cnVjdG9yKGUsdCxyKXt0aGlzLmRhdGE9ZTt0aGlzLnN0YXJ0PXQ7dGhpcy5lbmQ9cn1nZXQgZGVjb2Rlcigpe3JldHVybiBzaGFkb3codGhpcywiZGVjb2RlciIsbmV3IEFyaXRobWV0aWNEZWNvZGVyKHRoaXMuZGF0YSx0aGlzLnN0YXJ0LHRoaXMuZW5kKSl9Z2V0IGNvbnRleHRDYWNoZSgpe3JldHVybiBzaGFkb3codGhpcywiY29udGV4dENhY2hlIixuZXcgQ29udGV4dENhY2hlKX19ZnVuY3Rpb24gZGVjb2RlSW50ZWdlcihlLHQscil7Y29uc3QgYT1lLmdldENvbnRleHRzKHQpO2xldCBuPTE7ZnVuY3Rpb24gcmVhZEJpdHMoZSl7bGV0IHQ9MDtmb3IobGV0IGk9MDtpPGU7aSsrKXtjb25zdCBlPXIucmVhZEJpdChhLG4pO249bjwyNTY/bjw8MXxlOjUxMSYobjw8MXxlKXwyNTY7dD10PDwxfGV9cmV0dXJuIHQ+Pj4wfWNvbnN0IGk9cmVhZEJpdHMoMSkscz1yZWFkQml0cygxKT9yZWFkQml0cygxKT9yZWFkQml0cygxKT9yZWFkQml0cygxKT9yZWFkQml0cygxKT9yZWFkQml0cygzMikrNDQzNjpyZWFkQml0cygxMikrMzQwOnJlYWRCaXRzKDgpKzg0OnJlYWRCaXRzKDYpKzIwOnJlYWRCaXRzKDQpKzQ6cmVhZEJpdHMoMik7bGV0IG87MD09PWk/bz1zOnM+MCYmKG89LXMpO3JldHVybiBvPj0tMjE0NzQ4MzY0OCYmbzw9ZHI/bzpudWxsfWZ1bmN0aW9uIGRlY29kZUlBSUQoZSx0LHIpe2NvbnN0IGE9ZS5nZXRDb250ZXh0cygiSUFJRCIpO2xldCBuPTE7Zm9yKGxldCBlPTA7ZTxyO2UrKyl7bj1uPDwxfHQucmVhZEJpdChhLG4pfXJldHVybiByPDMxP24mKDE8PHIpLTE6MjE0NzQ4MzY0NyZufWNvbnN0IFlyPVsiU3ltYm9sRGljdGlvbmFyeSIsbnVsbCxudWxsLG51bGwsIkludGVybWVkaWF0ZVRleHRSZWdpb24iLG51bGwsIkltbWVkaWF0ZVRleHRSZWdpb24iLCJJbW1lZGlhdGVMb3NzbGVzc1RleHRSZWdpb24iLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCwiUGF0dGVybkRpY3Rpb25hcnkiLG51bGwsbnVsbCxudWxsLCJJbnRlcm1lZGlhdGVIYWxmdG9uZVJlZ2lvbiIsbnVsbCwiSW1tZWRpYXRlSGFsZnRvbmVSZWdpb24iLCJJbW1lZGlhdGVMb3NzbGVzc0hhbGZ0b25lUmVnaW9uIixudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCwiSW50ZXJtZWRpYXRlR2VuZXJpY1JlZ2lvbiIsbnVsbCwiSW1tZWRpYXRlR2VuZXJpY1JlZ2lvbiIsIkltbWVkaWF0ZUxvc3NsZXNzR2VuZXJpY1JlZ2lvbiIsIkludGVybWVkaWF0ZUdlbmVyaWNSZWZpbmVtZW50UmVnaW9uIixudWxsLCJJbW1lZGlhdGVHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsIkltbWVkaWF0ZUxvc3NsZXNzR2VuZXJpY1JlZmluZW1lbnRSZWdpb24iLG51bGwsbnVsbCxudWxsLG51bGwsIlBhZ2VJbmZvcm1hdGlvbiIsIkVuZE9mUGFnZSIsIkVuZE9mU3RyaXBlIiwiRW5kT2ZGaWxlIiwiUHJvZmlsZXMiLCJUYWJsZXMiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCwiRXh0ZW5zaW9uIl0sWnI9W1t7eDotMSx5Oi0yfSx7eDowLHk6LTJ9LHt4OjEseTotMn0se3g6LTIseTotMX0se3g6LTEseTotMX0se3g6MCx5Oi0xfSx7eDoxLHk6LTF9LHt4OjIseTotMX0se3g6LTQseTowfSx7eDotMyx5OjB9LHt4Oi0yLHk6MH0se3g6LTEseTowfV0sW3t4Oi0xLHk6LTJ9LHt4OjAseTotMn0se3g6MSx5Oi0yfSx7eDoyLHk6LTJ9LHt4Oi0yLHk6LTF9LHt4Oi0xLHk6LTF9LHt4OjAseTotMX0se3g6MSx5Oi0xfSx7eDoyLHk6LTF9LHt4Oi0zLHk6MH0se3g6LTIseTowfSx7eDotMSx5OjB9XSxbe3g6LTEseTotMn0se3g6MCx5Oi0yfSx7eDoxLHk6LTJ9LHt4Oi0yLHk6LTF9LHt4Oi0xLHk6LTF9LHt4OjAseTotMX0se3g6MSx5Oi0xfSx7eDotMix5OjB9LHt4Oi0xLHk6MH1dLFt7eDotMyx5Oi0xfSx7eDotMix5Oi0xfSx7eDotMSx5Oi0xfSx7eDowLHk6LTF9LHt4OjEseTotMX0se3g6LTQseTowfSx7eDotMyx5OjB9LHt4Oi0yLHk6MH0se3g6LTEseTowfV1dLFFyPVt7Y29kaW5nOlt7eDowLHk6LTF9LHt4OjEseTotMX0se3g6LTEseTowfV0scmVmZXJlbmNlOlt7eDowLHk6LTF9LHt4OjEseTotMX0se3g6LTEseTowfSx7eDowLHk6MH0se3g6MSx5OjB9LHt4Oi0xLHk6MX0se3g6MCx5OjF9LHt4OjEseToxfV19LHtjb2Rpbmc6W3t4Oi0xLHk6LTF9LHt4OjAseTotMX0se3g6MSx5Oi0xfSx7eDotMSx5OjB9XSxyZWZlcmVuY2U6W3t4OjAseTotMX0se3g6LTEseTowfSx7eDowLHk6MH0se3g6MSx5OjB9LHt4OjAseToxfSx7eDoxLHk6MX1dfV0sZWE9WzM5NzE3LDE5NDEsMjI5LDQwNV0sdGE9WzMyLDhdO2Z1bmN0aW9uIGRlY29kZUJpdG1hcChlLHQscixhLG4saSxzLG8pe2lmKGUpe3JldHVybiBkZWNvZGVNTVJCaXRtYXAobmV3IFJlYWRlcihvLmRhdGEsby5zdGFydCxvLmVuZCksdCxyLCExKX1pZigwPT09YSYmIWkmJiFuJiY0PT09cy5sZW5ndGgmJjM9PT1zWzBdLngmJi0xPT09c1swXS55JiYtMz09PXNbMV0ueCYmLTE9PT1zWzFdLnkmJjI9PT1zWzJdLngmJi0yPT09c1syXS55JiYtMj09PXNbM10ueCYmLTI9PT1zWzNdLnkpcmV0dXJuIGZ1bmN0aW9uIGRlY29kZUJpdG1hcFRlbXBsYXRlMChlLHQscil7Y29uc3QgYT1yLmRlY29kZXIsbj1yLmNvbnRleHRDYWNoZS5nZXRDb250ZXh0cygiR0IiKSxpPVtdO2xldCBzLG8sYyxsLGgsdSxkO2ZvcihvPTA7bzx0O28rKyl7aD1pW29dPW5ldyBVaW50OEFycmF5KGUpO3U9bzwxP2g6aVtvLTFdO2Q9bzwyP2g6aVtvLTJdO3M9ZFswXTw8MTN8ZFsxXTw8MTJ8ZFsyXTw8MTF8dVswXTw8N3x1WzFdPDw2fHVbMl08PDV8dVszXTw8NDtmb3IoYz0wO2M8ZTtjKyspe2hbY109bD1hLnJlYWRCaXQobixzKTtzPSgzMTczNSZzKTw8MXwoYyszPGU/ZFtjKzNdPDwxMTowKXwoYys0PGU/dVtjKzRdPDw0OjApfGx9fXJldHVybiBpfSh0LHIsbyk7Y29uc3QgYz0hIWksbD1aclthXS5jb25jYXQocyk7bC5zb3J0KChlLHQpPT5lLnktdC55fHxlLngtdC54KTtjb25zdCBoPWwubGVuZ3RoLHU9bmV3IEludDhBcnJheShoKSxkPW5ldyBJbnQ4QXJyYXkoaCksZj1bXTtsZXQgZyxwLG09MCxiPTAseT0wLHc9MDtmb3IocD0wO3A8aDtwKyspe3VbcF09bFtwXS54O2RbcF09bFtwXS55O2I9TWF0aC5taW4oYixsW3BdLngpO3k9TWF0aC5tYXgoeSxsW3BdLngpO3c9TWF0aC5taW4odyxsW3BdLnkpO3A8aC0xJiZsW3BdLnk9PT1sW3ArMV0ueSYmbFtwXS54PT09bFtwKzFdLngtMT9tfD0xPDxoLTEtcDpmLnB1c2gocCl9Y29uc3QgeD1mLmxlbmd0aCxTPW5ldyBJbnQ4QXJyYXkoeCksaz1uZXcgSW50OEFycmF5KHgpLEM9bmV3IFVpbnQxNkFycmF5KHgpO2ZvcihnPTA7Zzx4O2crKyl7cD1mW2ddO1NbZ109bFtwXS54O2tbZ109bFtwXS55O0NbZ109MTw8aC0xLXB9Y29uc3Qgdj0tYixUPS13LE89dC15LE09ZWFbYV07bGV0IEQ9bmV3IFVpbnQ4QXJyYXkodCk7Y29uc3QgUj1bXSxFPW8uZGVjb2RlcixOPW8uY29udGV4dENhY2hlLmdldENvbnRleHRzKCJHQiIpO2xldCBfLEwsaixVLHEsWD0wLEg9MDtmb3IobGV0IGU9MDtlPHI7ZSsrKXtpZihuKXtYXj1FLnJlYWRCaXQoTixNKTtpZihYKXtSLnB1c2goRCk7Y29udGludWV9fUQ9bmV3IFVpbnQ4QXJyYXkoRCk7Ui5wdXNoKEQpO2ZvcihfPTA7Xzx0O18rKyl7aWYoYyYmaVtlXVtfXSl7RFtfXT0wO2NvbnRpbnVlfWlmKF8+PXYmJl88TyYmZT49VCl7SD1IPDwxJm07Zm9yKHA9MDtwPHg7cCsrKXtMPWUra1twXTtqPV8rU1twXTtVPVJbTF1bal07aWYoVSl7VT1DW3BdO0h8PVV9fX1lbHNle0g9MDtxPWgtMTtmb3IocD0wO3A8aDtwKysscS0tKXtqPV8rdVtwXTtpZihqPj0wJiZqPHQpe0w9ZStkW3BdO2lmKEw+PTApe1U9UltMXVtqXTtVJiYoSHw9VTw8cSl9fX19Y29uc3Qgcj1FLnJlYWRCaXQoTixIKTtEW19dPXJ9fXJldHVybiBSfWZ1bmN0aW9uIGRlY29kZVJlZmluZW1lbnQoZSx0LHIsYSxuLGkscyxvLGMpe2xldCBsPVFyW3JdLmNvZGluZzswPT09ciYmKGw9bC5jb25jYXQoW29bMF1dKSk7Y29uc3QgaD1sLmxlbmd0aCx1PW5ldyBJbnQzMkFycmF5KGgpLGQ9bmV3IEludDMyQXJyYXkoaCk7bGV0IGY7Zm9yKGY9MDtmPGg7ZisrKXt1W2ZdPWxbZl0ueDtkW2ZdPWxbZl0ueX1sZXQgZz1RcltyXS5yZWZlcmVuY2U7MD09PXImJihnPWcuY29uY2F0KFtvWzFdXSkpO2NvbnN0IHA9Zy5sZW5ndGgsbT1uZXcgSW50MzJBcnJheShwKSxiPW5ldyBJbnQzMkFycmF5KHApO2ZvcihmPTA7ZjxwO2YrKyl7bVtmXT1nW2ZdLng7YltmXT1nW2ZdLnl9Y29uc3QgeT1hWzBdLmxlbmd0aCx3PWEubGVuZ3RoLHg9dGFbcl0sUz1bXSxrPWMuZGVjb2RlcixDPWMuY29udGV4dENhY2hlLmdldENvbnRleHRzKCJHUiIpO2xldCB2PTA7Zm9yKGxldCByPTA7cjx0O3IrKyl7aWYocyl7dl49ay5yZWFkQml0KEMseCk7aWYodil0aHJvdyBuZXcgSmJpZzJFcnJvcigicHJlZGljdGlvbiBpcyBub3Qgc3VwcG9ydGVkIil9Y29uc3QgdD1uZXcgVWludDhBcnJheShlKTtTLnB1c2godCk7Zm9yKGxldCBzPTA7czxlO3MrKyl7bGV0IG8sYyxsPTA7Zm9yKGY9MDtmPGg7ZisrKXtvPXIrZFtmXTtjPXMrdVtmXTtvPDB8fGM8MHx8Yz49ZT9sPDw9MTpsPWw8PDF8U1tvXVtjXX1mb3IoZj0wO2Y8cDtmKyspe289citiW2ZdLWk7Yz1zK21bZl0tbjtvPDB8fG8+PXd8fGM8MHx8Yz49eT9sPDw9MTpsPWw8PDF8YVtvXVtjXX1jb25zdCBnPWsucmVhZEJpdChDLGwpO3Rbc109Z319cmV0dXJuIFN9ZnVuY3Rpb24gZGVjb2RlVGV4dFJlZ2lvbihlLHQscixhLG4saSxzLG8sYyxsLGgsdSxkLGYsZyxwLG0sYix5KXtpZihlJiZ0KXRocm93IG5ldyBKYmlnMkVycm9yKCJyZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7Y29uc3Qgdz1bXTtsZXQgeCxTO2Zvcih4PTA7eDxhO3grKyl7Uz1uZXcgVWludDhBcnJheShyKTtuJiZTLmZpbGwobik7dy5wdXNoKFMpfWNvbnN0IGs9bS5kZWNvZGVyLEM9bS5jb250ZXh0Q2FjaGU7bGV0IHY9ZT8tZi50YWJsZURlbHRhVC5kZWNvZGUoeSk6LWRlY29kZUludGVnZXIoQywiSUFEVCIsayksVD0wO3g9MDtmb3IoO3g8aTspe3YrPWU/Zi50YWJsZURlbHRhVC5kZWNvZGUoeSk6ZGVjb2RlSW50ZWdlcihDLCJJQURUIixrKTtUKz1lP2YudGFibGVGaXJzdFMuZGVjb2RlKHkpOmRlY29kZUludGVnZXIoQywiSUFGUyIsayk7bGV0IGE9VDtmb3IoOzspe2xldCBuPTA7cz4xJiYobj1lP3kucmVhZEJpdHMoYik6ZGVjb2RlSW50ZWdlcihDLCJJQUlUIixrKSk7Y29uc3QgaT1zKnYrbixUPWU/Zi5zeW1ib2xJRFRhYmxlLmRlY29kZSh5KTpkZWNvZGVJQUlEKEMsayxjKSxPPXQmJihlP3kucmVhZEJpdCgpOmRlY29kZUludGVnZXIoQywiSUFSSSIsaykpO2xldCBNPW9bVF0sRD1NWzBdLmxlbmd0aCxSPU0ubGVuZ3RoO2lmKE8pe2NvbnN0IGU9ZGVjb2RlSW50ZWdlcihDLCJJQVJEVyIsayksdD1kZWNvZGVJbnRlZ2VyKEMsIklBUkRIIixrKTtEKz1lO1IrPXQ7TT1kZWNvZGVSZWZpbmVtZW50KEQsUixnLE0sKGU+PjEpK2RlY29kZUludGVnZXIoQywiSUFSRFgiLGspLCh0Pj4xKStkZWNvZGVJbnRlZ2VyKEMsIklBUkRZIixrKSwhMSxwLG0pfWxldCBFPTA7bD8xJnU/RT1SLTE6YSs9Ui0xOnU+MT9hKz1ELTE6RT1ELTE7Y29uc3QgTj1pLSgxJnU/MDpSLTEpLF89YS0oMiZ1P0QtMTowKTtsZXQgTCxqLFU7aWYobClmb3IoTD0wO0w8UjtMKyspe1M9d1tfK0xdO2lmKCFTKWNvbnRpbnVlO1U9TVtMXTtjb25zdCBlPU1hdGgubWluKHItTixEKTtzd2l0Y2goZCl7Y2FzZSAwOmZvcihqPTA7ajxlO2orKylTW04ral18PVVbal07YnJlYWs7Y2FzZSAyOmZvcihqPTA7ajxlO2orKylTW04ral1ePVVbal07YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgSmJpZzJFcnJvcihgb3BlcmF0b3IgJHtkfSBpcyBub3Qgc3VwcG9ydGVkYCl9fWVsc2UgZm9yKGo9MDtqPFI7aisrKXtTPXdbTitqXTtpZihTKXtVPU1bal07c3dpdGNoKGQpe2Nhc2UgMDpmb3IoTD0wO0w8RDtMKyspU1tfK0xdfD1VW0xdO2JyZWFrO2Nhc2UgMjpmb3IoTD0wO0w8RDtMKyspU1tfK0xdXj1VW0xdO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoYG9wZXJhdG9yICR7ZH0gaXMgbm90IHN1cHBvcnRlZGApfX19eCsrO2NvbnN0IHE9ZT9mLnRhYmxlRGVsdGFTLmRlY29kZSh5KTpkZWNvZGVJbnRlZ2VyKEMsIklBRFMiLGspO2lmKG51bGw9PT1xKWJyZWFrO2ErPUUrcStofX1yZXR1cm4gd31mdW5jdGlvbiByZWFkU2VnbWVudEhlYWRlcihlLHQpe2NvbnN0IHI9e307ci5udW1iZXI9cmVhZFVpbnQzMihlLHQpO2NvbnN0IGE9ZVt0KzRdLG49NjMmYTtpZighWXJbbl0pdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgc2VnbWVudCB0eXBlOiAiK24pO3IudHlwZT1uO3IudHlwZU5hbWU9WXJbbl07ci5kZWZlcnJlZE5vblJldGFpbj0hISgxMjgmYSk7Y29uc3QgaT0hISg2NCZhKSxzPWVbdCs1XTtsZXQgbz1zPj41Jjc7Y29uc3QgYz1bMzEmc107bGV0IGw9dCs2O2lmKDc9PT1zKXtvPTUzNjg3MDkxMSZyZWFkVWludDMyKGUsbC0xKTtsKz0zO2xldCB0PW8rNz4+MztjWzBdPWVbbCsrXTtmb3IoOy0tdD4wOyljLnB1c2goZVtsKytdKX1lbHNlIGlmKDU9PT1zfHw2PT09cyl0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCByZWZlcnJlZC10byBmbGFncyIpO3IucmV0YWluQml0cz1jO2xldCBoPTQ7ci5udW1iZXI8PTI1Nj9oPTE6ci5udW1iZXI8PTY1NTM2JiYoaD0yKTtjb25zdCB1PVtdO2xldCBkLGY7Zm9yKGQ9MDtkPG87ZCsrKXtsZXQgdDt0PTE9PT1oP2VbbF06Mj09PWg/cmVhZFVpbnQxNihlLGwpOnJlYWRVaW50MzIoZSxsKTt1LnB1c2godCk7bCs9aH1yLnJlZmVycmVkVG89dTtpZihpKXtyLnBhZ2VBc3NvY2lhdGlvbj1yZWFkVWludDMyKGUsbCk7bCs9NH1lbHNlIHIucGFnZUFzc29jaWF0aW9uPWVbbCsrXTtyLmxlbmd0aD1yZWFkVWludDMyKGUsbCk7bCs9NDtpZig0Mjk0OTY3Mjk1PT09ci5sZW5ndGgpe2lmKDM4IT09bil0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCB1bmtub3duIHNlZ21lbnQgbGVuZ3RoIik7e2NvbnN0IHQ9cmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihlLGwpLGE9ISEoMSZlW2wrcmFdKSxuPTYsaT1uZXcgVWludDhBcnJheShuKTtpZighYSl7aVswXT0yNTU7aVsxXT0xNzJ9aVsyXT10LmhlaWdodD4+PjI0JjI1NTtpWzNdPXQuaGVpZ2h0Pj4xNiYyNTU7aVs0XT10LmhlaWdodD4+OCYyNTU7aVs1XT0yNTUmdC5oZWlnaHQ7Zm9yKGQ9bCxmPWUubGVuZ3RoO2Q8ZjtkKyspe2xldCB0PTA7Zm9yKDt0PG4mJmlbdF09PT1lW2QrdF07KXQrKztpZih0PT09bil7ci5sZW5ndGg9ZCtuO2JyZWFrfX1pZig0Mjk0OTY3Mjk1PT09ci5sZW5ndGgpdGhyb3cgbmV3IEpiaWcyRXJyb3IoInNlZ21lbnQgZW5kIHdhcyBub3QgZm91bmQiKX19ci5oZWFkZXJFbmQ9bDtyZXR1cm4gcn1mdW5jdGlvbiByZWFkU2VnbWVudHMoZSx0LHIsYSl7Y29uc3Qgbj1bXTtsZXQgaT1yO2Zvcig7aTxhOyl7Y29uc3Qgcj1yZWFkU2VnbWVudEhlYWRlcih0LGkpO2k9ci5oZWFkZXJFbmQ7Y29uc3QgYT17aGVhZGVyOnIsZGF0YTp0fTtpZighZS5yYW5kb21BY2Nlc3Mpe2Euc3RhcnQ9aTtpKz1yLmxlbmd0aDthLmVuZD1pfW4ucHVzaChhKTtpZig1MT09PXIudHlwZSlicmVha31pZihlLnJhbmRvbUFjY2Vzcylmb3IobGV0IGU9MCx0PW4ubGVuZ3RoO2U8dDtlKyspe25bZV0uc3RhcnQ9aTtpKz1uW2VdLmhlYWRlci5sZW5ndGg7bltlXS5lbmQ9aX1yZXR1cm4gbn1mdW5jdGlvbiByZWFkUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uKGUsdCl7cmV0dXJue3dpZHRoOnJlYWRVaW50MzIoZSx0KSxoZWlnaHQ6cmVhZFVpbnQzMihlLHQrNCkseDpyZWFkVWludDMyKGUsdCs4KSx5OnJlYWRVaW50MzIoZSx0KzEyKSxjb21iaW5hdGlvbk9wZXJhdG9yOjcmZVt0KzE2XX19Y29uc3QgcmE9MTc7ZnVuY3Rpb24gcHJvY2Vzc1NlZ21lbnQoZSx0KXtjb25zdCByPWUuaGVhZGVyLGE9ZS5kYXRhLG49ZS5lbmQ7bGV0IGkscyxvLGMsbD1lLnN0YXJ0O3N3aXRjaChyLnR5cGUpe2Nhc2UgMDpjb25zdCBlPXt9LHQ9cmVhZFVpbnQxNihhLGwpO2UuaHVmZm1hbj0hISgxJnQpO2UucmVmaW5lbWVudD0hISgyJnQpO2UuaHVmZm1hbkRIU2VsZWN0b3I9dD4+MiYzO2UuaHVmZm1hbkRXU2VsZWN0b3I9dD4+NCYzO2UuYml0bWFwU2l6ZVNlbGVjdG9yPXQ+PjYmMTtlLmFnZ3JlZ2F0aW9uSW5zdGFuY2VzU2VsZWN0b3I9dD4+NyYxO2UuYml0bWFwQ29kaW5nQ29udGV4dFVzZWQ9ISEoMjU2JnQpO2UuYml0bWFwQ29kaW5nQ29udGV4dFJldGFpbmVkPSEhKDUxMiZ0KTtlLnRlbXBsYXRlPXQ+PjEwJjM7ZS5yZWZpbmVtZW50VGVtcGxhdGU9dD4+MTImMTtsKz0yO2lmKCFlLmh1ZmZtYW4pe2M9MD09PWUudGVtcGxhdGU/NDoxO3M9W107Zm9yKG89MDtvPGM7bysrKXtzLnB1c2goe3g6cmVhZEludDgoYSxsKSx5OnJlYWRJbnQ4KGEsbCsxKX0pO2wrPTJ9ZS5hdD1zfWlmKGUucmVmaW5lbWVudCYmIWUucmVmaW5lbWVudFRlbXBsYXRlKXtzPVtdO2ZvcihvPTA7bzwyO28rKyl7cy5wdXNoKHt4OnJlYWRJbnQ4KGEsbCkseTpyZWFkSW50OChhLGwrMSl9KTtsKz0yfWUucmVmaW5lbWVudEF0PXN9ZS5udW1iZXJPZkV4cG9ydGVkU3ltYm9scz1yZWFkVWludDMyKGEsbCk7bCs9NDtlLm51bWJlck9mTmV3U3ltYm9scz1yZWFkVWludDMyKGEsbCk7bCs9NDtpPVtlLHIubnVtYmVyLHIucmVmZXJyZWRUbyxhLGwsbl07YnJlYWs7Y2FzZSA2OmNhc2UgNzpjb25zdCBoPXt9O2guaW5mbz1yZWFkUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uKGEsbCk7bCs9cmE7Y29uc3QgdT1yZWFkVWludDE2KGEsbCk7bCs9MjtoLmh1ZmZtYW49ISEoMSZ1KTtoLnJlZmluZW1lbnQ9ISEoMiZ1KTtoLmxvZ1N0cmlwU2l6ZT11Pj4yJjM7aC5zdHJpcFNpemU9MTw8aC5sb2dTdHJpcFNpemU7aC5yZWZlcmVuY2VDb3JuZXI9dT4+NCYzO2gudHJhbnNwb3NlZD0hISg2NCZ1KTtoLmNvbWJpbmF0aW9uT3BlcmF0b3I9dT4+NyYzO2guZGVmYXVsdFBpeGVsVmFsdWU9dT4+OSYxO2guZHNPZmZzZXQ9dTw8MTc+PjI3O2gucmVmaW5lbWVudFRlbXBsYXRlPXU+PjE1JjE7aWYoaC5odWZmbWFuKXtjb25zdCBlPXJlYWRVaW50MTYoYSxsKTtsKz0yO2guaHVmZm1hbkZTPTMmZTtoLmh1ZmZtYW5EUz1lPj4yJjM7aC5odWZmbWFuRFQ9ZT4+NCYzO2guaHVmZm1hblJlZmluZW1lbnREVz1lPj42JjM7aC5odWZmbWFuUmVmaW5lbWVudERIPWU+PjgmMztoLmh1ZmZtYW5SZWZpbmVtZW50RFg9ZT4+MTAmMztoLmh1ZmZtYW5SZWZpbmVtZW50RFk9ZT4+MTImMztoLmh1ZmZtYW5SZWZpbmVtZW50U2l6ZVNlbGVjdG9yPSEhKDE2Mzg0JmUpfWlmKGgucmVmaW5lbWVudCYmIWgucmVmaW5lbWVudFRlbXBsYXRlKXtzPVtdO2ZvcihvPTA7bzwyO28rKyl7cy5wdXNoKHt4OnJlYWRJbnQ4KGEsbCkseTpyZWFkSW50OChhLGwrMSl9KTtsKz0yfWgucmVmaW5lbWVudEF0PXN9aC5udW1iZXJPZlN5bWJvbEluc3RhbmNlcz1yZWFkVWludDMyKGEsbCk7bCs9NDtpPVtoLHIucmVmZXJyZWRUbyxhLGwsbl07YnJlYWs7Y2FzZSAxNjpjb25zdCBkPXt9LGY9YVtsKytdO2QubW1yPSEhKDEmZik7ZC50ZW1wbGF0ZT1mPj4xJjM7ZC5wYXR0ZXJuV2lkdGg9YVtsKytdO2QucGF0dGVybkhlaWdodD1hW2wrK107ZC5tYXhQYXR0ZXJuSW5kZXg9cmVhZFVpbnQzMihhLGwpO2wrPTQ7aT1bZCxyLm51bWJlcixhLGwsbl07YnJlYWs7Y2FzZSAyMjpjYXNlIDIzOmNvbnN0IGc9e307Zy5pbmZvPXJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oYSxsKTtsKz1yYTtjb25zdCBwPWFbbCsrXTtnLm1tcj0hISgxJnApO2cudGVtcGxhdGU9cD4+MSYzO2cuZW5hYmxlU2tpcD0hISg4JnApO2cuY29tYmluYXRpb25PcGVyYXRvcj1wPj40Jjc7Zy5kZWZhdWx0UGl4ZWxWYWx1ZT1wPj43JjE7Zy5ncmlkV2lkdGg9cmVhZFVpbnQzMihhLGwpO2wrPTQ7Zy5ncmlkSGVpZ2h0PXJlYWRVaW50MzIoYSxsKTtsKz00O2cuZ3JpZE9mZnNldFg9NDI5NDk2NzI5NSZyZWFkVWludDMyKGEsbCk7bCs9NDtnLmdyaWRPZmZzZXRZPTQyOTQ5NjcyOTUmcmVhZFVpbnQzMihhLGwpO2wrPTQ7Zy5ncmlkVmVjdG9yWD1yZWFkVWludDE2KGEsbCk7bCs9MjtnLmdyaWRWZWN0b3JZPXJlYWRVaW50MTYoYSxsKTtsKz0yO2k9W2csci5yZWZlcnJlZFRvLGEsbCxuXTticmVhaztjYXNlIDM4OmNhc2UgMzk6Y29uc3QgbT17fTttLmluZm89cmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihhLGwpO2wrPXJhO2NvbnN0IGI9YVtsKytdO20ubW1yPSEhKDEmYik7bS50ZW1wbGF0ZT1iPj4xJjM7bS5wcmVkaWN0aW9uPSEhKDgmYik7aWYoIW0ubW1yKXtjPTA9PT1tLnRlbXBsYXRlPzQ6MTtzPVtdO2ZvcihvPTA7bzxjO28rKyl7cy5wdXNoKHt4OnJlYWRJbnQ4KGEsbCkseTpyZWFkSW50OChhLGwrMSl9KTtsKz0yfW0uYXQ9c31pPVttLGEsbCxuXTticmVhaztjYXNlIDQ4OmNvbnN0IHk9e3dpZHRoOnJlYWRVaW50MzIoYSxsKSxoZWlnaHQ6cmVhZFVpbnQzMihhLGwrNCkscmVzb2x1dGlvblg6cmVhZFVpbnQzMihhLGwrOCkscmVzb2x1dGlvblk6cmVhZFVpbnQzMihhLGwrMTIpfTs0Mjk0OTY3Mjk1PT09eS5oZWlnaHQmJmRlbGV0ZSB5LmhlaWdodDtjb25zdCB3PWFbbCsxNl07cmVhZFVpbnQxNihhLGwrMTcpO3kubG9zc2xlc3M9ISEoMSZ3KTt5LnJlZmluZW1lbnQ9ISEoMiZ3KTt5LmRlZmF1bHRQaXhlbFZhbHVlPXc+PjImMTt5LmNvbWJpbmF0aW9uT3BlcmF0b3I9dz4+MyYzO3kucmVxdWlyZXNCdWZmZXI9ISEoMzImdyk7eS5jb21iaW5hdGlvbk9wZXJhdG9yT3ZlcnJpZGU9ISEoNjQmdyk7aT1beV07YnJlYWs7Y2FzZSA0OTpjYXNlIDUwOmNhc2UgNTE6Y2FzZSA2MjpicmVhaztjYXNlIDUzOmk9W3IubnVtYmVyLGEsbCxuXTticmVhaztkZWZhdWx0OnRocm93IG5ldyBKYmlnMkVycm9yKGBzZWdtZW50IHR5cGUgJHtyLnR5cGVOYW1lfSgke3IudHlwZX0pIGlzIG5vdCBpbXBsZW1lbnRlZGApfWNvbnN0IGg9Im9uIityLnR5cGVOYW1lO2ggaW4gdCYmdFtoXS5hcHBseSh0LGkpfWZ1bmN0aW9uIHByb2Nlc3NTZWdtZW50cyhlLHQpe2ZvcihsZXQgcj0wLGE9ZS5sZW5ndGg7cjxhO3IrKylwcm9jZXNzU2VnbWVudChlW3JdLHQpfWNsYXNzIFNpbXBsZVNlZ21lbnRWaXNpdG9ye29uUGFnZUluZm9ybWF0aW9uKGUpe3RoaXMuY3VycmVudFBhZ2VJbmZvPWU7Y29uc3QgdD1lLndpZHRoKzc+PjMscj1uZXcgVWludDhDbGFtcGVkQXJyYXkodCplLmhlaWdodCk7ZS5kZWZhdWx0UGl4ZWxWYWx1ZSYmci5maWxsKDI1NSk7dGhpcy5idWZmZXI9cn1kcmF3Qml0bWFwKGUsdCl7Y29uc3Qgcj10aGlzLmN1cnJlbnRQYWdlSW5mbyxhPWUud2lkdGgsbj1lLmhlaWdodCxpPXIud2lkdGgrNz4+MyxzPXIuY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlP2UuY29tYmluYXRpb25PcGVyYXRvcjpyLmNvbWJpbmF0aW9uT3BlcmF0b3Isbz10aGlzLmJ1ZmZlcixjPTEyOD4+KDcmZS54KTtsZXQgbCxoLHUsZCxmPWUueSppKyhlLng+PjMpO3N3aXRjaChzKXtjYXNlIDA6Zm9yKGw9MDtsPG47bCsrKXt1PWM7ZD1mO2ZvcihoPTA7aDxhO2grKyl7dFtsXVtoXSYmKG9bZF18PXUpO3U+Pj0xO2lmKCF1KXt1PTEyODtkKyt9fWYrPWl9YnJlYWs7Y2FzZSAyOmZvcihsPTA7bDxuO2wrKyl7dT1jO2Q9Zjtmb3IoaD0wO2g8YTtoKyspe3RbbF1baF0mJihvW2RdXj11KTt1Pj49MTtpZighdSl7dT0xMjg7ZCsrfX1mKz1pfWJyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoYG9wZXJhdG9yICR7c30gaXMgbm90IHN1cHBvcnRlZGApfX1vbkltbWVkaWF0ZUdlbmVyaWNSZWdpb24oZSx0LHIsYSl7Y29uc3Qgbj1lLmluZm8saT1uZXcgRGVjb2RpbmdDb250ZXh0KHQscixhKSxzPWRlY29kZUJpdG1hcChlLm1tcixuLndpZHRoLG4uaGVpZ2h0LGUudGVtcGxhdGUsZS5wcmVkaWN0aW9uLG51bGwsZS5hdCxpKTt0aGlzLmRyYXdCaXRtYXAobixzKX1vbkltbWVkaWF0ZUxvc3NsZXNzR2VuZXJpY1JlZ2lvbigpe3RoaXMub25JbW1lZGlhdGVHZW5lcmljUmVnaW9uKC4uLmFyZ3VtZW50cyl9b25TeW1ib2xEaWN0aW9uYXJ5KGUsdCxyLGEsbixpKXtsZXQgcyxvO2lmKGUuaHVmZm1hbil7cz1mdW5jdGlvbiBnZXRTeW1ib2xEaWN0aW9uYXJ5SHVmZm1hblRhYmxlcyhlLHQscil7bGV0IGEsbixpLHMsbz0wO3N3aXRjaChlLmh1ZmZtYW5ESFNlbGVjdG9yKXtjYXNlIDA6Y2FzZSAxOmE9Z2V0U3RhbmRhcmRUYWJsZShlLmh1ZmZtYW5ESFNlbGVjdG9yKzQpO2JyZWFrO2Nhc2UgMzphPWdldEN1c3RvbUh1ZmZtYW5UYWJsZShvLHQscik7bysrO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBESCBzZWxlY3RvciIpfXN3aXRjaChlLmh1ZmZtYW5EV1NlbGVjdG9yKXtjYXNlIDA6Y2FzZSAxOm49Z2V0U3RhbmRhcmRUYWJsZShlLmh1ZmZtYW5EV1NlbGVjdG9yKzIpO2JyZWFrO2Nhc2UgMzpuPWdldEN1c3RvbUh1ZmZtYW5UYWJsZShvLHQscik7bysrO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVyBzZWxlY3RvciIpfWlmKGUuYml0bWFwU2l6ZVNlbGVjdG9yKXtpPWdldEN1c3RvbUh1ZmZtYW5UYWJsZShvLHQscik7bysrfWVsc2UgaT1nZXRTdGFuZGFyZFRhYmxlKDEpO3M9ZS5hZ2dyZWdhdGlvbkluc3RhbmNlc1NlbGVjdG9yP2dldEN1c3RvbUh1ZmZtYW5UYWJsZShvLHQscik6Z2V0U3RhbmRhcmRUYWJsZSgxKTtyZXR1cm57dGFibGVEZWx0YUhlaWdodDphLHRhYmxlRGVsdGFXaWR0aDpuLHRhYmxlQml0bWFwU2l6ZTppLHRhYmxlQWdncmVnYXRlSW5zdGFuY2VzOnN9fShlLHIsdGhpcy5jdXN0b21UYWJsZXMpO289bmV3IFJlYWRlcihhLG4saSl9bGV0IGM9dGhpcy5zeW1ib2xzO2N8fCh0aGlzLnN5bWJvbHM9Yz17fSk7Y29uc3QgbD1bXTtmb3IoY29uc3QgZSBvZiByKXtjb25zdCB0PWNbZV07dCYmbC5wdXNoKC4uLnQpfWNvbnN0IGg9bmV3IERlY29kaW5nQ29udGV4dChhLG4saSk7Y1t0XT1mdW5jdGlvbiBkZWNvZGVTeW1ib2xEaWN0aW9uYXJ5KGUsdCxyLGEsbixpLHMsbyxjLGwsaCx1KXtpZihlJiZ0KXRocm93IG5ldyBKYmlnMkVycm9yKCJzeW1ib2wgcmVmaW5lbWVudCB3aXRoIEh1ZmZtYW4gaXMgbm90IHN1cHBvcnRlZCIpO2NvbnN0IGQ9W107bGV0IGY9MCxnPWxvZzIoci5sZW5ndGgrYSk7Y29uc3QgcD1oLmRlY29kZXIsbT1oLmNvbnRleHRDYWNoZTtsZXQgYix5O2lmKGUpe2I9Z2V0U3RhbmRhcmRUYWJsZSgxKTt5PVtdO2c9TWF0aC5tYXgoZywxKX1mb3IoO2QubGVuZ3RoPGE7KXtmKz1lP2kudGFibGVEZWx0YUhlaWdodC5kZWNvZGUodSk6ZGVjb2RlSW50ZWdlcihtLCJJQURIIixwKTtsZXQgYT0wLG49MDtjb25zdCBiPWU/eS5sZW5ndGg6MDtmb3IoOzspe2NvbnN0IGI9ZT9pLnRhYmxlRGVsdGFXaWR0aC5kZWNvZGUodSk6ZGVjb2RlSW50ZWdlcihtLCJJQURXIixwKTtpZihudWxsPT09YilicmVhazthKz1iO24rPWE7bGV0IHc7aWYodCl7Y29uc3Qgbj1kZWNvZGVJbnRlZ2VyKG0sIklBQUkiLHApO2lmKG4+MSl3PWRlY29kZVRleHRSZWdpb24oZSx0LGEsZiwwLG4sMSxyLmNvbmNhdChkKSxnLDAsMCwxLDAsaSxjLGwsaCwwLHUpO2Vsc2V7Y29uc3QgZT1kZWNvZGVJQUlEKG0scCxnKSx0PWRlY29kZUludGVnZXIobSwiSUFSRFgiLHApLG49ZGVjb2RlSW50ZWdlcihtLCJJQVJEWSIscCk7dz1kZWNvZGVSZWZpbmVtZW50KGEsZixjLGU8ci5sZW5ndGg/cltlXTpkW2Utci5sZW5ndGhdLHQsbiwhMSxsLGgpfWQucHVzaCh3KX1lbHNlIGlmKGUpeS5wdXNoKGEpO2Vsc2V7dz1kZWNvZGVCaXRtYXAoITEsYSxmLHMsITEsbnVsbCxvLGgpO2QucHVzaCh3KX19aWYoZSYmIXQpe2NvbnN0IGU9aS50YWJsZUJpdG1hcFNpemUuZGVjb2RlKHUpO3UuYnl0ZUFsaWduKCk7bGV0IHQ7aWYoMD09PWUpdD1yZWFkVW5jb21wcmVzc2VkQml0bWFwKHUsbixmKTtlbHNle2NvbnN0IHI9dS5lbmQsYT11LnBvc2l0aW9uK2U7dS5lbmQ9YTt0PWRlY29kZU1NUkJpdG1hcCh1LG4sZiwhMSk7dS5lbmQ9cjt1LnBvc2l0aW9uPWF9Y29uc3Qgcj15Lmxlbmd0aDtpZihiPT09ci0xKWQucHVzaCh0KTtlbHNle2xldCBlLGEsbixpLHMsbz0wO2ZvcihlPWI7ZTxyO2UrKyl7aT15W2VdO249bytpO3M9W107Zm9yKGE9MDthPGY7YSsrKXMucHVzaCh0W2FdLnN1YmFycmF5KG8sbikpO2QucHVzaChzKTtvPW59fX19Y29uc3Qgdz1bXSx4PVtdO2xldCBTLGssQz0hMTtjb25zdCB2PXIubGVuZ3RoK2E7Zm9yKDt4Lmxlbmd0aDx2Oyl7bGV0IHQ9ZT9iLmRlY29kZSh1KTpkZWNvZGVJbnRlZ2VyKG0sIklBRVgiLHApO2Zvcig7dC0tOyl4LnB1c2goQyk7Qz0hQ31mb3IoUz0wLGs9ci5sZW5ndGg7UzxrO1MrKyl4W1NdJiZ3LnB1c2gocltTXSk7Zm9yKGxldCBlPTA7ZTxhO1MrKyxlKyspeFtTXSYmdy5wdXNoKGRbZV0pO3JldHVybiB3fShlLmh1ZmZtYW4sZS5yZWZpbmVtZW50LGwsZS5udW1iZXJPZk5ld1N5bWJvbHMsZS5udW1iZXJPZkV4cG9ydGVkU3ltYm9scyxzLGUudGVtcGxhdGUsZS5hdCxlLnJlZmluZW1lbnRUZW1wbGF0ZSxlLnJlZmluZW1lbnRBdCxoLG8pfW9uSW1tZWRpYXRlVGV4dFJlZ2lvbihlLHQscixhLG4pe2NvbnN0IGk9ZS5pbmZvO2xldCBzLG87Y29uc3QgYz10aGlzLnN5bWJvbHMsbD1bXTtmb3IoY29uc3QgZSBvZiB0KXtjb25zdCB0PWNbZV07dCYmbC5wdXNoKC4uLnQpfWNvbnN0IGg9bG9nMihsLmxlbmd0aCk7aWYoZS5odWZmbWFuKXtvPW5ldyBSZWFkZXIocixhLG4pO3M9ZnVuY3Rpb24gZ2V0VGV4dFJlZ2lvbkh1ZmZtYW5UYWJsZXMoZSx0LHIsYSxuKXtjb25zdCBpPVtdO2ZvcihsZXQgZT0wO2U8PTM0O2UrKyl7Y29uc3QgdD1uLnJlYWRCaXRzKDQpO2kucHVzaChuZXcgSHVmZm1hbkxpbmUoW2UsdCwwLDBdKSl9Y29uc3Qgcz1uZXcgSHVmZm1hblRhYmxlKGksITEpO2kubGVuZ3RoPTA7Zm9yKGxldCBlPTA7ZTxhOyl7Y29uc3QgdD1zLmRlY29kZShuKTtpZih0Pj0zMil7bGV0IHIsYSxzO3N3aXRjaCh0KXtjYXNlIDMyOmlmKDA9PT1lKXRocm93IG5ldyBKYmlnMkVycm9yKCJubyBwcmV2aW91cyB2YWx1ZSBpbiBzeW1ib2wgSUQgdGFibGUiKTthPW4ucmVhZEJpdHMoMikrMztyPWlbZS0xXS5wcmVmaXhMZW5ndGg7YnJlYWs7Y2FzZSAzMzphPW4ucmVhZEJpdHMoMykrMztyPTA7YnJlYWs7Y2FzZSAzNDphPW4ucmVhZEJpdHMoNykrMTE7cj0wO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgY29kZSBsZW5ndGggaW4gc3ltYm9sIElEIHRhYmxlIil9Zm9yKHM9MDtzPGE7cysrKXtpLnB1c2gobmV3IEh1ZmZtYW5MaW5lKFtlLHIsMCwwXSkpO2UrK319ZWxzZXtpLnB1c2gobmV3IEh1ZmZtYW5MaW5lKFtlLHQsMCwwXSkpO2UrK319bi5ieXRlQWxpZ24oKTtjb25zdCBvPW5ldyBIdWZmbWFuVGFibGUoaSwhMSk7bGV0IGMsbCxoLHU9MDtzd2l0Y2goZS5odWZmbWFuRlMpe2Nhc2UgMDpjYXNlIDE6Yz1nZXRTdGFuZGFyZFRhYmxlKGUuaHVmZm1hbkZTKzYpO2JyZWFrO2Nhc2UgMzpjPWdldEN1c3RvbUh1ZmZtYW5UYWJsZSh1LHQscik7dSsrO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBGUyBzZWxlY3RvciIpfXN3aXRjaChlLmh1ZmZtYW5EUyl7Y2FzZSAwOmNhc2UgMTpjYXNlIDI6bD1nZXRTdGFuZGFyZFRhYmxlKGUuaHVmZm1hbkRTKzgpO2JyZWFrO2Nhc2UgMzpsPWdldEN1c3RvbUh1ZmZtYW5UYWJsZSh1LHQscik7dSsrO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEUyBzZWxlY3RvciIpfXN3aXRjaChlLmh1ZmZtYW5EVCl7Y2FzZSAwOmNhc2UgMTpjYXNlIDI6aD1nZXRTdGFuZGFyZFRhYmxlKGUuaHVmZm1hbkRUKzExKTticmVhaztjYXNlIDM6aD1nZXRDdXN0b21IdWZmbWFuVGFibGUodSx0LHIpO3UrKzticmVhaztkZWZhdWx0OnRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIEh1ZmZtYW4gRFQgc2VsZWN0b3IiKX1pZihlLnJlZmluZW1lbnQpdGhyb3cgbmV3IEpiaWcyRXJyb3IoInJlZmluZW1lbnQgd2l0aCBIdWZmbWFuIGlzIG5vdCBzdXBwb3J0ZWQiKTtyZXR1cm57c3ltYm9sSURUYWJsZTpvLHRhYmxlRmlyc3RTOmMsdGFibGVEZWx0YVM6bCx0YWJsZURlbHRhVDpofX0oZSx0LHRoaXMuY3VzdG9tVGFibGVzLGwubGVuZ3RoLG8pfWNvbnN0IHU9bmV3IERlY29kaW5nQ29udGV4dChyLGEsbiksZD1kZWNvZGVUZXh0UmVnaW9uKGUuaHVmZm1hbixlLnJlZmluZW1lbnQsaS53aWR0aCxpLmhlaWdodCxlLmRlZmF1bHRQaXhlbFZhbHVlLGUubnVtYmVyT2ZTeW1ib2xJbnN0YW5jZXMsZS5zdHJpcFNpemUsbCxoLGUudHJhbnNwb3NlZCxlLmRzT2Zmc2V0LGUucmVmZXJlbmNlQ29ybmVyLGUuY29tYmluYXRpb25PcGVyYXRvcixzLGUucmVmaW5lbWVudFRlbXBsYXRlLGUucmVmaW5lbWVudEF0LHUsZS5sb2dTdHJpcFNpemUsbyk7dGhpcy5kcmF3Qml0bWFwKGksZCl9b25JbW1lZGlhdGVMb3NzbGVzc1RleHRSZWdpb24oKXt0aGlzLm9uSW1tZWRpYXRlVGV4dFJlZ2lvbiguLi5hcmd1bWVudHMpfW9uUGF0dGVybkRpY3Rpb25hcnkoZSx0LHIsYSxuKXtsZXQgaT10aGlzLnBhdHRlcm5zO2l8fCh0aGlzLnBhdHRlcm5zPWk9e30pO2NvbnN0IHM9bmV3IERlY29kaW5nQ29udGV4dChyLGEsbik7aVt0XT1mdW5jdGlvbiBkZWNvZGVQYXR0ZXJuRGljdGlvbmFyeShlLHQscixhLG4saSl7Y29uc3Qgcz1bXTtpZighZSl7cy5wdXNoKHt4Oi10LHk6MH0pOzA9PT1uJiZzLnB1c2goe3g6LTMseTotMX0se3g6Mix5Oi0yfSx7eDotMix5Oi0yfSl9Y29uc3Qgbz1kZWNvZGVCaXRtYXAoZSwoYSsxKSp0LHIsbiwhMSxudWxsLHMsaSksYz1bXTtmb3IobGV0IGU9MDtlPD1hO2UrKyl7Y29uc3QgYT1bXSxuPXQqZSxpPW4rdDtmb3IobGV0IGU9MDtlPHI7ZSsrKWEucHVzaChvW2VdLnN1YmFycmF5KG4saSkpO2MucHVzaChhKX1yZXR1cm4gY30oZS5tbXIsZS5wYXR0ZXJuV2lkdGgsZS5wYXR0ZXJuSGVpZ2h0LGUubWF4UGF0dGVybkluZGV4LGUudGVtcGxhdGUscyl9b25JbW1lZGlhdGVIYWxmdG9uZVJlZ2lvbihlLHQscixhLG4pe2NvbnN0IGk9dGhpcy5wYXR0ZXJuc1t0WzBdXSxzPWUuaW5mbyxvPW5ldyBEZWNvZGluZ0NvbnRleHQocixhLG4pLGM9ZnVuY3Rpb24gZGVjb2RlSGFsZnRvbmVSZWdpb24oZSx0LHIsYSxuLGkscyxvLGMsbCxoLHUsZCxmLGcpe2lmKHMpdGhyb3cgbmV3IEpiaWcyRXJyb3IoInNraXAgaXMgbm90IHN1cHBvcnRlZCIpO2lmKDAhPT1vKXRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAiJHtvfSIgaXMgbm90IHN1cHBvcnRlZCBpbiBoYWxmdG9uZSByZWdpb25gKTtjb25zdCBwPVtdO2xldCBtLGIseTtmb3IobT0wO208bjttKyspe3k9bmV3IFVpbnQ4QXJyYXkoYSk7aSYmeS5maWxsKGkpO3AucHVzaCh5KX1jb25zdCB3PXQubGVuZ3RoLHg9dFswXSxTPXhbMF0ubGVuZ3RoLGs9eC5sZW5ndGgsQz1sb2cyKHcpLHY9W107aWYoIWUpe3YucHVzaCh7eDpyPD0xPzM6Mix5Oi0xfSk7MD09PXImJnYucHVzaCh7eDotMyx5Oi0xfSx7eDoyLHk6LTJ9LHt4Oi0yLHk6LTJ9KX1jb25zdCBUPVtdO2xldCBPLE0sRCxSLEUsTixfLEwsaixVLHE7ZSYmKE89bmV3IFJlYWRlcihnLmRhdGEsZy5zdGFydCxnLmVuZCkpO2ZvcihtPUMtMTttPj0wO20tLSl7TT1lP2RlY29kZU1NUkJpdG1hcChPLGMsbCwhMCk6ZGVjb2RlQml0bWFwKCExLGMsbCxyLCExLG51bGwsdixnKTtUW21dPU19Zm9yKEQ9MDtEPGw7RCsrKWZvcihSPTA7UjxjO1IrKyl7RT0wO049MDtmb3IoYj1DLTE7Yj49MDtiLS0pe0VePVRbYl1bRF1bUl07Tnw9RTw8Yn1fPXRbTl07TD1oK0QqZitSKmQ+Pjg7aj11K0QqZC1SKmY+Pjg7aWYoTD49MCYmTCtTPD1hJiZqPj0wJiZqK2s8PW4pZm9yKG09MDttPGs7bSsrKXtxPXBbaittXTtVPV9bbV07Zm9yKGI9MDtiPFM7YisrKXFbTCtiXXw9VVtiXX1lbHNle2xldCBlLHQ7Zm9yKG09MDttPGs7bSsrKXt0PWorbTtpZighKHQ8MHx8dD49bikpe3E9cFt0XTtVPV9bbV07Zm9yKGI9MDtiPFM7YisrKXtlPUwrYjtlPj0wJiZlPGEmJihxW2VdfD1VW2JdKX19fX19cmV0dXJuIHB9KGUubW1yLGksZS50ZW1wbGF0ZSxzLndpZHRoLHMuaGVpZ2h0LGUuZGVmYXVsdFBpeGVsVmFsdWUsZS5lbmFibGVTa2lwLGUuY29tYmluYXRpb25PcGVyYXRvcixlLmdyaWRXaWR0aCxlLmdyaWRIZWlnaHQsZS5ncmlkT2Zmc2V0WCxlLmdyaWRPZmZzZXRZLGUuZ3JpZFZlY3RvclgsZS5ncmlkVmVjdG9yWSxvKTt0aGlzLmRyYXdCaXRtYXAocyxjKX1vbkltbWVkaWF0ZUxvc3NsZXNzSGFsZnRvbmVSZWdpb24oKXt0aGlzLm9uSW1tZWRpYXRlSGFsZnRvbmVSZWdpb24oLi4uYXJndW1lbnRzKX1vblRhYmxlcyhlLHQscixhKXtsZXQgbj10aGlzLmN1c3RvbVRhYmxlcztufHwodGhpcy5jdXN0b21UYWJsZXM9bj17fSk7bltlXT1mdW5jdGlvbiBkZWNvZGVUYWJsZXNTZWdtZW50KGUsdCxyKXtjb25zdCBhPWVbdF0sbj00Mjk0OTY3Mjk1JnJlYWRVaW50MzIoZSx0KzEpLGk9NDI5NDk2NzI5NSZyZWFkVWludDMyKGUsdCs1KSxzPW5ldyBSZWFkZXIoZSx0Kzksciksbz0xKyhhPj4xJjcpLGM9MSsoYT4+NCY3KSxsPVtdO2xldCBoLHUsZD1uO2Rve2g9cy5yZWFkQml0cyhvKTt1PXMucmVhZEJpdHMoYyk7bC5wdXNoKG5ldyBIdWZmbWFuTGluZShbZCxoLHUsMF0pKTtkKz0xPDx1fXdoaWxlKGQ8aSk7aD1zLnJlYWRCaXRzKG8pO2wucHVzaChuZXcgSHVmZm1hbkxpbmUoW24tMSxoLDMyLDAsImxvd2VyIl0pKTtoPXMucmVhZEJpdHMobyk7bC5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSxoLDMyLDBdKSk7aWYoMSZhKXtoPXMucmVhZEJpdHMobyk7bC5wdXNoKG5ldyBIdWZmbWFuTGluZShbaCwwXSkpfXJldHVybiBuZXcgSHVmZm1hblRhYmxlKGwsITEpfSh0LHIsYSl9fWNsYXNzIEh1ZmZtYW5MaW5le2NvbnN0cnVjdG9yKGUpe2lmKDI9PT1lLmxlbmd0aCl7dGhpcy5pc09PQj0hMDt0aGlzLnJhbmdlTG93PTA7dGhpcy5wcmVmaXhMZW5ndGg9ZVswXTt0aGlzLnJhbmdlTGVuZ3RoPTA7dGhpcy5wcmVmaXhDb2RlPWVbMV07dGhpcy5pc0xvd2VyUmFuZ2U9ITF9ZWxzZXt0aGlzLmlzT09CPSExO3RoaXMucmFuZ2VMb3c9ZVswXTt0aGlzLnByZWZpeExlbmd0aD1lWzFdO3RoaXMucmFuZ2VMZW5ndGg9ZVsyXTt0aGlzLnByZWZpeENvZGU9ZVszXTt0aGlzLmlzTG93ZXJSYW5nZT0ibG93ZXIiPT09ZVs0XX19fWNsYXNzIEh1ZmZtYW5UcmVlTm9kZXtjb25zdHJ1Y3RvcihlKXt0aGlzLmNoaWxkcmVuPVtdO2lmKGUpe3RoaXMuaXNMZWFmPSEwO3RoaXMucmFuZ2VMZW5ndGg9ZS5yYW5nZUxlbmd0aDt0aGlzLnJhbmdlTG93PWUucmFuZ2VMb3c7dGhpcy5pc0xvd2VyUmFuZ2U9ZS5pc0xvd2VyUmFuZ2U7dGhpcy5pc09PQj1lLmlzT09CfWVsc2UgdGhpcy5pc0xlYWY9ITF9YnVpbGRUcmVlKGUsdCl7Y29uc3Qgcj1lLnByZWZpeENvZGU+PnQmMTtpZih0PD0wKXRoaXMuY2hpbGRyZW5bcl09bmV3IEh1ZmZtYW5UcmVlTm9kZShlKTtlbHNle2xldCBhPXRoaXMuY2hpbGRyZW5bcl07YXx8KHRoaXMuY2hpbGRyZW5bcl09YT1uZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpKTthLmJ1aWxkVHJlZShlLHQtMSl9fWRlY29kZU5vZGUoZSl7aWYodGhpcy5pc0xlYWYpe2lmKHRoaXMuaXNPT0IpcmV0dXJuIG51bGw7Y29uc3QgdD1lLnJlYWRCaXRzKHRoaXMucmFuZ2VMZW5ndGgpO3JldHVybiB0aGlzLnJhbmdlTG93Kyh0aGlzLmlzTG93ZXJSYW5nZT8tdDp0KX1jb25zdCB0PXRoaXMuY2hpbGRyZW5bZS5yZWFkQml0KCldO2lmKCF0KXRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIEh1ZmZtYW4gZGF0YSIpO3JldHVybiB0LmRlY29kZU5vZGUoZSl9fWNsYXNzIEh1ZmZtYW5UYWJsZXtjb25zdHJ1Y3RvcihlLHQpe3R8fHRoaXMuYXNzaWduUHJlZml4Q29kZXMoZSk7dGhpcy5yb290Tm9kZT1uZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpO2ZvcihsZXQgdD0wLHI9ZS5sZW5ndGg7dDxyO3QrKyl7Y29uc3Qgcj1lW3RdO3IucHJlZml4TGVuZ3RoPjAmJnRoaXMucm9vdE5vZGUuYnVpbGRUcmVlKHIsci5wcmVmaXhMZW5ndGgtMSl9fWRlY29kZShlKXtyZXR1cm4gdGhpcy5yb290Tm9kZS5kZWNvZGVOb2RlKGUpfWFzc2lnblByZWZpeENvZGVzKGUpe2NvbnN0IHQ9ZS5sZW5ndGg7bGV0IHI9MDtmb3IobGV0IGE9MDthPHQ7YSsrKXI9TWF0aC5tYXgocixlW2FdLnByZWZpeExlbmd0aCk7Y29uc3QgYT1uZXcgVWludDMyQXJyYXkocisxKTtmb3IobGV0IHI9MDtyPHQ7cisrKWFbZVtyXS5wcmVmaXhMZW5ndGhdKys7bGV0IG4saSxzLG89MSxjPTA7YVswXT0wO2Zvcig7bzw9cjspe2M9YythW28tMV08PDE7bj1jO2k9MDtmb3IoO2k8dDspe3M9ZVtpXTtpZihzLnByZWZpeExlbmd0aD09PW8pe3MucHJlZml4Q29kZT1uO24rK31pKyt9bysrfX19Y29uc3QgYWE9e307ZnVuY3Rpb24gZ2V0U3RhbmRhcmRUYWJsZShlKXtsZXQgdCxyPWFhW2VdO2lmKHIpcmV0dXJuIHI7c3dpdGNoKGUpe2Nhc2UgMTp0PVtbMCwxLDQsMF0sWzE2LDIsOCwyXSxbMjcyLDMsMTYsNl0sWzY1ODA4LDMsMzIsN11dO2JyZWFrO2Nhc2UgMjp0PVtbMCwxLDAsMF0sWzEsMiwwLDJdLFsyLDMsMCw2XSxbMyw0LDMsMTRdLFsxMSw1LDYsMzBdLFs3NSw2LDMyLDYyXSxbNiw2M11dO2JyZWFrO2Nhc2UgMzp0PVtbLTI1Niw4LDgsMjU0XSxbMCwxLDAsMF0sWzEsMiwwLDJdLFsyLDMsMCw2XSxbMyw0LDMsMTRdLFsxMSw1LDYsMzBdLFstMjU3LDgsMzIsMjU1LCJsb3dlciJdLFs3NSw3LDMyLDEyNl0sWzYsNjJdXTticmVhaztjYXNlIDQ6dD1bWzEsMSwwLDBdLFsyLDIsMCwyXSxbMywzLDAsNl0sWzQsNCwzLDE0XSxbMTIsNSw2LDMwXSxbNzYsNSwzMiwzMV1dO2JyZWFrO2Nhc2UgNTp0PVtbLTI1NSw3LDgsMTI2XSxbMSwxLDAsMF0sWzIsMiwwLDJdLFszLDMsMCw2XSxbNCw0LDMsMTRdLFsxMiw1LDYsMzBdLFstMjU2LDcsMzIsMTI3LCJsb3dlciJdLFs3Niw2LDMyLDYyXV07YnJlYWs7Y2FzZSA2OnQ9W1stMjA0OCw1LDEwLDI4XSxbLTEwMjQsNCw5LDhdLFstNTEyLDQsOCw5XSxbLTI1Niw0LDcsMTBdLFstMTI4LDUsNiwyOV0sWy02NCw1LDUsMzBdLFstMzIsNCw1LDExXSxbMCwyLDcsMF0sWzEyOCwzLDcsMl0sWzI1NiwzLDgsM10sWzUxMiw0LDksMTJdLFsxMDI0LDQsMTAsMTNdLFstMjA0OSw2LDMyLDYyLCJsb3dlciJdLFsyMDQ4LDYsMzIsNjNdXTticmVhaztjYXNlIDc6dD1bWy0xMDI0LDQsOSw4XSxbLTUxMiwzLDgsMF0sWy0yNTYsNCw3LDldLFstMTI4LDUsNiwyNl0sWy02NCw1LDUsMjddLFstMzIsNCw1LDEwXSxbMCw0LDUsMTFdLFszMiw1LDUsMjhdLFs2NCw1LDYsMjldLFsxMjgsNCw3LDEyXSxbMjU2LDMsOCwxXSxbNTEyLDMsOSwyXSxbMTAyNCwzLDEwLDNdLFstMTAyNSw1LDMyLDMwLCJsb3dlciJdLFsyMDQ4LDUsMzIsMzFdXTticmVhaztjYXNlIDg6dD1bWy0xNSw4LDMsMjUyXSxbLTcsOSwxLDUwOF0sWy01LDgsMSwyNTNdLFstMyw5LDAsNTA5XSxbLTIsNywwLDEyNF0sWy0xLDQsMCwxMF0sWzAsMiwxLDBdLFsyLDUsMCwyNl0sWzMsNiwwLDU4XSxbNCwzLDQsNF0sWzIwLDYsMSw1OV0sWzIyLDQsNCwxMV0sWzM4LDQsNSwxMl0sWzcwLDUsNiwyN10sWzEzNCw1LDcsMjhdLFsyNjIsNiw3LDYwXSxbMzkwLDcsOCwxMjVdLFs2NDYsNiwxMCw2MV0sWy0xNiw5LDMyLDUxMCwibG93ZXIiXSxbMTY3MCw5LDMyLDUxMV0sWzIsMV1dO2JyZWFrO2Nhc2UgOTp0PVtbLTMxLDgsNCwyNTJdLFstMTUsOSwyLDUwOF0sWy0xMSw4LDIsMjUzXSxbLTcsOSwxLDUwOV0sWy01LDcsMSwxMjRdLFstMyw0LDEsMTBdLFstMSwzLDEsMl0sWzEsMywxLDNdLFszLDUsMSwyNl0sWzUsNiwxLDU4XSxbNywzLDUsNF0sWzM5LDYsMiw1OV0sWzQzLDQsNSwxMV0sWzc1LDQsNiwxMl0sWzEzOSw1LDcsMjddLFsyNjcsNSw4LDI4XSxbNTIzLDYsOCw2MF0sWzc3OSw3LDksMTI1XSxbMTI5MSw2LDExLDYxXSxbLTMyLDksMzIsNTEwLCJsb3dlciJdLFszMzM5LDksMzIsNTExXSxbMiwwXV07YnJlYWs7Y2FzZSAxMDp0PVtbLTIxLDcsNCwxMjJdLFstNSw4LDAsMjUyXSxbLTQsNywwLDEyM10sWy0zLDUsMCwyNF0sWy0yLDIsMiwwXSxbMiw1LDAsMjVdLFszLDYsMCw1NF0sWzQsNywwLDEyNF0sWzUsOCwwLDI1M10sWzYsMiw2LDFdLFs3MCw1LDUsMjZdLFsxMDIsNiw1LDU1XSxbMTM0LDYsNiw1Nl0sWzE5OCw2LDcsNTddLFszMjYsNiw4LDU4XSxbNTgyLDYsOSw1OV0sWzEwOTQsNiwxMCw2MF0sWzIxMTgsNywxMSwxMjVdLFstMjIsOCwzMiwyNTQsImxvd2VyIl0sWzQxNjYsOCwzMiwyNTVdLFsyLDJdXTticmVhaztjYXNlIDExOnQ9W1sxLDEsMCwwXSxbMiwyLDEsMl0sWzQsNCwwLDEyXSxbNSw0LDEsMTNdLFs3LDUsMSwyOF0sWzksNSwyLDI5XSxbMTMsNiwyLDYwXSxbMTcsNywyLDEyMl0sWzIxLDcsMywxMjNdLFsyOSw3LDQsMTI0XSxbNDUsNyw1LDEyNV0sWzc3LDcsNiwxMjZdLFsxNDEsNywzMiwxMjddXTticmVhaztjYXNlIDEyOnQ9W1sxLDEsMCwwXSxbMiwyLDAsMl0sWzMsMywxLDZdLFs1LDUsMCwyOF0sWzYsNSwxLDI5XSxbOCw2LDEsNjBdLFsxMCw3LDAsMTIyXSxbMTEsNywxLDEyM10sWzEzLDcsMiwxMjRdLFsxNyw3LDMsMTI1XSxbMjUsNyw0LDEyNl0sWzQxLDgsNSwyNTRdLFs3Myw4LDMyLDI1NV1dO2JyZWFrO2Nhc2UgMTM6dD1bWzEsMSwwLDBdLFsyLDMsMCw0XSxbMyw0LDAsMTJdLFs0LDUsMCwyOF0sWzUsNCwxLDEzXSxbNywzLDMsNV0sWzE1LDYsMSw1OF0sWzE3LDYsMiw1OV0sWzIxLDYsMyw2MF0sWzI5LDYsNCw2MV0sWzQ1LDYsNSw2Ml0sWzc3LDcsNiwxMjZdLFsxNDEsNywzMiwxMjddXTticmVhaztjYXNlIDE0OnQ9W1stMiwzLDAsNF0sWy0xLDMsMCw1XSxbMCwxLDAsMF0sWzEsMywwLDZdLFsyLDMsMCw3XV07YnJlYWs7Y2FzZSAxNTp0PVtbLTI0LDcsNCwxMjRdLFstOCw2LDIsNjBdLFstNCw1LDEsMjhdLFstMiw0LDAsMTJdLFstMSwzLDAsNF0sWzAsMSwwLDBdLFsxLDMsMCw1XSxbMiw0LDAsMTNdLFszLDUsMSwyOV0sWzUsNiwyLDYxXSxbOSw3LDQsMTI1XSxbLTI1LDcsMzIsMTI2LCJsb3dlciJdLFsyNSw3LDMyLDEyN11dO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEpiaWcyRXJyb3IoYHN0YW5kYXJkIHRhYmxlIEIuJHtlfSBkb2VzIG5vdCBleGlzdGApfWZvcihsZXQgZT0wLHI9dC5sZW5ndGg7ZTxyO2UrKyl0W2VdPW5ldyBIdWZmbWFuTGluZSh0W2VdKTtyPW5ldyBIdWZmbWFuVGFibGUodCwhMCk7YWFbZV09cjtyZXR1cm4gcn1jbGFzcyBSZWFkZXJ7Y29uc3RydWN0b3IoZSx0LHIpe3RoaXMuZGF0YT1lO3RoaXMuc3RhcnQ9dDt0aGlzLmVuZD1yO3RoaXMucG9zaXRpb249dDt0aGlzLnNoaWZ0PS0xO3RoaXMuY3VycmVudEJ5dGU9MH1yZWFkQml0KCl7aWYodGhpcy5zaGlmdDwwKXtpZih0aGlzLnBvc2l0aW9uPj10aGlzLmVuZCl0aHJvdyBuZXcgSmJpZzJFcnJvcigiZW5kIG9mIGRhdGEgd2hpbGUgcmVhZGluZyBiaXQiKTt0aGlzLmN1cnJlbnRCeXRlPXRoaXMuZGF0YVt0aGlzLnBvc2l0aW9uKytdO3RoaXMuc2hpZnQ9N31jb25zdCBlPXRoaXMuY3VycmVudEJ5dGU+PnRoaXMuc2hpZnQmMTt0aGlzLnNoaWZ0LS07cmV0dXJuIGV9cmVhZEJpdHMoZSl7bGV0IHQscj0wO2Zvcih0PWUtMTt0Pj0wO3QtLSlyfD10aGlzLnJlYWRCaXQoKTw8dDtyZXR1cm4gcn1ieXRlQWxpZ24oKXt0aGlzLnNoaWZ0PS0xfW5leHQoKXtyZXR1cm4gdGhpcy5wb3NpdGlvbj49dGhpcy5lbmQ/LTE6dGhpcy5kYXRhW3RoaXMucG9zaXRpb24rK119fWZ1bmN0aW9uIGdldEN1c3RvbUh1ZmZtYW5UYWJsZShlLHQscil7bGV0IGE9MDtmb3IobGV0IG49MCxpPXQubGVuZ3RoO248aTtuKyspe2NvbnN0IGk9clt0W25dXTtpZihpKXtpZihlPT09YSlyZXR1cm4gaTthKyt9fXRocm93IG5ldyBKYmlnMkVycm9yKCJjYW4ndCBmaW5kIGN1c3RvbSBIdWZmbWFuIHRhYmxlIil9ZnVuY3Rpb24gcmVhZFVuY29tcHJlc3NlZEJpdG1hcChlLHQscil7Y29uc3QgYT1bXTtmb3IobGV0IG49MDtuPHI7bisrKXtjb25zdCByPW5ldyBVaW50OEFycmF5KHQpO2EucHVzaChyKTtmb3IobGV0IGE9MDthPHQ7YSsrKXJbYV09ZS5yZWFkQml0KCk7ZS5ieXRlQWxpZ24oKX1yZXR1cm4gYX1mdW5jdGlvbiBkZWNvZGVNTVJCaXRtYXAoZSx0LHIsYSl7Y29uc3Qgbj1uZXcgQ0NJVFRGYXhEZWNvZGVyKGUse0s6LTEsQ29sdW1uczp0LFJvd3M6cixCbGFja0lzMTohMCxFbmRPZkJsb2NrOmF9KSxpPVtdO2xldCBzLG89ITE7Zm9yKGxldCBlPTA7ZTxyO2UrKyl7Y29uc3QgZT1uZXcgVWludDhBcnJheSh0KTtpLnB1c2goZSk7bGV0IHI9LTE7Zm9yKGxldCBhPTA7YTx0O2ErKyl7aWYocjwwKXtzPW4ucmVhZE5leHRDaGFyKCk7aWYoLTE9PT1zKXtzPTA7bz0hMH1yPTd9ZVthXT1zPj5yJjE7ci0tfX1pZihhJiYhbyl7Y29uc3QgZT01O2ZvcihsZXQgdD0wO3Q8ZSYmLTEhPT1uLnJlYWROZXh0Q2hhcigpO3QrKyk7fXJldHVybiBpfWNsYXNzIEpiaWcySW1hZ2V7cGFyc2VDaHVua3MoZSl7cmV0dXJuIGZ1bmN0aW9uIHBhcnNlSmJpZzJDaHVua3MoZSl7Y29uc3QgdD1uZXcgU2ltcGxlU2VnbWVudFZpc2l0b3I7Zm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKXtjb25zdCBhPWVbcl07cHJvY2Vzc1NlZ21lbnRzKHJlYWRTZWdtZW50cyh7fSxhLmRhdGEsYS5zdGFydCxhLmVuZCksdCl9cmV0dXJuIHQuYnVmZmVyfShlKX1wYXJzZShlKXt0aHJvdyBuZXcgRXJyb3IoIk5vdCBpbXBsZW1lbnRlZDogSmJpZzJJbWFnZS5wYXJzZSIpfX1jbGFzcyBKYmlnMlN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbXtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIodCk7dGhpcy5zdHJlYW09ZTt0aGlzLmRpY3Q9ZS5kaWN0O3RoaXMubWF5YmVMZW5ndGg9dDt0aGlzLnBhcmFtcz1yfWdldCBieXRlcygpe3JldHVybiBzaGFkb3codGhpcywiYnl0ZXMiLHRoaXMuc3RyZWFtLmdldEJ5dGVzKHRoaXMubWF5YmVMZW5ndGgpKX1lbnN1cmVCdWZmZXIoZSl7fXJlYWRCbG9jaygpe3RoaXMuZGVjb2RlSW1hZ2UoKX1kZWNvZGVJbWFnZShlKXtpZih0aGlzLmVvZilyZXR1cm4gdGhpcy5idWZmZXI7ZXx8PXRoaXMuYnl0ZXM7Y29uc3QgdD1uZXcgSmJpZzJJbWFnZSxyPVtdO2lmKHRoaXMucGFyYW1zIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgZT10aGlzLnBhcmFtcy5nZXQoIkpCSUcyR2xvYmFscyIpO2lmKGUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKXtjb25zdCB0PWUuZ2V0Qnl0ZXMoKTtyLnB1c2goe2RhdGE6dCxzdGFydDowLGVuZDp0Lmxlbmd0aH0pfX1yLnB1c2goe2RhdGE6ZSxzdGFydDowLGVuZDplLmxlbmd0aH0pO2NvbnN0IGE9dC5wYXJzZUNodW5rcyhyKSxuPWEubGVuZ3RoO2ZvcihsZXQgZT0wO2U8bjtlKyspYVtlXV49MjU1O3RoaXMuYnVmZmVyPWE7dGhpcy5idWZmZXJMZW5ndGg9bjt0aGlzLmVvZj0hMDtyZXR1cm4gdGhpcy5idWZmZXJ9Z2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCl7cmV0dXJuIHRoaXMuc3RyZWFtLmlzQXN5bmN9fWNsYXNzIEpweFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbXtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIodCk7dGhpcy5zdHJlYW09ZTt0aGlzLmRpY3Q9ZS5kaWN0O3RoaXMubWF5YmVMZW5ndGg9dDt0aGlzLnBhcmFtcz1yfWdldCBieXRlcygpe3JldHVybiBzaGFkb3codGhpcywiYnl0ZXMiLHRoaXMuc3RyZWFtLmdldEJ5dGVzKHRoaXMubWF5YmVMZW5ndGgpKX1lbnN1cmVCdWZmZXIoZSl7fXJlYWRCbG9jayhlKXt1bnJlYWNoYWJsZSgiSnB4U3RyZWFtLnJlYWRCbG9jayIpfWdldCBpc0FzeW5jRGVjb2Rlcigpe3JldHVybiEwfWFzeW5jIGRlY29kZUltYWdlKGUsdCl7aWYodGhpcy5lb2YpcmV0dXJuIHRoaXMuYnVmZmVyO2V8fD10aGlzLmJ5dGVzO3RoaXMuYnVmZmVyPWF3YWl0IEpweEltYWdlLmRlY29kZShlLHQpO3RoaXMuYnVmZmVyTGVuZ3RoPXRoaXMuYnVmZmVyLmxlbmd0aDt0aGlzLmVvZj0hMDtyZXR1cm4gdGhpcy5idWZmZXJ9Z2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCl7cmV0dXJuIHRoaXMuc3RyZWFtLmlzQXN5bmN9fWNsYXNzIExaV1N0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbXtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIodCk7dGhpcy5zdHI9ZTt0aGlzLmRpY3Q9ZS5kaWN0O3RoaXMuY2FjaGVkRGF0YT0wO3RoaXMuYml0c0NhY2hlZD0wO2NvbnN0IGE9NDA5NixuPXtlYXJseUNoYW5nZTpyLGNvZGVMZW5ndGg6OSxuZXh0Q29kZToyNTgsZGljdGlvbmFyeVZhbHVlczpuZXcgVWludDhBcnJheShhKSxkaWN0aW9uYXJ5TGVuZ3RoczpuZXcgVWludDE2QXJyYXkoYSksZGljdGlvbmFyeVByZXZDb2RlczpuZXcgVWludDE2QXJyYXkoYSksY3VycmVudFNlcXVlbmNlOm5ldyBVaW50OEFycmF5KGEpLGN1cnJlbnRTZXF1ZW5jZUxlbmd0aDowfTtmb3IobGV0IGU9MDtlPDI1NjsrK2Upe24uZGljdGlvbmFyeVZhbHVlc1tlXT1lO24uZGljdGlvbmFyeUxlbmd0aHNbZV09MX10aGlzLmx6d1N0YXRlPW59cmVhZEJpdHMoZSl7bGV0IHQ9dGhpcy5iaXRzQ2FjaGVkLHI9dGhpcy5jYWNoZWREYXRhO2Zvcig7dDxlOyl7Y29uc3QgZT10aGlzLnN0ci5nZXRCeXRlKCk7aWYoLTE9PT1lKXt0aGlzLmVvZj0hMDtyZXR1cm4gbnVsbH1yPXI8PDh8ZTt0Kz04fXRoaXMuYml0c0NhY2hlZD10LT1lO3RoaXMuY2FjaGVkRGF0YT1yO3RoaXMubGFzdENvZGU9bnVsbDtyZXR1cm4gcj4+PnQmKDE8PGUpLTF9cmVhZEJsb2NrKCl7bGV0IGUsdCxyLGE9MTAyNDtjb25zdCBuPXRoaXMubHp3U3RhdGU7aWYoIW4pcmV0dXJuO2NvbnN0IGk9bi5lYXJseUNoYW5nZTtsZXQgcz1uLm5leHRDb2RlO2NvbnN0IG89bi5kaWN0aW9uYXJ5VmFsdWVzLGM9bi5kaWN0aW9uYXJ5TGVuZ3RocyxsPW4uZGljdGlvbmFyeVByZXZDb2RlcztsZXQgaD1uLmNvZGVMZW5ndGgsdT1uLnByZXZDb2RlO2NvbnN0IGQ9bi5jdXJyZW50U2VxdWVuY2U7bGV0IGY9bi5jdXJyZW50U2VxdWVuY2VMZW5ndGgsZz0wLHA9dGhpcy5idWZmZXJMZW5ndGgsbT10aGlzLmVuc3VyZUJ1ZmZlcih0aGlzLmJ1ZmZlckxlbmd0aCthKTtmb3IoZT0wO2U8NTEyO2UrKyl7Y29uc3QgZT10aGlzLnJlYWRCaXRzKGgpLG49Zj4wO2lmKGU8MjU2KXtkWzBdPWU7Zj0xfWVsc2V7aWYoIShlPj0yNTgpKXtpZigyNTY9PT1lKXtoPTk7cz0yNTg7Zj0wO2NvbnRpbnVlfXRoaXMuZW9mPSEwO2RlbGV0ZSB0aGlzLmx6d1N0YXRlO2JyZWFrfWlmKGU8cyl7Zj1jW2VdO2Zvcih0PWYtMSxyPWU7dD49MDt0LS0pe2RbdF09b1tyXTtyPWxbcl19fWVsc2UgZFtmKytdPWRbMF19aWYobil7bFtzXT11O2Nbc109Y1t1XSsxO29bc109ZFswXTtzKys7aD1zK2kmcytpLTE/aDowfE1hdGgubWluKE1hdGgubG9nKHMraSkvLjY5MzE0NzE4MDU1OTk0NTMrMSwxMil9dT1lO2crPWY7aWYoYTxnKXtkb3thKz01MTJ9d2hpbGUoYTxnKTttPXRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoK2EpfWZvcih0PTA7dDxmO3QrKyltW3ArK109ZFt0XX1uLm5leHRDb2RlPXM7bi5jb2RlTGVuZ3RoPWg7bi5wcmV2Q29kZT11O24uY3VycmVudFNlcXVlbmNlTGVuZ3RoPWY7dGhpcy5idWZmZXJMZW5ndGg9cH19Y2xhc3MgUHJlZGljdG9yU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFte2NvbnN0cnVjdG9yKGUsdCxyKXtzdXBlcih0KTtpZighKHIgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm4gZTtjb25zdCBhPXRoaXMucHJlZGljdG9yPXIuZ2V0KCJQcmVkaWN0b3IiKXx8MTtpZihhPD0xKXJldHVybiBlO2lmKDIhPT1hJiYoYTwxMHx8YT4xNSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbnN1cHBvcnRlZCBwcmVkaWN0b3I6ICR7YX1gKTt0aGlzLnJlYWRCbG9jaz0yPT09YT90aGlzLnJlYWRCbG9ja1RpZmY6dGhpcy5yZWFkQmxvY2tQbmc7dGhpcy5zdHI9ZTt0aGlzLmRpY3Q9ZS5kaWN0O2NvbnN0IG49dGhpcy5jb2xvcnM9ci5nZXQoIkNvbG9ycyIpfHwxLGk9dGhpcy5iaXRzPXIuZ2V0KCJCUEMiLCJCaXRzUGVyQ29tcG9uZW50Iil8fDgscz10aGlzLmNvbHVtbnM9ci5nZXQoIkNvbHVtbnMiKXx8MTt0aGlzLnBpeEJ5dGVzPW4qaSs3Pj4zO3RoaXMucm93Qnl0ZXM9cypuKmkrNz4+MztyZXR1cm4gdGhpc31yZWFkQmxvY2tUaWZmKCl7Y29uc3QgZT10aGlzLnJvd0J5dGVzLHQ9dGhpcy5idWZmZXJMZW5ndGgscj10aGlzLmVuc3VyZUJ1ZmZlcih0K2UpLGE9dGhpcy5iaXRzLG49dGhpcy5jb2xvcnMsaT10aGlzLnN0ci5nZXRCeXRlcyhlKTt0aGlzLmVvZj0haS5sZW5ndGg7aWYodGhpcy5lb2YpcmV0dXJuO2xldCBzLG89MCxjPTAsbD0wLGg9MCx1PXQ7aWYoMT09PWEmJjE9PT1uKWZvcihzPTA7czxlOysrcyl7bGV0IGU9aVtzXV5vO2VePWU+PjE7ZV49ZT4+MjtlXj1lPj40O289KDEmZSk8PDc7clt1KytdPWV9ZWxzZSBpZig4PT09YSl7Zm9yKHM9MDtzPG47KytzKXJbdSsrXT1pW3NdO2Zvcig7czxlOysrcyl7clt1XT1yW3Utbl0raVtzXTt1Kyt9fWVsc2UgaWYoMTY9PT1hKXtjb25zdCB0PTIqbjtmb3Iocz0wO3M8dDsrK3Mpclt1KytdPWlbc107Zm9yKDtzPGU7cys9Mil7Y29uc3QgZT0oKDI1NSZpW3NdKTw8OCkrKDI1NSZpW3MrMV0pKygoMjU1JnJbdS10XSk8PDgpKygyNTUmclt1LXQrMV0pO3JbdSsrXT1lPj44JjI1NTtyW3UrK109MjU1JmV9fWVsc2V7Y29uc3QgZT1uZXcgVWludDhBcnJheShuKzEpLHU9KDE8PGEpLTE7bGV0IGQ9MCxmPXQ7Y29uc3QgZz10aGlzLmNvbHVtbnM7Zm9yKHM9MDtzPGc7KytzKWZvcihsZXQgdD0wO3Q8bjsrK3Qpe2lmKGw8YSl7bz1vPDw4fDI1NSZpW2QrK107bCs9OH1lW3RdPWVbdF0rKG8+PmwtYSkmdTtsLT1hO2M9Yzw8YXxlW3RdO2grPWE7aWYoaD49OCl7cltmKytdPWM+PmgtOCYyNTU7aC09OH19aD4wJiYocltmKytdPShjPDw4LWgpKyhvJigxPDw4LWgpLTEpKX10aGlzLmJ1ZmZlckxlbmd0aCs9ZX1yZWFkQmxvY2tQbmcoKXtjb25zdCBlPXRoaXMucm93Qnl0ZXMsdD10aGlzLnBpeEJ5dGVzLHI9dGhpcy5zdHIuZ2V0Qnl0ZSgpLGE9dGhpcy5zdHIuZ2V0Qnl0ZXMoZSk7dGhpcy5lb2Y9IWEubGVuZ3RoO2lmKHRoaXMuZW9mKXJldHVybjtjb25zdCBuPXRoaXMuYnVmZmVyTGVuZ3RoLGk9dGhpcy5lbnN1cmVCdWZmZXIobitlKTtsZXQgcz1pLnN1YmFycmF5KG4tZSxuKTswPT09cy5sZW5ndGgmJihzPW5ldyBVaW50OEFycmF5KGUpKTtsZXQgbyxjLGwsaD1uO3N3aXRjaChyKXtjYXNlIDA6Zm9yKG89MDtvPGU7KytvKWlbaCsrXT1hW29dO2JyZWFrO2Nhc2UgMTpmb3Iobz0wO288dDsrK28paVtoKytdPWFbb107Zm9yKDtvPGU7KytvKXtpW2hdPWlbaC10XSthW29dJjI1NTtoKyt9YnJlYWs7Y2FzZSAyOmZvcihvPTA7bzxlOysrbylpW2grK109c1tvXSthW29dJjI1NTticmVhaztjYXNlIDM6Zm9yKG89MDtvPHQ7KytvKWlbaCsrXT0oc1tvXT4+MSkrYVtvXTtmb3IoO288ZTsrK28pe2lbaF09KHNbb10raVtoLXRdPj4xKSthW29dJjI1NTtoKyt9YnJlYWs7Y2FzZSA0OmZvcihvPTA7bzx0Oysrbyl7Yz1zW29dO2w9YVtvXTtpW2grK109YytsfWZvcig7bzxlOysrbyl7Yz1zW29dO2NvbnN0IGU9c1tvLXRdLHI9aVtoLXRdLG49citjLWU7bGV0IHU9bi1yO3U8MCYmKHU9LXUpO2xldCBkPW4tYztkPDAmJihkPS1kKTtsZXQgZj1uLWU7ZjwwJiYoZj0tZik7bD1hW29dO2lbaCsrXT11PD1kJiZ1PD1mP3IrbDpkPD1mP2MrbDplK2x9YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVuc3VwcG9ydGVkIHByZWRpY3RvcjogJHtyfWApfXRoaXMuYnVmZmVyTGVuZ3RoKz1lfX1jbGFzcyBSdW5MZW5ndGhTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW17Y29uc3RydWN0b3IoZSx0KXtzdXBlcih0KTt0aGlzLnN0cj1lO3RoaXMuZGljdD1lLmRpY3R9cmVhZEJsb2NrKCl7Y29uc3QgZT10aGlzLnN0ci5nZXRCeXRlcygyKTtpZighZXx8ZS5sZW5ndGg8Mnx8MTI4PT09ZVswXSl7dGhpcy5lb2Y9ITA7cmV0dXJufWxldCB0LHI9dGhpcy5idWZmZXJMZW5ndGgsYT1lWzBdO2lmKGE8MTI4KXt0PXRoaXMuZW5zdXJlQnVmZmVyKHIrYSsxKTt0W3IrK109ZVsxXTtpZihhPjApe2NvbnN0IGU9dGhpcy5zdHIuZ2V0Qnl0ZXMoYSk7dC5zZXQoZSxyKTtyKz1hfX1lbHNle2E9MjU3LWE7dD10aGlzLmVuc3VyZUJ1ZmZlcihyK2ErMSk7dC5maWxsKGVbMV0scixyK2EpO3IrPWF9dGhpcy5idWZmZXJMZW5ndGg9cn19Y2xhc3MgUGFyc2Vye2NvbnN0cnVjdG9yKHtsZXhlcjplLHhyZWY6dCxhbGxvd1N0cmVhbXM6cj0hMSxyZWNvdmVyeU1vZGU6YT0hMX0pe3RoaXMubGV4ZXI9ZTt0aGlzLnhyZWY9dDt0aGlzLmFsbG93U3RyZWFtcz1yO3RoaXMucmVjb3ZlcnlNb2RlPWE7dGhpcy5pbWFnZUNhY2hlPU9iamVjdC5jcmVhdGUobnVsbCk7dGhpcy5faW1hZ2VJZD0wO3RoaXMucmVmaWxsKCl9cmVmaWxsKCl7dGhpcy5idWYxPXRoaXMubGV4ZXIuZ2V0T2JqKCk7dGhpcy5idWYyPXRoaXMubGV4ZXIuZ2V0T2JqKCl9c2hpZnQoKXtpZih0aGlzLmJ1ZjIgaW5zdGFuY2VvZiBDbWQmJiJJRCI9PT10aGlzLmJ1ZjIuY21kKXt0aGlzLmJ1ZjE9dGhpcy5idWYyO3RoaXMuYnVmMj1udWxsfWVsc2V7dGhpcy5idWYxPXRoaXMuYnVmMjt0aGlzLmJ1ZjI9dGhpcy5sZXhlci5nZXRPYmooKX19dHJ5U2hpZnQoKXt0cnl7dGhpcy5zaGlmdCgpO3JldHVybiEwfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO3JldHVybiExfX1nZXRPYmooZT1udWxsKXtjb25zdCB0PXRoaXMuYnVmMTt0aGlzLnNoaWZ0KCk7aWYodCBpbnN0YW5jZW9mIENtZClzd2l0Y2godC5jbWQpe2Nhc2UiQkkiOnJldHVybiB0aGlzLm1ha2VJbmxpbmVJbWFnZShlKTtjYXNlIlsiOmNvbnN0IHI9W107Zm9yKDshaXNDbWQodGhpcy5idWYxLCJdIikmJnRoaXMuYnVmMSE9PXNyOylyLnB1c2godGhpcy5nZXRPYmooZSkpO2lmKHRoaXMuYnVmMT09PXNyKXtpZih0aGlzLnJlY292ZXJ5TW9kZSlyZXR1cm4gcjt0aHJvdyBuZXcgUGFyc2VyRU9GRXhjZXB0aW9uKCJFbmQgb2YgZmlsZSBpbnNpZGUgYXJyYXkuIil9dGhpcy5zaGlmdCgpO3JldHVybiByO2Nhc2UiPDwiOmNvbnN0IGE9bmV3IERpY3QodGhpcy54cmVmKTtmb3IoOyFpc0NtZCh0aGlzLmJ1ZjEsIj4+IikmJnRoaXMuYnVmMSE9PXNyOyl7aWYoISh0aGlzLmJ1ZjEgaW5zdGFuY2VvZiBOYW1lKSl7aW5mbygiTWFsZm9ybWVkIGRpY3Rpb25hcnk6IGtleSBtdXN0IGJlIGEgbmFtZSBvYmplY3QiKTt0aGlzLnNoaWZ0KCk7Y29udGludWV9Y29uc3QgdD10aGlzLmJ1ZjEubmFtZTt0aGlzLnNoaWZ0KCk7aWYodGhpcy5idWYxPT09c3IpYnJlYWs7YS5zZXQodCx0aGlzLmdldE9iaihlKSl9aWYodGhpcy5idWYxPT09c3Ipe2lmKHRoaXMucmVjb3ZlcnlNb2RlKXJldHVybiBhO3Rocm93IG5ldyBQYXJzZXJFT0ZFeGNlcHRpb24oIkVuZCBvZiBmaWxlIGluc2lkZSBkaWN0aW9uYXJ5LiIpfWlmKGlzQ21kKHRoaXMuYnVmMiwic3RyZWFtIikpcmV0dXJuIHRoaXMuYWxsb3dTdHJlYW1zP3RoaXMubWFrZVN0cmVhbShhLGUpOmE7dGhpcy5zaGlmdCgpO3JldHVybiBhO2RlZmF1bHQ6cmV0dXJuIHR9aWYoTnVtYmVyLmlzSW50ZWdlcih0KSl7aWYoTnVtYmVyLmlzSW50ZWdlcih0aGlzLmJ1ZjEpJiZpc0NtZCh0aGlzLmJ1ZjIsIlIiKSl7Y29uc3QgZT1SZWYuZ2V0KHQsdGhpcy5idWYxKTt0aGlzLnNoaWZ0KCk7dGhpcy5zaGlmdCgpO3JldHVybiBlfXJldHVybiB0fXJldHVybiJzdHJpbmciPT10eXBlb2YgdCYmZT9lLmRlY3J5cHRTdHJpbmcodCk6dH1maW5kRGVmYXVsdElubGluZVN0cmVhbUVuZChlKXtjb25zdHtrbm93bkNvbW1hbmRzOnR9PXRoaXMubGV4ZXIscj1lLnBvcztsZXQgYSxuLGk9MDtmb3IoOy0xIT09KGE9ZS5nZXRCeXRlKCkpOylpZigwPT09aSlpPTY5PT09YT8xOjA7ZWxzZSBpZigxPT09aSlpPTczPT09YT8yOjA7ZWxzZSBpZigzMj09PWF8fDEwPT09YXx8MTM9PT1hKXtuPWUucG9zO2NvbnN0IHI9ZS5wZWVrQnl0ZXMoMTUpLHM9ci5sZW5ndGg7aWYoMD09PXMpYnJlYWs7Zm9yKGxldCBlPTA7ZTxzO2UrKyl7YT1yW2VdO2lmKCgwIT09YXx8MD09PXJbZSsxXSkmJigxMCE9PWEmJjEzIT09YSYmKGE8MzJ8fGE+MTI3KSkpe2k9MDticmVha319aWYoMiE9PWkpY29udGludWU7aWYoIXQpe3dhcm4oImZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kIC0gYGxleGVyLmtub3duQ29tbWFuZHNgIGlzIHVuZGVmaW5lZC4iKTtjb250aW51ZX1jb25zdCBvPW5ldyBMZXhlcihuZXcgU3RyZWFtKGUucGVla0J5dGVzKDc1KSksdCk7by5faGV4U3RyaW5nV2Fybj0oKT0+e307bGV0IGM9MDtmb3IoOzspe2NvbnN0IGU9by5nZXRPYmooKTtpZihlPT09c3Ipe2k9MDticmVha31pZihlIGluc3RhbmNlb2YgQ21kKXtjb25zdCByPXRbZS5jbWRdO2lmKCFyKXtpPTA7YnJlYWt9aWYoci52YXJpYWJsZUFyZ3M/Yzw9ci5udW1BcmdzOmM9PT1yLm51bUFyZ3MpYnJlYWs7Yz0wO2NvbnRpbnVlfWMrK31pZigyPT09aSlicmVha31lbHNlIGk9MDtpZigtMT09PWEpe3dhcm4oImZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kOiBSZWFjaGVkIHRoZSBlbmQgb2YgdGhlIHN0cmVhbSB3aXRob3V0IGZpbmRpbmcgYSB2YWxpZCBFSSBtYXJrZXIiKTtpZihuKXt3YXJuKCcuLi4gdHJ5aW5nIHRvIHJlY292ZXIgYnkgdXNpbmcgdGhlIGxhc3QgIkVJIiBvY2N1cnJlbmNlLicpO2Uuc2tpcCgtKGUucG9zLW4pKX19bGV0IHM9NDtlLnNraXAoLXMpO2E9ZS5wZWVrQnl0ZSgpO2Uuc2tpcChzKTtpc1doaXRlU3BhY2UoYSl8fHMtLTtyZXR1cm4gZS5wb3Mtcy1yfWZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoZSl7Y29uc3QgdD1lLnBvcztsZXQgcixhLG49ITE7Zm9yKDstMSE9PShyPWUuZ2V0Qnl0ZSgpKTspaWYoMjU1PT09cil7c3dpdGNoKGUuZ2V0Qnl0ZSgpKXtjYXNlIDA6YnJlYWs7Y2FzZSAyNTU6ZS5za2lwKC0xKTticmVhaztjYXNlIDIxNzpuPSEwO2JyZWFrO2Nhc2UgMTkyOmNhc2UgMTkzOmNhc2UgMTk0OmNhc2UgMTk1OmNhc2UgMTk3OmNhc2UgMTk4OmNhc2UgMTk5OmNhc2UgMjAxOmNhc2UgMjAyOmNhc2UgMjAzOmNhc2UgMjA1OmNhc2UgMjA2OmNhc2UgMjA3OmNhc2UgMTk2OmNhc2UgMjA0OmNhc2UgMjE4OmNhc2UgMjE5OmNhc2UgMjIwOmNhc2UgMjIxOmNhc2UgMjIyOmNhc2UgMjIzOmNhc2UgMjI0OmNhc2UgMjI1OmNhc2UgMjI2OmNhc2UgMjI3OmNhc2UgMjI4OmNhc2UgMjI5OmNhc2UgMjMwOmNhc2UgMjMxOmNhc2UgMjMyOmNhc2UgMjMzOmNhc2UgMjM0OmNhc2UgMjM1OmNhc2UgMjM2OmNhc2UgMjM3OmNhc2UgMjM4OmNhc2UgMjM5OmNhc2UgMjU0OmE9ZS5nZXRVaW50MTYoKTthPjI/ZS5za2lwKGEtMik6ZS5za2lwKC0yKX1pZihuKWJyZWFrfWNvbnN0IGk9ZS5wb3MtdDtpZigtMT09PXIpe3dhcm4oIklubGluZSBEQ1REZWNvZGUgaW1hZ2Ugc3RyZWFtOiBFT0kgbWFya2VyIG5vdCBmb3VuZCwgc2VhcmNoaW5nIGZvciAvRUkvIGluc3RlYWQuIik7ZS5za2lwKC1pKTtyZXR1cm4gdGhpcy5maW5kRGVmYXVsdElubGluZVN0cmVhbUVuZChlKX10aGlzLmlubGluZVN0cmVhbVNraXBFSShlKTtyZXR1cm4gaX1maW5kQVNDSUk4NURlY29kZUlubGluZVN0cmVhbUVuZChlKXtjb25zdCB0PWUucG9zO2xldCByO2Zvcig7LTEhPT0ocj1lLmdldEJ5dGUoKSk7KWlmKDEyNj09PXIpe2NvbnN0IHQ9ZS5wb3M7cj1lLnBlZWtCeXRlKCk7Zm9yKDtpc1doaXRlU3BhY2Uocik7KXtlLnNraXAoKTtyPWUucGVla0J5dGUoKX1pZig2Mj09PXIpe2Uuc2tpcCgpO2JyZWFrfWlmKGUucG9zPnQpe2NvbnN0IHQ9ZS5wZWVrQnl0ZXMoMik7aWYoNjk9PT10WzBdJiY3Mz09PXRbMV0pYnJlYWt9fWNvbnN0IGE9ZS5wb3MtdDtpZigtMT09PXIpe3dhcm4oIklubGluZSBBU0NJSTg1RGVjb2RlIGltYWdlIHN0cmVhbTogRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpO2Uuc2tpcCgtYSk7cmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoZSl9dGhpcy5pbmxpbmVTdHJlYW1Ta2lwRUkoZSk7cmV0dXJuIGF9ZmluZEFTQ0lJSGV4RGVjb2RlSW5saW5lU3RyZWFtRW5kKGUpe2NvbnN0IHQ9ZS5wb3M7bGV0IHI7Zm9yKDstMSE9PShyPWUuZ2V0Qnl0ZSgpKSYmNjIhPT1yOyk7Y29uc3QgYT1lLnBvcy10O2lmKC0xPT09cil7d2FybigiSW5saW5lIEFTQ0lJSGV4RGVjb2RlIGltYWdlIHN0cmVhbTogRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpO2Uuc2tpcCgtYSk7cmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoZSl9dGhpcy5pbmxpbmVTdHJlYW1Ta2lwRUkoZSk7cmV0dXJuIGF9aW5saW5lU3RyZWFtU2tpcEVJKGUpe2xldCB0LHI9MDtmb3IoOy0xIT09KHQ9ZS5nZXRCeXRlKCkpOylpZigwPT09cilyPTY5PT09dD8xOjA7ZWxzZSBpZigxPT09cilyPTczPT09dD8yOjA7ZWxzZSBpZigyPT09cilicmVha31tYWtlSW5saW5lSW1hZ2UoZSl7Y29uc3QgdD10aGlzLmxleGVyLHI9dC5zdHJlYW0sYT1PYmplY3QuY3JlYXRlKG51bGwpO2xldCBuO2Zvcig7IWlzQ21kKHRoaXMuYnVmMSwiSUQiKSYmdGhpcy5idWYxIT09c3I7KXtpZighKHRoaXMuYnVmMSBpbnN0YW5jZW9mIE5hbWUpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiRGljdGlvbmFyeSBrZXkgbXVzdCBiZSBhIG5hbWUgb2JqZWN0Iik7Y29uc3QgdD10aGlzLmJ1ZjEubmFtZTt0aGlzLnNoaWZ0KCk7aWYodGhpcy5idWYxPT09c3IpYnJlYWs7YVt0XT10aGlzLmdldE9iaihlKX0tMSE9PXQuYmVnaW5JbmxpbmVJbWFnZVBvcyYmKG49ci5wb3MtdC5iZWdpbklubGluZUltYWdlUG9zKTtjb25zdCBpPXRoaXMueHJlZi5mZXRjaElmUmVmKGEuRnx8YS5GaWx0ZXIpO2xldCBzO2lmKGkgaW5zdGFuY2VvZiBOYW1lKXM9aS5uYW1lO2Vsc2UgaWYoQXJyYXkuaXNBcnJheShpKSl7Y29uc3QgZT10aGlzLnhyZWYuZmV0Y2hJZlJlZihpWzBdKTtlIGluc3RhbmNlb2YgTmFtZSYmKHM9ZS5uYW1lKX1jb25zdCBvPXIucG9zO2xldCBjLGw7c3dpdGNoKHMpe2Nhc2UiRENUIjpjYXNlIkRDVERlY29kZSI6Yz10aGlzLmZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQocik7YnJlYWs7Y2FzZSJBODUiOmNhc2UiQVNDSUk4NURlY29kZSI6Yz10aGlzLmZpbmRBU0NJSTg1RGVjb2RlSW5saW5lU3RyZWFtRW5kKHIpO2JyZWFrO2Nhc2UiQUh4IjpjYXNlIkFTQ0lJSGV4RGVjb2RlIjpjPXRoaXMuZmluZEFTQ0lJSGV4RGVjb2RlSW5saW5lU3RyZWFtRW5kKHIpO2JyZWFrO2RlZmF1bHQ6Yz10aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHIpfWlmKGM8MWUzJiZuPjApe2NvbnN0IGU9ci5wb3M7ci5wb3M9dC5iZWdpbklubGluZUltYWdlUG9zO2w9ZnVuY3Rpb24gZ2V0SW5saW5lSW1hZ2VDYWNoZUtleShlKXtjb25zdCB0PVtdLHI9ZS5sZW5ndGg7bGV0IGE9MDtmb3IoO2E8ci0xOyl0LnB1c2goZVthKytdPDw4fGVbYSsrXSk7YTxyJiZ0LnB1c2goZVthXSk7cmV0dXJuIHIrIl8iK1N0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCx0KX0oci5nZXRCeXRlcyhuK2MpKTtyLnBvcz1lO2NvbnN0IGE9dGhpcy5pbWFnZUNhY2hlW2xdO2lmKHZvaWQgMCE9PWEpe3RoaXMuYnVmMj1DbWQuZ2V0KCJFSSIpO3RoaXMuc2hpZnQoKTthLnJlc2V0KCk7cmV0dXJuIGF9fWNvbnN0IGg9bmV3IERpY3QodGhpcy54cmVmKTtmb3IoY29uc3QgZSBpbiBhKWguc2V0KGUsYVtlXSk7bGV0IHU9ci5tYWtlU3ViU3RyZWFtKG8sYyxoKTtlJiYodT1lLmNyZWF0ZVN0cmVhbSh1LGMpKTt1PXRoaXMuZmlsdGVyKHUsaCxjKTt1LmRpY3Q9aDtpZih2b2lkIDAhPT1sKXt1LmNhY2hlS2V5PSJpbmxpbmVfaW1nXyIrICsrdGhpcy5faW1hZ2VJZDt0aGlzLmltYWdlQ2FjaGVbbF09dX10aGlzLmJ1ZjI9Q21kLmdldCgiRUkiKTt0aGlzLnNoaWZ0KCk7cmV0dXJuIHV9I1goZSl7Y29uc3R7c3RyZWFtOnR9PXRoaXMubGV4ZXI7dC5wb3M9ZTtjb25zdCByPW5ldyBVaW50OEFycmF5KFsxMDEsMTEwLDEwMF0pLGE9ci5sZW5ndGgsbj1bbmV3IFVpbnQ4QXJyYXkoWzExNSwxMTYsMTE0LDEwMSw5NywxMDldKSxuZXcgVWludDhBcnJheShbMTE1LDExNiwxMDEsOTcsMTA5XSksbmV3IFVpbnQ4QXJyYXkoWzExNSwxMTYsMTE0LDEwMSw5N10pXSxpPTktYTtmb3IoO3QucG9zPHQuZW5kOyl7Y29uc3Qgcz10LnBlZWtCeXRlcygyMDQ4KSxvPXMubGVuZ3RoLTk7aWYobzw9MClicmVhaztsZXQgYz0wO2Zvcig7YzxvOyl7bGV0IG89MDtmb3IoO288YSYmc1tjK29dPT09cltvXTspbysrO2lmKG8+PWEpe2xldCBhPSExO2Zvcihjb25zdCBlIG9mIG4pe2NvbnN0IHQ9ZS5sZW5ndGg7bGV0IG49MDtmb3IoO248dCYmc1tjK28rbl09PT1lW25dOyluKys7aWYobj49aSl7YT0hMDticmVha31pZihuPj10KXtpZihpc1doaXRlU3BhY2Uoc1tjK28rbl0pKXtpbmZvKGBGb3VuZCAiJHtieXRlc1RvU3RyaW5nKFsuLi5yLC4uLmVdKX0iIHdoZW4gc2VhcmNoaW5nIGZvciBlbmRzdHJlYW0gY29tbWFuZC5gKTthPSEwfWJyZWFrfX1pZihhKXt0LnBvcys9YztyZXR1cm4gdC5wb3MtZX19YysrfXQucG9zKz1vfXJldHVybi0xfW1ha2VTdHJlYW0oZSx0KXtjb25zdCByPXRoaXMubGV4ZXI7bGV0IGE9ci5zdHJlYW07ci5za2lwVG9OZXh0TGluZSgpO2NvbnN0IG49YS5wb3MtMTtsZXQgaT1lLmdldCgiTGVuZ3RoIik7aWYoIU51bWJlci5pc0ludGVnZXIoaSkpe2luZm8oYEJhZCBsZW5ndGggIiR7aSYmaS50b1N0cmluZygpfSIgaW4gc3RyZWFtLmApO2k9MH1hLnBvcz1uK2k7ci5uZXh0Q2hhcigpO2lmKHRoaXMudHJ5U2hpZnQoKSYmaXNDbWQodGhpcy5idWYyLCJlbmRzdHJlYW0iKSl0aGlzLnNoaWZ0KCk7ZWxzZXtpPXRoaXMuI1gobik7aWYoaTwwKXRocm93IG5ldyBGb3JtYXRFcnJvcigiTWlzc2luZyBlbmRzdHJlYW0gY29tbWFuZC4iKTtyLm5leHRDaGFyKCk7dGhpcy5zaGlmdCgpO3RoaXMuc2hpZnQoKX10aGlzLnNoaWZ0KCk7YT1hLm1ha2VTdWJTdHJlYW0obixpLGUpO3QmJihhPXQuY3JlYXRlU3RyZWFtKGEsaSkpO2E9dGhpcy5maWx0ZXIoYSxlLGkpO2EuZGljdD1lO3JldHVybiBhfWZpbHRlcihlLHQscil7bGV0IGE9dC5nZXQoIkYiLCJGaWx0ZXIiKSxuPXQuZ2V0KCJEUCIsIkRlY29kZVBhcm1zIik7aWYoYSBpbnN0YW5jZW9mIE5hbWUpe0FycmF5LmlzQXJyYXkobikmJndhcm4oIi9EZWNvZGVQYXJtcyBzaG91bGQgbm90IGJlIGFuIEFycmF5LCB3aGVuIC9GaWx0ZXIgaXMgYSBOYW1lLiIpO3JldHVybiB0aGlzLm1ha2VGaWx0ZXIoZSxhLm5hbWUscixuKX1sZXQgaT1yO2lmKEFycmF5LmlzQXJyYXkoYSkpe2NvbnN0IHQ9YSxyPW47Zm9yKGxldCBzPTAsbz10Lmxlbmd0aDtzPG87KytzKXthPXRoaXMueHJlZi5mZXRjaElmUmVmKHRbc10pO2lmKCEoYSBpbnN0YW5jZW9mIE5hbWUpKXRocm93IG5ldyBGb3JtYXRFcnJvcihgQmFkIGZpbHRlciBuYW1lICIke2F9ImApO249bnVsbDtBcnJheS5pc0FycmF5KHIpJiZzIGluIHImJihuPXRoaXMueHJlZi5mZXRjaElmUmVmKHJbc10pKTtlPXRoaXMubWFrZUZpbHRlcihlLGEubmFtZSxpLG4pO2k9bnVsbH19cmV0dXJuIGV9bWFrZUZpbHRlcihlLHQscixhKXtpZigwPT09cil7d2FybihgRW1wdHkgIiR7dH0iIHN0cmVhbS5gKTtyZXR1cm4gbmV3IE51bGxTdHJlYW19dHJ5e3N3aXRjaCh0KXtjYXNlIkZsIjpjYXNlIkZsYXRlRGVjb2RlIjpyZXR1cm4gYT9uZXcgUHJlZGljdG9yU3RyZWFtKG5ldyBGbGF0ZVN0cmVhbShlLHIpLHIsYSk6bmV3IEZsYXRlU3RyZWFtKGUscik7Y2FzZSJMWlciOmNhc2UiTFpXRGVjb2RlIjpsZXQgdD0xO2lmKGEpe2EuaGFzKCJFYXJseUNoYW5nZSIpJiYodD1hLmdldCgiRWFybHlDaGFuZ2UiKSk7cmV0dXJuIG5ldyBQcmVkaWN0b3JTdHJlYW0obmV3IExaV1N0cmVhbShlLHIsdCkscixhKX1yZXR1cm4gbmV3IExaV1N0cmVhbShlLHIsdCk7Y2FzZSJEQ1QiOmNhc2UiRENURGVjb2RlIjpyZXR1cm4gbmV3IEpwZWdTdHJlYW0oZSxyLGEpO2Nhc2UiSlBYIjpjYXNlIkpQWERlY29kZSI6cmV0dXJuIG5ldyBKcHhTdHJlYW0oZSxyLGEpO2Nhc2UiQTg1IjpjYXNlIkFTQ0lJODVEZWNvZGUiOnJldHVybiBuZXcgQXNjaWk4NVN0cmVhbShlLHIpO2Nhc2UiQUh4IjpjYXNlIkFTQ0lJSGV4RGVjb2RlIjpyZXR1cm4gbmV3IEFzY2lpSGV4U3RyZWFtKGUscik7Y2FzZSJDQ0YiOmNhc2UiQ0NJVFRGYXhEZWNvZGUiOnJldHVybiBuZXcgQ0NJVFRGYXhTdHJlYW0oZSxyLGEpO2Nhc2UiUkwiOmNhc2UiUnVuTGVuZ3RoRGVjb2RlIjpyZXR1cm4gbmV3IFJ1bkxlbmd0aFN0cmVhbShlLHIpO2Nhc2UiSkJJRzJEZWNvZGUiOnJldHVybiBuZXcgSmJpZzJTdHJlYW0oZSxyLGEpfXdhcm4oYEZpbHRlciAiJHt0fSIgaXMgbm90IHN1cHBvcnRlZC5gKTtyZXR1cm4gZX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKGBJbnZhbGlkIHN0cmVhbTogIiR7ZX0iYCk7cmV0dXJuIG5ldyBOdWxsU3RyZWFtfX19Y29uc3QgbmE9WzEsMCwwLDAsMCwwLDAsMCwwLDEsMSwwLDEsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwxLDAsMCwwLDAsMiwwLDAsMiwyLDAsMCwwLDAsMCwyLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDIsMCwyLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMiwwLDIsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDIsMCwyLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdO2Z1bmN0aW9uIHRvSGV4RGlnaXQoZSl7cmV0dXJuIGU+PTQ4JiZlPD01Nz8xNSZlOmU+PTY1JiZlPD03MHx8ZT49OTcmJmU8PTEwMj85KygxNSZlKTotMX1jbGFzcyBMZXhlcntjb25zdHJ1Y3RvcihlLHQ9bnVsbCl7dGhpcy5zdHJlYW09ZTt0aGlzLm5leHRDaGFyKCk7dGhpcy5zdHJCdWY9W107dGhpcy5rbm93bkNvbW1hbmRzPXQ7dGhpcy5faGV4U3RyaW5nTnVtV2Fybj0wO3RoaXMuYmVnaW5JbmxpbmVJbWFnZVBvcz0tMX1uZXh0Q2hhcigpe3JldHVybiB0aGlzLmN1cnJlbnRDaGFyPXRoaXMuc3RyZWFtLmdldEJ5dGUoKX1wZWVrQ2hhcigpe3JldHVybiB0aGlzLnN0cmVhbS5wZWVrQnl0ZSgpfWdldE51bWJlcigpe2xldCBlPXRoaXMuY3VycmVudENoYXIsdD0hMSxyPTAsYT0xO2lmKDQ1PT09ZSl7YT0tMTtlPXRoaXMubmV4dENoYXIoKTs0NT09PWUmJihlPXRoaXMubmV4dENoYXIoKSl9ZWxzZSA0Mz09PWUmJihlPXRoaXMubmV4dENoYXIoKSk7aWYoMTA9PT1lfHwxMz09PWUpZG97ZT10aGlzLm5leHRDaGFyKCl9d2hpbGUoMTA9PT1lfHwxMz09PWUpO2lmKDQ2PT09ZSl7cj0xMDtlPXRoaXMubmV4dENoYXIoKX1pZihlPDQ4fHxlPjU3KXtjb25zdCB0PWBJbnZhbGlkIG51bWJlcjogJHtTdHJpbmcuZnJvbUNoYXJDb2RlKGUpfSAoY2hhckNvZGUgJHtlfSlgO2lmKGlzV2hpdGVTcGFjZShlKXx8NDA9PT1lfHw2MD09PWV8fC0xPT09ZSl7aW5mbyhgTGV4ZXIuZ2V0TnVtYmVyIC0gIiR7dH0iLmApO3JldHVybiAwfXRocm93IG5ldyBGb3JtYXRFcnJvcih0KX1sZXQgbj1lLTQ4LGk9MCxzPTE7Zm9yKDsoZT10aGlzLm5leHRDaGFyKCkpPj0wOylpZihlPj00OCYmZTw9NTcpe2NvbnN0IGE9ZS00ODtpZih0KWk9MTAqaSthO2Vsc2V7MCE9PXImJihyKj0xMCk7bj0xMCpuK2F9fWVsc2UgaWYoNDY9PT1lKXtpZigwIT09cilicmVhaztyPTF9ZWxzZSBpZig0NT09PWUpd2FybigiQmFkbHkgZm9ybWF0dGVkIG51bWJlcjogbWludXMgc2lnbiBpbiB0aGUgbWlkZGxlIik7ZWxzZXtpZig2OSE9PWUmJjEwMSE9PWUpYnJlYWs7ZT10aGlzLnBlZWtDaGFyKCk7aWYoNDM9PT1lfHw0NT09PWUpe3M9NDU9PT1lPy0xOjE7dGhpcy5uZXh0Q2hhcigpfWVsc2UgaWYoZTw0OHx8ZT41NylicmVhazt0PSEwfTAhPT1yJiYobi89cik7dCYmKG4qPTEwKioocyppKSk7cmV0dXJuIGEqbn1nZXRTdHJpbmcoKXtsZXQgZT0xLHQ9ITE7Y29uc3Qgcj10aGlzLnN0ckJ1ZjtyLmxlbmd0aD0wO2xldCBhPXRoaXMubmV4dENoYXIoKTtmb3IoOzspe2xldCBuPSExO3N3aXRjaCgwfGEpe2Nhc2UtMTp3YXJuKCJVbnRlcm1pbmF0ZWQgc3RyaW5nIik7dD0hMDticmVhaztjYXNlIDQwOisrZTtyLnB1c2goIigiKTticmVhaztjYXNlIDQxOmlmKDA9PT0tLWUpe3RoaXMubmV4dENoYXIoKTt0PSEwfWVsc2Ugci5wdXNoKCIpIik7YnJlYWs7Y2FzZSA5MjphPXRoaXMubmV4dENoYXIoKTtzd2l0Y2goYSl7Y2FzZS0xOndhcm4oIlVudGVybWluYXRlZCBzdHJpbmciKTt0PSEwO2JyZWFrO2Nhc2UgMTEwOnIucHVzaCgiXG4iKTticmVhaztjYXNlIDExNDpyLnB1c2goIlxyIik7YnJlYWs7Y2FzZSAxMTY6ci5wdXNoKCJcdCIpO2JyZWFrO2Nhc2UgOTg6ci5wdXNoKCJcYiIpO2JyZWFrO2Nhc2UgMTAyOnIucHVzaCgiXGYiKTticmVhaztjYXNlIDkyOmNhc2UgNDA6Y2FzZSA0MTpyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhKSk7YnJlYWs7Y2FzZSA0ODpjYXNlIDQ5OmNhc2UgNTA6Y2FzZSA1MTpjYXNlIDUyOmNhc2UgNTM6Y2FzZSA1NDpjYXNlIDU1OmxldCBlPTE1JmE7YT10aGlzLm5leHRDaGFyKCk7bj0hMDtpZihhPj00OCYmYTw9NTUpe2U9KGU8PDMpKygxNSZhKTthPXRoaXMubmV4dENoYXIoKTtpZihhPj00OCYmYTw9NTUpe249ITE7ZT0oZTw8MykrKDE1JmEpfX1yLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShlKSk7YnJlYWs7Y2FzZSAxMzoxMD09PXRoaXMucGVla0NoYXIoKSYmdGhpcy5uZXh0Q2hhcigpO2JyZWFrO2Nhc2UgMTA6YnJlYWs7ZGVmYXVsdDpyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhKSl9YnJlYWs7ZGVmYXVsdDpyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhKSl9aWYodClicmVhaztufHwoYT10aGlzLm5leHRDaGFyKCkpfXJldHVybiByLmpvaW4oIiIpfWdldE5hbWUoKXtsZXQgZSx0O2NvbnN0IHI9dGhpcy5zdHJCdWY7ci5sZW5ndGg9MDtmb3IoOyhlPXRoaXMubmV4dENoYXIoKSk+PTAmJiFuYVtlXTspaWYoMzU9PT1lKXtlPXRoaXMubmV4dENoYXIoKTtpZihuYVtlXSl7d2FybigiTGV4ZXJfZ2V0TmFtZTogTlVNQkVSIFNJR04gKCMpIHNob3VsZCBiZSBmb2xsb3dlZCBieSBhIGhleGFkZWNpbWFsIG51bWJlci4iKTtyLnB1c2goIiMiKTticmVha31jb25zdCBhPXRvSGV4RGlnaXQoZSk7aWYoLTEhPT1hKXt0PWU7ZT10aGlzLm5leHRDaGFyKCk7Y29uc3Qgbj10b0hleERpZ2l0KGUpO2lmKC0xPT09bil7d2FybihgTGV4ZXJfZ2V0TmFtZTogSWxsZWdhbCBkaWdpdCAoJHtTdHJpbmcuZnJvbUNoYXJDb2RlKGUpfSkgaW4gaGV4YWRlY2ltYWwgbnVtYmVyLmApO3IucHVzaCgiIyIsU3RyaW5nLmZyb21DaGFyQ29kZSh0KSk7aWYobmFbZV0pYnJlYWs7ci5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoZSkpO2NvbnRpbnVlfXIucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGE8PDR8bikpfWVsc2Ugci5wdXNoKCIjIixTdHJpbmcuZnJvbUNoYXJDb2RlKGUpKX1lbHNlIHIucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGUpKTtyLmxlbmd0aD4xMjcmJndhcm4oYE5hbWUgdG9rZW4gaXMgbG9uZ2VyIHRoYW4gYWxsb3dlZCBieSB0aGUgc3BlYzogJHtyLmxlbmd0aH1gKTtyZXR1cm4gTmFtZS5nZXQoci5qb2luKCIiKSl9X2hleFN0cmluZ1dhcm4oZSl7NSE9PXRoaXMuX2hleFN0cmluZ051bVdhcm4rKz90aGlzLl9oZXhTdHJpbmdOdW1XYXJuPjV8fHdhcm4oYGdldEhleFN0cmluZyAtIGlnbm9yaW5nIGludmFsaWQgY2hhcmFjdGVyOiAke2V9YCk6d2FybigiZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgYWRkaXRpb25hbCBpbnZhbGlkIGNoYXJhY3RlcnMuIil9Z2V0SGV4U3RyaW5nKCl7Y29uc3QgZT10aGlzLnN0ckJ1ZjtlLmxlbmd0aD0wO2xldCB0PXRoaXMuY3VycmVudENoYXIscj0tMSxhPS0xO3RoaXMuX2hleFN0cmluZ051bVdhcm49MDtmb3IoOzspe2lmKHQ8MCl7d2FybigiVW50ZXJtaW5hdGVkIGhleCBzdHJpbmciKTticmVha31pZig2Mj09PXQpe3RoaXMubmV4dENoYXIoKTticmVha31pZigxIT09bmFbdF0pe2E9dG9IZXhEaWdpdCh0KTtpZigtMT09PWEpdGhpcy5faGV4U3RyaW5nV2Fybih0KTtlbHNlIGlmKC0xPT09cilyPWE7ZWxzZXtlLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShyPDw0fGEpKTtyPS0xfXQ9dGhpcy5uZXh0Q2hhcigpfWVsc2UgdD10aGlzLm5leHRDaGFyKCl9LTEhPT1yJiZlLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShyPDw0KSk7cmV0dXJuIGUuam9pbigiIil9Z2V0T2JqKCl7bGV0IGU9ITEsdD10aGlzLmN1cnJlbnRDaGFyO2Zvcig7Oyl7aWYodDwwKXJldHVybiBzcjtpZihlKTEwIT09dCYmMTMhPT10fHwoZT0hMSk7ZWxzZSBpZigzNz09PXQpZT0hMDtlbHNlIGlmKDEhPT1uYVt0XSlicmVhazt0PXRoaXMubmV4dENoYXIoKX1zd2l0Y2goMHx0KXtjYXNlIDQ4OmNhc2UgNDk6Y2FzZSA1MDpjYXNlIDUxOmNhc2UgNTI6Y2FzZSA1MzpjYXNlIDU0OmNhc2UgNTU6Y2FzZSA1NjpjYXNlIDU3OmNhc2UgNDM6Y2FzZSA0NTpjYXNlIDQ2OnJldHVybiB0aGlzLmdldE51bWJlcigpO2Nhc2UgNDA6cmV0dXJuIHRoaXMuZ2V0U3RyaW5nKCk7Y2FzZSA0NzpyZXR1cm4gdGhpcy5nZXROYW1lKCk7Y2FzZSA5MTp0aGlzLm5leHRDaGFyKCk7cmV0dXJuIENtZC5nZXQoIlsiKTtjYXNlIDkzOnRoaXMubmV4dENoYXIoKTtyZXR1cm4gQ21kLmdldCgiXSIpO2Nhc2UgNjA6dD10aGlzLm5leHRDaGFyKCk7aWYoNjA9PT10KXt0aGlzLm5leHRDaGFyKCk7cmV0dXJuIENtZC5nZXQoIjw8Iil9cmV0dXJuIHRoaXMuZ2V0SGV4U3RyaW5nKCk7Y2FzZSA2Mjp0PXRoaXMubmV4dENoYXIoKTtpZig2Mj09PXQpe3RoaXMubmV4dENoYXIoKTtyZXR1cm4gQ21kLmdldCgiPj4iKX1yZXR1cm4gQ21kLmdldCgiPiIpO2Nhc2UgMTIzOnRoaXMubmV4dENoYXIoKTtyZXR1cm4gQ21kLmdldCgieyIpO2Nhc2UgMTI1OnRoaXMubmV4dENoYXIoKTtyZXR1cm4gQ21kLmdldCgifSIpO2Nhc2UgNDE6dGhpcy5uZXh0Q2hhcigpO3Rocm93IG5ldyBGb3JtYXRFcnJvcihgSWxsZWdhbCBjaGFyYWN0ZXI6ICR7dH1gKX1sZXQgcj1TdHJpbmcuZnJvbUNoYXJDb2RlKHQpO2lmKHQ8MzJ8fHQ+MTI3KXtjb25zdCBlPXRoaXMucGVla0NoYXIoKTtpZihlPj0zMiYmZTw9MTI3KXt0aGlzLm5leHRDaGFyKCk7cmV0dXJuIENtZC5nZXQocil9fWNvbnN0IGE9dGhpcy5rbm93bkNvbW1hbmRzO2xldCBuPXZvaWQgMCE9PWE/LltyXTtmb3IoOyh0PXRoaXMubmV4dENoYXIoKSk+PTAmJiFuYVt0XTspe2NvbnN0IGU9citTdHJpbmcuZnJvbUNoYXJDb2RlKHQpO2lmKG4mJnZvaWQgMD09PWFbZV0pYnJlYWs7aWYoMTI4PT09ci5sZW5ndGgpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBDb21tYW5kIHRva2VuIHRvbyBsb25nOiAke3IubGVuZ3RofWApO3I9ZTtuPXZvaWQgMCE9PWE/LltyXX1pZigidHJ1ZSI9PT1yKXJldHVybiEwO2lmKCJmYWxzZSI9PT1yKXJldHVybiExO2lmKCJudWxsIj09PXIpcmV0dXJuIG51bGw7IkJJIj09PXImJih0aGlzLmJlZ2luSW5saW5lSW1hZ2VQb3M9dGhpcy5zdHJlYW0ucG9zKTtyZXR1cm4gQ21kLmdldChyKX1za2lwVG9OZXh0TGluZSgpe2xldCBlPXRoaXMuY3VycmVudENoYXI7Zm9yKDtlPj0wOyl7aWYoMTM9PT1lKXtlPXRoaXMubmV4dENoYXIoKTsxMD09PWUmJnRoaXMubmV4dENoYXIoKTticmVha31pZigxMD09PWUpe3RoaXMubmV4dENoYXIoKTticmVha31lPXRoaXMubmV4dENoYXIoKX19fWNsYXNzIExpbmVhcml6YXRpb257c3RhdGljIGNyZWF0ZShlKXtmdW5jdGlvbiBnZXRJbnQoZSx0LHI9ITEpe2NvbnN0IGE9ZS5nZXQodCk7aWYoTnVtYmVyLmlzSW50ZWdlcihhKSYmKHI/YT49MDphPjApKXJldHVybiBhO3Rocm93IG5ldyBFcnJvcihgVGhlICIke3R9IiBwYXJhbWV0ZXIgaW4gdGhlIGxpbmVhcml6YXRpb24gZGljdGlvbmFyeSBpcyBpbnZhbGlkLmApfWNvbnN0IHQ9bmV3IFBhcnNlcih7bGV4ZXI6bmV3IExleGVyKGUpLHhyZWY6bnVsbH0pLHI9dC5nZXRPYmooKSxhPXQuZ2V0T2JqKCksbj10LmdldE9iaigpLGk9dC5nZXRPYmooKTtsZXQgcyxvO2lmKCEoTnVtYmVyLmlzSW50ZWdlcihyKSYmTnVtYmVyLmlzSW50ZWdlcihhKSYmaXNDbWQobiwib2JqIikmJmkgaW5zdGFuY2VvZiBEaWN0JiYibnVtYmVyIj09dHlwZW9mKHM9aS5nZXQoIkxpbmVhcml6ZWQiKSkmJnM+MCkpcmV0dXJuIG51bGw7aWYoKG89Z2V0SW50KGksIkwiKSkhPT1lLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoJ1RoZSAiTCIgcGFyYW1ldGVyIGluIHRoZSBsaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgZG9lcyBub3QgZXF1YWwgdGhlIHN0cmVhbSBsZW5ndGguJyk7cmV0dXJue2xlbmd0aDpvLGhpbnRzOmZ1bmN0aW9uIGdldEhpbnRzKGUpe2NvbnN0IHQ9ZS5nZXQoIkgiKTtsZXQgcjtpZihBcnJheS5pc0FycmF5KHQpJiYoMj09PShyPXQubGVuZ3RoKXx8ND09PXIpKXtmb3IobGV0IGU9MDtlPHI7ZSsrKXtjb25zdCByPXRbZV07aWYoIShOdW1iZXIuaXNJbnRlZ2VyKHIpJiZyPjApKXRocm93IG5ldyBFcnJvcihgSGludCAoJHtlfSkgaW4gdGhlIGxpbmVhcml6YXRpb24gZGljdGlvbmFyeSBpcyBpbnZhbGlkLmApfXJldHVybiB0fXRocm93IG5ldyBFcnJvcigiSGludCBhcnJheSBpbiB0aGUgbGluZWFyaXphdGlvbiBkaWN0aW9uYXJ5IGlzIGludmFsaWQuIil9KGkpLG9iamVjdE51bWJlckZpcnN0OmdldEludChpLCJPIiksZW5kRmlyc3Q6Z2V0SW50KGksIkUiKSxudW1QYWdlczpnZXRJbnQoaSwiTiIpLG1haW5YUmVmRW50cmllc09mZnNldDpnZXRJbnQoaSwiVCIpLHBhZ2VGaXJzdDppLmhhcygiUCIpP2dldEludChpLCJQIiwhMCk6MH19fWNvbnN0IGlhPVsiQWRvYmUtR0IxLVVDUzIiLCJBZG9iZS1DTlMxLVVDUzIiLCJBZG9iZS1KYXBhbjEtVUNTMiIsIkFkb2JlLUtvcmVhMS1VQ1MyIiwiNzgtRVVDLUgiLCI3OC1FVUMtViIsIjc4LUgiLCI3OC1SS1NKLUgiLCI3OC1SS1NKLVYiLCI3OC1WIiwiNzhtcy1SS1NKLUgiLCI3OG1zLVJLU0otViIsIjgzcHYtUktTSi1IIiwiOTBtcy1SS1NKLUgiLCI5MG1zLVJLU0otViIsIjkwbXNwLVJLU0otSCIsIjkwbXNwLVJLU0otViIsIjkwcHYtUktTSi1IIiwiOTBwdi1SS1NKLVYiLCJBZGQtSCIsIkFkZC1SS1NKLUgiLCJBZGQtUktTSi1WIiwiQWRkLVYiLCJBZG9iZS1DTlMxLTAiLCJBZG9iZS1DTlMxLTEiLCJBZG9iZS1DTlMxLTIiLCJBZG9iZS1DTlMxLTMiLCJBZG9iZS1DTlMxLTQiLCJBZG9iZS1DTlMxLTUiLCJBZG9iZS1DTlMxLTYiLCJBZG9iZS1HQjEtMCIsIkFkb2JlLUdCMS0xIiwiQWRvYmUtR0IxLTIiLCJBZG9iZS1HQjEtMyIsIkFkb2JlLUdCMS00IiwiQWRvYmUtR0IxLTUiLCJBZG9iZS1KYXBhbjEtMCIsIkFkb2JlLUphcGFuMS0xIiwiQWRvYmUtSmFwYW4xLTIiLCJBZG9iZS1KYXBhbjEtMyIsIkFkb2JlLUphcGFuMS00IiwiQWRvYmUtSmFwYW4xLTUiLCJBZG9iZS1KYXBhbjEtNiIsIkFkb2JlLUtvcmVhMS0wIiwiQWRvYmUtS29yZWExLTEiLCJBZG9iZS1Lb3JlYTEtMiIsIkI1LUgiLCJCNS1WIiwiQjVwYy1IIiwiQjVwYy1WIiwiQ05TLUVVQy1IIiwiQ05TLUVVQy1WIiwiQ05TMS1IIiwiQ05TMS1WIiwiQ05TMi1IIiwiQ05TMi1WIiwiRVRISy1CNS1IIiwiRVRISy1CNS1WIiwiRVRlbi1CNS1IIiwiRVRlbi1CNS1WIiwiRVRlbm1zLUI1LUgiLCJFVGVubXMtQjUtViIsIkVVQy1IIiwiRVVDLVYiLCJFeHQtSCIsIkV4dC1SS1NKLUgiLCJFeHQtUktTSi1WIiwiRXh0LVYiLCJHQi1FVUMtSCIsIkdCLUVVQy1WIiwiR0ItSCIsIkdCLVYiLCJHQkstRVVDLUgiLCJHQkstRVVDLVYiLCJHQksySy1IIiwiR0JLMkstViIsIkdCS3AtRVVDLUgiLCJHQktwLUVVQy1WIiwiR0JULUVVQy1IIiwiR0JULUVVQy1WIiwiR0JULUgiLCJHQlQtViIsIkdCVHBjLUVVQy1IIiwiR0JUcGMtRVVDLVYiLCJHQnBjLUVVQy1IIiwiR0JwYy1FVUMtViIsIkgiLCJIS2RsYS1CNS1IIiwiSEtkbGEtQjUtViIsIkhLZGxiLUI1LUgiLCJIS2RsYi1CNS1WIiwiSEtnY2NzLUI1LUgiLCJIS2djY3MtQjUtViIsIkhLbTMxNC1CNS1IIiwiSEttMzE0LUI1LVYiLCJIS200NzEtQjUtSCIsIkhLbTQ3MS1CNS1WIiwiSEtzY3MtQjUtSCIsIkhLc2NzLUI1LVYiLCJIYW5rYWt1IiwiSGlyYWdhbmEiLCJLU0MtRVVDLUgiLCJLU0MtRVVDLVYiLCJLU0MtSCIsIktTQy1Kb2hhYi1IIiwiS1NDLUpvaGFiLVYiLCJLU0MtViIsIktTQ21zLVVIQy1IIiwiS1NDbXMtVUhDLUhXLUgiLCJLU0Ntcy1VSEMtSFctViIsIktTQ21zLVVIQy1WIiwiS1NDcGMtRVVDLUgiLCJLU0NwYy1FVUMtViIsIkthdGFrYW5hIiwiTldQLUgiLCJOV1AtViIsIlJLU0otSCIsIlJLU0otViIsIlJvbWFuIiwiVW5pQ05TLVVDUzItSCIsIlVuaUNOUy1VQ1MyLVYiLCJVbmlDTlMtVVRGMTYtSCIsIlVuaUNOUy1VVEYxNi1WIiwiVW5pQ05TLVVURjMyLUgiLCJVbmlDTlMtVVRGMzItViIsIlVuaUNOUy1VVEY4LUgiLCJVbmlDTlMtVVRGOC1WIiwiVW5pR0ItVUNTMi1IIiwiVW5pR0ItVUNTMi1WIiwiVW5pR0ItVVRGMTYtSCIsIlVuaUdCLVVURjE2LVYiLCJVbmlHQi1VVEYzMi1IIiwiVW5pR0ItVVRGMzItViIsIlVuaUdCLVVURjgtSCIsIlVuaUdCLVVURjgtViIsIlVuaUpJUy1VQ1MyLUgiLCJVbmlKSVMtVUNTMi1IVy1IIiwiVW5pSklTLVVDUzItSFctViIsIlVuaUpJUy1VQ1MyLVYiLCJVbmlKSVMtVVRGMTYtSCIsIlVuaUpJUy1VVEYxNi1WIiwiVW5pSklTLVVURjMyLUgiLCJVbmlKSVMtVVRGMzItViIsIlVuaUpJUy1VVEY4LUgiLCJVbmlKSVMtVVRGOC1WIiwiVW5pSklTMjAwNC1VVEYxNi1IIiwiVW5pSklTMjAwNC1VVEYxNi1WIiwiVW5pSklTMjAwNC1VVEYzMi1IIiwiVW5pSklTMjAwNC1VVEYzMi1WIiwiVW5pSklTMjAwNC1VVEY4LUgiLCJVbmlKSVMyMDA0LVVURjgtViIsIlVuaUpJU1Byby1VQ1MyLUhXLVYiLCJVbmlKSVNQcm8tVUNTMi1WIiwiVW5pSklTUHJvLVVURjgtViIsIlVuaUpJU1gwMjEzLVVURjMyLUgiLCJVbmlKSVNYMDIxMy1VVEYzMi1WIiwiVW5pSklTWDAyMTMyMDA0LVVURjMyLUgiLCJVbmlKSVNYMDIxMzIwMDQtVVRGMzItViIsIlVuaUtTLVVDUzItSCIsIlVuaUtTLVVDUzItViIsIlVuaUtTLVVURjE2LUgiLCJVbmlLUy1VVEYxNi1WIiwiVW5pS1MtVVRGMzItSCIsIlVuaUtTLVVURjMyLVYiLCJVbmlLUy1VVEY4LUgiLCJVbmlLUy1VVEY4LVYiLCJWIiwiV1AtU3ltYm9sIl0sc2E9MioqMjQtMTtjbGFzcyBDTWFwe2NvbnN0cnVjdG9yKGU9ITEpe3RoaXMuY29kZXNwYWNlUmFuZ2VzPVtbXSxbXSxbXSxbXV07dGhpcy5udW1Db2Rlc3BhY2VSYW5nZXM9MDt0aGlzLl9tYXA9W107dGhpcy5uYW1lPSIiO3RoaXMudmVydGljYWw9ITE7dGhpcy51c2VDTWFwPW51bGw7dGhpcy5idWlsdEluQ01hcD1lfWFkZENvZGVzcGFjZVJhbmdlKGUsdCxyKXt0aGlzLmNvZGVzcGFjZVJhbmdlc1tlLTFdLnB1c2godCxyKTt0aGlzLm51bUNvZGVzcGFjZVJhbmdlcysrfW1hcENpZFJhbmdlKGUsdCxyKXtpZih0LWU+c2EpdGhyb3cgbmV3IEVycm9yKCJtYXBDaWRSYW5nZSAtIGlnbm9yaW5nIGRhdGEgYWJvdmUgTUFYX01BUF9SQU5HRS4iKTtmb3IoO2U8PXQ7KXRoaXMuX21hcFtlKytdPXIrK31tYXBCZlJhbmdlKGUsdCxyKXtpZih0LWU+c2EpdGhyb3cgbmV3IEVycm9yKCJtYXBCZlJhbmdlIC0gaWdub3JpbmcgZGF0YSBhYm92ZSBNQVhfTUFQX1JBTkdFLiIpO2NvbnN0IGE9ci5sZW5ndGgtMTtmb3IoO2U8PXQ7KXt0aGlzLl9tYXBbZSsrXT1yO2NvbnN0IHQ9ci5jaGFyQ29kZUF0KGEpKzE7dD4yNTU/cj1yLnN1YnN0cmluZygwLGEtMSkrU3RyaW5nLmZyb21DaGFyQ29kZShyLmNoYXJDb2RlQXQoYS0xKSsxKSsiXDAiOnI9ci5zdWJzdHJpbmcoMCxhKStTdHJpbmcuZnJvbUNoYXJDb2RlKHQpfX1tYXBCZlJhbmdlVG9BcnJheShlLHQscil7aWYodC1lPnNhKXRocm93IG5ldyBFcnJvcigibWFwQmZSYW5nZVRvQXJyYXkgLSBpZ25vcmluZyBkYXRhIGFib3ZlIE1BWF9NQVBfUkFOR0UuIik7Y29uc3QgYT1yLmxlbmd0aDtsZXQgbj0wO2Zvcig7ZTw9dCYmbjxhOyl7dGhpcy5fbWFwW2VdPXJbbisrXTsrK2V9fW1hcE9uZShlLHQpe3RoaXMuX21hcFtlXT10fWxvb2t1cChlKXtyZXR1cm4gdGhpcy5fbWFwW2VdfWNvbnRhaW5zKGUpe3JldHVybiB2b2lkIDAhPT10aGlzLl9tYXBbZV19Zm9yRWFjaChlKXtjb25zdCB0PXRoaXMuX21hcCxyPXQubGVuZ3RoO2lmKHI8PTY1NTM2KWZvcihsZXQgYT0wO2E8cjthKyspdm9pZCAwIT09dFthXSYmZShhLHRbYV0pO2Vsc2UgZm9yKGNvbnN0IHIgaW4gdCllKHIsdFtyXSl9Y2hhckNvZGVPZihlKXtjb25zdCB0PXRoaXMuX21hcDtpZih0Lmxlbmd0aDw9NjU1MzYpcmV0dXJuIHQuaW5kZXhPZihlKTtmb3IoY29uc3QgciBpbiB0KWlmKHRbcl09PT1lKXJldHVybiAwfHI7cmV0dXJuLTF9Z2V0TWFwKCl7cmV0dXJuIHRoaXMuX21hcH1yZWFkQ2hhckNvZGUoZSx0LHIpe2xldCBhPTA7Y29uc3Qgbj10aGlzLmNvZGVzcGFjZVJhbmdlcztmb3IobGV0IGk9MCxzPW4ubGVuZ3RoO2k8cztpKyspe2E9KGE8PDh8ZS5jaGFyQ29kZUF0KHQraSkpPj4+MDtjb25zdCBzPW5baV07Zm9yKGxldCBlPTAsdD1zLmxlbmd0aDtlPHQ7KXtjb25zdCB0PXNbZSsrXSxuPXNbZSsrXTtpZihhPj10JiZhPD1uKXtyLmNoYXJjb2RlPWE7ci5sZW5ndGg9aSsxO3JldHVybn19fXIuY2hhcmNvZGU9MDtyLmxlbmd0aD0xfWdldENoYXJDb2RlTGVuZ3RoKGUpe2NvbnN0IHQ9dGhpcy5jb2Rlc3BhY2VSYW5nZXM7Zm9yKGxldCByPTAsYT10Lmxlbmd0aDtyPGE7cisrKXtjb25zdCBhPXRbcl07Zm9yKGxldCB0PTAsbj1hLmxlbmd0aDt0PG47KXtjb25zdCBuPWFbdCsrXSxpPWFbdCsrXTtpZihlPj1uJiZlPD1pKXJldHVybiByKzF9fXJldHVybiAxfWdldCBsZW5ndGgoKXtyZXR1cm4gdGhpcy5fbWFwLmxlbmd0aH1nZXQgaXNJZGVudGl0eUNNYXAoKXtpZigiSWRlbnRpdHktSCIhPT10aGlzLm5hbWUmJiJJZGVudGl0eS1WIiE9PXRoaXMubmFtZSlyZXR1cm4hMTtpZig2NTUzNiE9PXRoaXMuX21hcC5sZW5ndGgpcmV0dXJuITE7Zm9yKGxldCBlPTA7ZTw2NTUzNjtlKyspaWYodGhpcy5fbWFwW2VdIT09ZSlyZXR1cm4hMTtyZXR1cm4hMH19Y2xhc3MgSWRlbnRpdHlDTWFwIGV4dGVuZHMgQ01hcHtjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKCk7dGhpcy52ZXJ0aWNhbD1lO3RoaXMuYWRkQ29kZXNwYWNlUmFuZ2UodCwwLDY1NTM1KX1tYXBDaWRSYW5nZShlLHQscil7dW5yZWFjaGFibGUoInNob3VsZCBub3QgY2FsbCBtYXBDaWRSYW5nZSIpfW1hcEJmUmFuZ2UoZSx0LHIpe3VucmVhY2hhYmxlKCJzaG91bGQgbm90IGNhbGwgbWFwQmZSYW5nZSIpfW1hcEJmUmFuZ2VUb0FycmF5KGUsdCxyKXt1bnJlYWNoYWJsZSgic2hvdWxkIG5vdCBjYWxsIG1hcEJmUmFuZ2VUb0FycmF5Iil9bWFwT25lKGUsdCl7dW5yZWFjaGFibGUoInNob3VsZCBub3QgY2FsbCBtYXBDaWRPbmUiKX1sb29rdXAoZSl7cmV0dXJuIE51bWJlci5pc0ludGVnZXIoZSkmJmU8PTY1NTM1P2U6dm9pZCAwfWNvbnRhaW5zKGUpe3JldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGUpJiZlPD02NTUzNX1mb3JFYWNoKGUpe2ZvcihsZXQgdD0wO3Q8PTY1NTM1O3QrKyllKHQsdCl9Y2hhckNvZGVPZihlKXtyZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihlKSYmZTw9NjU1MzU/ZTotMX1nZXRNYXAoKXtjb25zdCBlPW5ldyBBcnJheSg2NTUzNik7Zm9yKGxldCB0PTA7dDw9NjU1MzU7dCsrKWVbdF09dDtyZXR1cm4gZX1nZXQgbGVuZ3RoKCl7cmV0dXJuIDY1NTM2fWdldCBpc0lkZW50aXR5Q01hcCgpe3VucmVhY2hhYmxlKCJzaG91bGQgbm90IGFjY2VzcyAuaXNJZGVudGl0eUNNYXAiKX19ZnVuY3Rpb24gc3RyVG9JbnQoZSl7bGV0IHQ9MDtmb3IobGV0IHI9MDtyPGUubGVuZ3RoO3IrKyl0PXQ8PDh8ZS5jaGFyQ29kZUF0KHIpO3JldHVybiB0Pj4+MH1mdW5jdGlvbiBleHBlY3RTdHJpbmcoZSl7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBGb3JtYXRFcnJvcigiTWFsZm9ybWVkIENNYXA6IGV4cGVjdGVkIHN0cmluZy4iKX1mdW5jdGlvbiBleHBlY3RJbnQoZSl7aWYoIU51bWJlci5pc0ludGVnZXIoZSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNYWxmb3JtZWQgQ01hcDogZXhwZWN0ZWQgaW50LiIpfWZ1bmN0aW9uIHBhcnNlQmZDaGFyKGUsdCl7Zm9yKDs7KXtsZXQgcj10LmdldE9iaigpO2lmKHI9PT1zcilicmVhaztpZihpc0NtZChyLCJlbmRiZmNoYXIiKSlyZXR1cm47ZXhwZWN0U3RyaW5nKHIpO2NvbnN0IGE9c3RyVG9JbnQocik7cj10LmdldE9iaigpO2V4cGVjdFN0cmluZyhyKTtjb25zdCBuPXI7ZS5tYXBPbmUoYSxuKX19ZnVuY3Rpb24gcGFyc2VCZlJhbmdlKGUsdCl7Zm9yKDs7KXtsZXQgcj10LmdldE9iaigpO2lmKHI9PT1zcilicmVhaztpZihpc0NtZChyLCJlbmRiZnJhbmdlIikpcmV0dXJuO2V4cGVjdFN0cmluZyhyKTtjb25zdCBhPXN0clRvSW50KHIpO3I9dC5nZXRPYmooKTtleHBlY3RTdHJpbmcocik7Y29uc3Qgbj1zdHJUb0ludChyKTtyPXQuZ2V0T2JqKCk7aWYoTnVtYmVyLmlzSW50ZWdlcihyKXx8InN0cmluZyI9PXR5cGVvZiByKXtjb25zdCB0PU51bWJlci5pc0ludGVnZXIocik/U3RyaW5nLmZyb21DaGFyQ29kZShyKTpyO2UubWFwQmZSYW5nZShhLG4sdCl9ZWxzZXtpZighaXNDbWQociwiWyIpKWJyZWFrO3tyPXQuZ2V0T2JqKCk7Y29uc3QgaT1bXTtmb3IoOyFpc0NtZChyLCJdIikmJnIhPT1zcjspe2kucHVzaChyKTtyPXQuZ2V0T2JqKCl9ZS5tYXBCZlJhbmdlVG9BcnJheShhLG4saSl9fX10aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgYmYgcmFuZ2UuIil9ZnVuY3Rpb24gcGFyc2VDaWRDaGFyKGUsdCl7Zm9yKDs7KXtsZXQgcj10LmdldE9iaigpO2lmKHI9PT1zcilicmVhaztpZihpc0NtZChyLCJlbmRjaWRjaGFyIikpcmV0dXJuO2V4cGVjdFN0cmluZyhyKTtjb25zdCBhPXN0clRvSW50KHIpO3I9dC5nZXRPYmooKTtleHBlY3RJbnQocik7Y29uc3Qgbj1yO2UubWFwT25lKGEsbil9fWZ1bmN0aW9uIHBhcnNlQ2lkUmFuZ2UoZSx0KXtmb3IoOzspe2xldCByPXQuZ2V0T2JqKCk7aWYocj09PXNyKWJyZWFrO2lmKGlzQ21kKHIsImVuZGNpZHJhbmdlIikpcmV0dXJuO2V4cGVjdFN0cmluZyhyKTtjb25zdCBhPXN0clRvSW50KHIpO3I9dC5nZXRPYmooKTtleHBlY3RTdHJpbmcocik7Y29uc3Qgbj1zdHJUb0ludChyKTtyPXQuZ2V0T2JqKCk7ZXhwZWN0SW50KHIpO2NvbnN0IGk9cjtlLm1hcENpZFJhbmdlKGEsbixpKX19ZnVuY3Rpb24gcGFyc2VDb2Rlc3BhY2VSYW5nZShlLHQpe2Zvcig7Oyl7bGV0IHI9dC5nZXRPYmooKTtpZihyPT09c3IpYnJlYWs7aWYoaXNDbWQociwiZW5kY29kZXNwYWNlcmFuZ2UiKSlyZXR1cm47aWYoInN0cmluZyIhPXR5cGVvZiByKWJyZWFrO2NvbnN0IGE9c3RyVG9JbnQocik7cj10LmdldE9iaigpO2lmKCJzdHJpbmciIT10eXBlb2YgcilicmVhaztjb25zdCBuPXN0clRvSW50KHIpO2UuYWRkQ29kZXNwYWNlUmFuZ2Uoci5sZW5ndGgsYSxuKX10aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgY29kZXNwYWNlIHJhbmdlLiIpfWZ1bmN0aW9uIHBhcnNlV01vZGUoZSx0KXtjb25zdCByPXQuZ2V0T2JqKCk7TnVtYmVyLmlzSW50ZWdlcihyKSYmKGUudmVydGljYWw9ISFyKX1mdW5jdGlvbiBwYXJzZUNNYXBOYW1lKGUsdCl7Y29uc3Qgcj10LmdldE9iaigpO3IgaW5zdGFuY2VvZiBOYW1lJiYoZS5uYW1lPXIubmFtZSl9YXN5bmMgZnVuY3Rpb24gcGFyc2VDTWFwKGUsdCxyLGEpe2xldCBuLGk7ZTpmb3IoOzspdHJ5e2NvbnN0IHI9dC5nZXRPYmooKTtpZihyPT09c3IpYnJlYWs7aWYociBpbnN0YW5jZW9mIE5hbWUpeyJXTW9kZSI9PT1yLm5hbWU/cGFyc2VXTW9kZShlLHQpOiJDTWFwTmFtZSI9PT1yLm5hbWUmJnBhcnNlQ01hcE5hbWUoZSx0KTtuPXJ9ZWxzZSBpZihyIGluc3RhbmNlb2YgQ21kKXN3aXRjaChyLmNtZCl7Y2FzZSJlbmRjbWFwIjpicmVhayBlO2Nhc2UidXNlY21hcCI6biBpbnN0YW5jZW9mIE5hbWUmJihpPW4ubmFtZSk7YnJlYWs7Y2FzZSJiZWdpbmNvZGVzcGFjZXJhbmdlIjpwYXJzZUNvZGVzcGFjZVJhbmdlKGUsdCk7YnJlYWs7Y2FzZSJiZWdpbmJmY2hhciI6cGFyc2VCZkNoYXIoZSx0KTticmVhaztjYXNlImJlZ2luY2lkY2hhciI6cGFyc2VDaWRDaGFyKGUsdCk7YnJlYWs7Y2FzZSJiZWdpbmJmcmFuZ2UiOnBhcnNlQmZSYW5nZShlLHQpO2JyZWFrO2Nhc2UiYmVnaW5jaWRyYW5nZSI6cGFyc2VDaWRSYW5nZShlLHQpfX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKCJJbnZhbGlkIGNNYXAgZGF0YTogIitlKTtjb250aW51ZX0hYSYmaSYmKGE9aSk7cmV0dXJuIGE/ZXh0ZW5kQ01hcChlLHIsYSk6ZX1hc3luYyBmdW5jdGlvbiBleHRlbmRDTWFwKGUsdCxyKXtlLnVzZUNNYXA9YXdhaXQgY3JlYXRlQnVpbHRJbkNNYXAocix0KTtpZigwPT09ZS5udW1Db2Rlc3BhY2VSYW5nZXMpe2NvbnN0IHQ9ZS51c2VDTWFwLmNvZGVzcGFjZVJhbmdlcztmb3IobGV0IHI9MDtyPHQubGVuZ3RoO3IrKyllLmNvZGVzcGFjZVJhbmdlc1tyXT10W3JdLnNsaWNlKCk7ZS5udW1Db2Rlc3BhY2VSYW5nZXM9ZS51c2VDTWFwLm51bUNvZGVzcGFjZVJhbmdlc31lLnVzZUNNYXAuZm9yRWFjaChmdW5jdGlvbih0LHIpe2UuY29udGFpbnModCl8fGUubWFwT25lKHQscil9KTtyZXR1cm4gZX1hc3luYyBmdW5jdGlvbiBjcmVhdGVCdWlsdEluQ01hcChlLHQpe2lmKCJJZGVudGl0eS1IIj09PWUpcmV0dXJuIG5ldyBJZGVudGl0eUNNYXAoITEsMik7aWYoIklkZW50aXR5LVYiPT09ZSlyZXR1cm4gbmV3IElkZW50aXR5Q01hcCghMCwyKTtpZighaWEuaW5jbHVkZXMoZSkpdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIENNYXAgbmFtZTogIitlKTtpZighdCl0aHJvdyBuZXcgRXJyb3IoIkJ1aWx0LWluIENNYXAgcGFyYW1ldGVycyBhcmUgbm90IHByb3ZpZGVkLiIpO2NvbnN0e2NNYXBEYXRhOnIsaXNDb21wcmVzc2VkOmF9PWF3YWl0IHQoZSksbj1uZXcgQ01hcCghMCk7aWYoYSlyZXR1cm4obmV3IEJpbmFyeUNNYXBSZWFkZXIpLnByb2Nlc3MocixuLGU9PmV4dGVuZENNYXAobix0LGUpKTtjb25zdCBpPW5ldyBMZXhlcihuZXcgU3RyZWFtKHIpKTtyZXR1cm4gcGFyc2VDTWFwKG4saSx0LG51bGwpfWNsYXNzIENNYXBGYWN0b3J5e3N0YXRpYyBhc3luYyBjcmVhdGUoe2VuY29kaW5nOmUsZmV0Y2hCdWlsdEluQ01hcDp0LHVzZUNNYXA6cn0pe2lmKGUgaW5zdGFuY2VvZiBOYW1lKXJldHVybiBjcmVhdGVCdWlsdEluQ01hcChlLm5hbWUsdCk7aWYoZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pe2NvbnN0IGE9YXdhaXQgcGFyc2VDTWFwKG5ldyBDTWFwLG5ldyBMZXhlcihlKSx0LHIpO3JldHVybiBhLmlzSWRlbnRpdHlDTWFwP2NyZWF0ZUJ1aWx0SW5DTWFwKGEubmFtZSx0KTphfXRocm93IG5ldyBFcnJvcigiRW5jb2RpbmcgcmVxdWlyZWQuIil9fWNvbnN0IG9hPVsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwic3BhY2UiLCJleGNsYW1zbWFsbCIsIkh1bmdhcnVtbGF1dHNtYWxsIiwiIiwiZG9sbGFyb2xkc3R5bGUiLCJkb2xsYXJzdXBlcmlvciIsImFtcGVyc2FuZHNtYWxsIiwiQWN1dGVzbWFsbCIsInBhcmVubGVmdHN1cGVyaW9yIiwicGFyZW5yaWdodHN1cGVyaW9yIiwidHdvZG90ZW5sZWFkZXIiLCJvbmVkb3RlbmxlYWRlciIsImNvbW1hIiwiaHlwaGVuIiwicGVyaW9kIiwiZnJhY3Rpb24iLCJ6ZXJvb2xkc3R5bGUiLCJvbmVvbGRzdHlsZSIsInR3b29sZHN0eWxlIiwidGhyZWVvbGRzdHlsZSIsImZvdXJvbGRzdHlsZSIsImZpdmVvbGRzdHlsZSIsInNpeG9sZHN0eWxlIiwic2V2ZW5vbGRzdHlsZSIsImVpZ2h0b2xkc3R5bGUiLCJuaW5lb2xkc3R5bGUiLCJjb2xvbiIsInNlbWljb2xvbiIsImNvbW1hc3VwZXJpb3IiLCJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwicGVyaW9kc3VwZXJpb3IiLCJxdWVzdGlvbnNtYWxsIiwiIiwiYXN1cGVyaW9yIiwiYnN1cGVyaW9yIiwiY2VudHN1cGVyaW9yIiwiZHN1cGVyaW9yIiwiZXN1cGVyaW9yIiwiIiwiIiwiIiwiaXN1cGVyaW9yIiwiIiwiIiwibHN1cGVyaW9yIiwibXN1cGVyaW9yIiwibnN1cGVyaW9yIiwib3N1cGVyaW9yIiwiIiwiIiwicnN1cGVyaW9yIiwic3N1cGVyaW9yIiwidHN1cGVyaW9yIiwiIiwiZmYiLCJmaSIsImZsIiwiZmZpIiwiZmZsIiwicGFyZW5sZWZ0aW5mZXJpb3IiLCIiLCJwYXJlbnJpZ2h0aW5mZXJpb3IiLCJDaXJjdW1mbGV4c21hbGwiLCJoeXBoZW5zdXBlcmlvciIsIkdyYXZlc21hbGwiLCJBc21hbGwiLCJCc21hbGwiLCJDc21hbGwiLCJEc21hbGwiLCJFc21hbGwiLCJGc21hbGwiLCJHc21hbGwiLCJIc21hbGwiLCJJc21hbGwiLCJKc21hbGwiLCJLc21hbGwiLCJMc21hbGwiLCJNc21hbGwiLCJOc21hbGwiLCJPc21hbGwiLCJQc21hbGwiLCJRc21hbGwiLCJSc21hbGwiLCJTc21hbGwiLCJUc21hbGwiLCJVc21hbGwiLCJWc21hbGwiLCJXc21hbGwiLCJYc21hbGwiLCJZc21hbGwiLCJac21hbGwiLCJjb2xvbm1vbmV0YXJ5Iiwib25lZml0dGVkIiwicnVwaWFoIiwiVGlsZGVzbWFsbCIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsImV4Y2xhbWRvd25zbWFsbCIsImNlbnRvbGRzdHlsZSIsIkxzbGFzaHNtYWxsIiwiIiwiIiwiU2Nhcm9uc21hbGwiLCJaY2Fyb25zbWFsbCIsIkRpZXJlc2lzc21hbGwiLCJCcmV2ZXNtYWxsIiwiQ2Fyb25zbWFsbCIsIiIsIkRvdGFjY2VudHNtYWxsIiwiIiwiIiwiTWFjcm9uc21hbGwiLCIiLCIiLCJmaWd1cmVkYXNoIiwiaHlwaGVuaW5mZXJpb3IiLCIiLCIiLCJPZ29uZWtzbWFsbCIsIlJpbmdzbWFsbCIsIkNlZGlsbGFzbWFsbCIsIiIsIiIsIiIsIm9uZXF1YXJ0ZXIiLCJvbmVoYWxmIiwidGhyZWVxdWFydGVycyIsInF1ZXN0aW9uZG93bnNtYWxsIiwib25lZWlnaHRoIiwidGhyZWVlaWdodGhzIiwiZml2ZWVpZ2h0aHMiLCJzZXZlbmVpZ2h0aHMiLCJvbmV0aGlyZCIsInR3b3RoaXJkcyIsIiIsIiIsInplcm9zdXBlcmlvciIsIm9uZXN1cGVyaW9yIiwidHdvc3VwZXJpb3IiLCJ0aHJlZXN1cGVyaW9yIiwiZm91cnN1cGVyaW9yIiwiZml2ZXN1cGVyaW9yIiwic2l4c3VwZXJpb3IiLCJzZXZlbnN1cGVyaW9yIiwiZWlnaHRzdXBlcmlvciIsIm5pbmVzdXBlcmlvciIsInplcm9pbmZlcmlvciIsIm9uZWluZmVyaW9yIiwidHdvaW5mZXJpb3IiLCJ0aHJlZWluZmVyaW9yIiwiZm91cmluZmVyaW9yIiwiZml2ZWluZmVyaW9yIiwic2l4aW5mZXJpb3IiLCJzZXZlbmluZmVyaW9yIiwiZWlnaHRpbmZlcmlvciIsIm5pbmVpbmZlcmlvciIsImNlbnRpbmZlcmlvciIsImRvbGxhcmluZmVyaW9yIiwicGVyaW9kaW5mZXJpb3IiLCJjb21tYWluZmVyaW9yIiwiQWdyYXZlc21hbGwiLCJBYWN1dGVzbWFsbCIsIkFjaXJjdW1mbGV4c21hbGwiLCJBdGlsZGVzbWFsbCIsIkFkaWVyZXNpc3NtYWxsIiwiQXJpbmdzbWFsbCIsIkFFc21hbGwiLCJDY2VkaWxsYXNtYWxsIiwiRWdyYXZlc21hbGwiLCJFYWN1dGVzbWFsbCIsIkVjaXJjdW1mbGV4c21hbGwiLCJFZGllcmVzaXNzbWFsbCIsIklncmF2ZXNtYWxsIiwiSWFjdXRlc21hbGwiLCJJY2lyY3VtZmxleHNtYWxsIiwiSWRpZXJlc2lzc21hbGwiLCJFdGhzbWFsbCIsIk50aWxkZXNtYWxsIiwiT2dyYXZlc21hbGwiLCJPYWN1dGVzbWFsbCIsIk9jaXJjdW1mbGV4c21hbGwiLCJPdGlsZGVzbWFsbCIsIk9kaWVyZXNpc3NtYWxsIiwiT0VzbWFsbCIsIk9zbGFzaHNtYWxsIiwiVWdyYXZlc21hbGwiLCJVYWN1dGVzbWFsbCIsIlVjaXJjdW1mbGV4c21hbGwiLCJVZGllcmVzaXNzbWFsbCIsIllhY3V0ZXNtYWxsIiwiVGhvcm5zbWFsbCIsIllkaWVyZXNpc3NtYWxsIl0sY2E9WyIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCJzcGFjZSIsImV4Y2xhbXNtYWxsIiwiSHVuZ2FydW1sYXV0c21hbGwiLCJjZW50b2xkc3R5bGUiLCJkb2xsYXJvbGRzdHlsZSIsImRvbGxhcnN1cGVyaW9yIiwiYW1wZXJzYW5kc21hbGwiLCJBY3V0ZXNtYWxsIiwicGFyZW5sZWZ0c3VwZXJpb3IiLCJwYXJlbnJpZ2h0c3VwZXJpb3IiLCJ0d29kb3RlbmxlYWRlciIsIm9uZWRvdGVubGVhZGVyIiwiY29tbWEiLCJoeXBoZW4iLCJwZXJpb2QiLCJmcmFjdGlvbiIsInplcm9vbGRzdHlsZSIsIm9uZW9sZHN0eWxlIiwidHdvb2xkc3R5bGUiLCJ0aHJlZW9sZHN0eWxlIiwiZm91cm9sZHN0eWxlIiwiZml2ZW9sZHN0eWxlIiwic2l4b2xkc3R5bGUiLCJzZXZlbm9sZHN0eWxlIiwiZWlnaHRvbGRzdHlsZSIsIm5pbmVvbGRzdHlsZSIsImNvbG9uIiwic2VtaWNvbG9uIiwiIiwidGhyZWVxdWFydGVyc2VtZGFzaCIsIiIsInF1ZXN0aW9uc21hbGwiLCIiLCIiLCIiLCIiLCJFdGhzbWFsbCIsIiIsIiIsIm9uZXF1YXJ0ZXIiLCJvbmVoYWxmIiwidGhyZWVxdWFydGVycyIsIm9uZWVpZ2h0aCIsInRocmVlZWlnaHRocyIsImZpdmVlaWdodGhzIiwic2V2ZW5laWdodGhzIiwib25ldGhpcmQiLCJ0d290aGlyZHMiLCIiLCIiLCIiLCIiLCIiLCIiLCJmZiIsImZpIiwiZmwiLCJmZmkiLCJmZmwiLCJwYXJlbmxlZnRpbmZlcmlvciIsIiIsInBhcmVucmlnaHRpbmZlcmlvciIsIkNpcmN1bWZsZXhzbWFsbCIsImh5cGhlbmluZmVyaW9yIiwiR3JhdmVzbWFsbCIsIkFzbWFsbCIsIkJzbWFsbCIsIkNzbWFsbCIsIkRzbWFsbCIsIkVzbWFsbCIsIkZzbWFsbCIsIkdzbWFsbCIsIkhzbWFsbCIsIklzbWFsbCIsIkpzbWFsbCIsIktzbWFsbCIsIkxzbWFsbCIsIk1zbWFsbCIsIk5zbWFsbCIsIk9zbWFsbCIsIlBzbWFsbCIsIlFzbWFsbCIsIlJzbWFsbCIsIlNzbWFsbCIsIlRzbWFsbCIsIlVzbWFsbCIsIlZzbWFsbCIsIldzbWFsbCIsIlhzbWFsbCIsIllzbWFsbCIsIlpzbWFsbCIsImNvbG9ubW9uZXRhcnkiLCJvbmVmaXR0ZWQiLCJydXBpYWgiLCJUaWxkZXNtYWxsIiwiIiwiIiwiYXN1cGVyaW9yIiwiY2VudHN1cGVyaW9yIiwiIiwiIiwiIiwiIiwiQWFjdXRlc21hbGwiLCJBZ3JhdmVzbWFsbCIsIkFjaXJjdW1mbGV4c21hbGwiLCJBZGllcmVzaXNzbWFsbCIsIkF0aWxkZXNtYWxsIiwiQXJpbmdzbWFsbCIsIkNjZWRpbGxhc21hbGwiLCJFYWN1dGVzbWFsbCIsIkVncmF2ZXNtYWxsIiwiRWNpcmN1bWZsZXhzbWFsbCIsIkVkaWVyZXNpc3NtYWxsIiwiSWFjdXRlc21hbGwiLCJJZ3JhdmVzbWFsbCIsIkljaXJjdW1mbGV4c21hbGwiLCJJZGllcmVzaXNzbWFsbCIsIk50aWxkZXNtYWxsIiwiT2FjdXRlc21hbGwiLCJPZ3JhdmVzbWFsbCIsIk9jaXJjdW1mbGV4c21hbGwiLCJPZGllcmVzaXNzbWFsbCIsIk90aWxkZXNtYWxsIiwiVWFjdXRlc21hbGwiLCJVZ3JhdmVzbWFsbCIsIlVjaXJjdW1mbGV4c21hbGwiLCJVZGllcmVzaXNzbWFsbCIsIiIsImVpZ2h0c3VwZXJpb3IiLCJmb3VyaW5mZXJpb3IiLCJ0aHJlZWluZmVyaW9yIiwic2l4aW5mZXJpb3IiLCJlaWdodGluZmVyaW9yIiwic2V2ZW5pbmZlcmlvciIsIlNjYXJvbnNtYWxsIiwiIiwiY2VudGluZmVyaW9yIiwidHdvaW5mZXJpb3IiLCIiLCJEaWVyZXNpc3NtYWxsIiwiIiwiQ2Fyb25zbWFsbCIsIm9zdXBlcmlvciIsImZpdmVpbmZlcmlvciIsIiIsImNvbW1haW5mZXJpb3IiLCJwZXJpb2RpbmZlcmlvciIsIllhY3V0ZXNtYWxsIiwiIiwiZG9sbGFyaW5mZXJpb3IiLCIiLCIiLCJUaG9ybnNtYWxsIiwiIiwibmluZWluZmVyaW9yIiwiemVyb2luZmVyaW9yIiwiWmNhcm9uc21hbGwiLCJBRXNtYWxsIiwiT3NsYXNoc21hbGwiLCJxdWVzdGlvbmRvd25zbWFsbCIsIm9uZWluZmVyaW9yIiwiTHNsYXNoc21hbGwiLCIiLCIiLCIiLCIiLCIiLCIiLCJDZWRpbGxhc21hbGwiLCIiLCIiLCIiLCIiLCIiLCJPRXNtYWxsIiwiZmlndXJlZGFzaCIsImh5cGhlbnN1cGVyaW9yIiwiIiwiIiwiIiwiIiwiZXhjbGFtZG93bnNtYWxsIiwiIiwiWWRpZXJlc2lzc21hbGwiLCIiLCJvbmVzdXBlcmlvciIsInR3b3N1cGVyaW9yIiwidGhyZWVzdXBlcmlvciIsImZvdXJzdXBlcmlvciIsImZpdmVzdXBlcmlvciIsInNpeHN1cGVyaW9yIiwic2V2ZW5zdXBlcmlvciIsIm5pbmVzdXBlcmlvciIsInplcm9zdXBlcmlvciIsIiIsImVzdXBlcmlvciIsInJzdXBlcmlvciIsInRzdXBlcmlvciIsIiIsIiIsImlzdXBlcmlvciIsInNzdXBlcmlvciIsImRzdXBlcmlvciIsIiIsIiIsIiIsIiIsIiIsImxzdXBlcmlvciIsIk9nb25la3NtYWxsIiwiQnJldmVzbWFsbCIsIk1hY3JvbnNtYWxsIiwiYnN1cGVyaW9yIiwibnN1cGVyaW9yIiwibXN1cGVyaW9yIiwiY29tbWFzdXBlcmlvciIsInBlcmlvZHN1cGVyaW9yIiwiRG90YWNjZW50c21hbGwiLCJSaW5nc21hbGwiLCIiLCIiLCIiLCIiXSxsYT1bIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsInNwYWNlIiwiZXhjbGFtIiwicXVvdGVkYmwiLCJudW1iZXJzaWduIiwiZG9sbGFyIiwicGVyY2VudCIsImFtcGVyc2FuZCIsInF1b3Rlc2luZ2xlIiwicGFyZW5sZWZ0IiwicGFyZW5yaWdodCIsImFzdGVyaXNrIiwicGx1cyIsImNvbW1hIiwiaHlwaGVuIiwicGVyaW9kIiwic2xhc2giLCJ6ZXJvIiwib25lIiwidHdvIiwidGhyZWUiLCJmb3VyIiwiZml2ZSIsInNpeCIsInNldmVuIiwiZWlnaHQiLCJuaW5lIiwiY29sb24iLCJzZW1pY29sb24iLCJsZXNzIiwiZXF1YWwiLCJncmVhdGVyIiwicXVlc3Rpb24iLCJhdCIsIkEiLCJCIiwiQyIsIkQiLCJFIiwiRiIsIkciLCJIIiwiSSIsIkoiLCJLIiwiTCIsIk0iLCJOIiwiTyIsIlAiLCJRIiwiUiIsIlMiLCJUIiwiVSIsIlYiLCJXIiwiWCIsIlkiLCJaIiwiYnJhY2tldGxlZnQiLCJiYWNrc2xhc2giLCJicmFja2V0cmlnaHQiLCJhc2NpaWNpcmN1bSIsInVuZGVyc2NvcmUiLCJncmF2ZSIsImEiLCJiIiwiYyIsImQiLCJlIiwiZiIsImciLCJoIiwiaSIsImoiLCJrIiwibCIsIm0iLCJuIiwibyIsInAiLCJxIiwiciIsInMiLCJ0IiwidSIsInYiLCJ3IiwieCIsInkiLCJ6IiwiYnJhY2VsZWZ0IiwiYmFyIiwiYnJhY2VyaWdodCIsImFzY2lpdGlsZGUiLCIiLCJBZGllcmVzaXMiLCJBcmluZyIsIkNjZWRpbGxhIiwiRWFjdXRlIiwiTnRpbGRlIiwiT2RpZXJlc2lzIiwiVWRpZXJlc2lzIiwiYWFjdXRlIiwiYWdyYXZlIiwiYWNpcmN1bWZsZXgiLCJhZGllcmVzaXMiLCJhdGlsZGUiLCJhcmluZyIsImNjZWRpbGxhIiwiZWFjdXRlIiwiZWdyYXZlIiwiZWNpcmN1bWZsZXgiLCJlZGllcmVzaXMiLCJpYWN1dGUiLCJpZ3JhdmUiLCJpY2lyY3VtZmxleCIsImlkaWVyZXNpcyIsIm50aWxkZSIsIm9hY3V0ZSIsIm9ncmF2ZSIsIm9jaXJjdW1mbGV4Iiwib2RpZXJlc2lzIiwib3RpbGRlIiwidWFjdXRlIiwidWdyYXZlIiwidWNpcmN1bWZsZXgiLCJ1ZGllcmVzaXMiLCJkYWdnZXIiLCJkZWdyZWUiLCJjZW50Iiwic3RlcmxpbmciLCJzZWN0aW9uIiwiYnVsbGV0IiwicGFyYWdyYXBoIiwiZ2VybWFuZGJscyIsInJlZ2lzdGVyZWQiLCJjb3B5cmlnaHQiLCJ0cmFkZW1hcmsiLCJhY3V0ZSIsImRpZXJlc2lzIiwibm90ZXF1YWwiLCJBRSIsIk9zbGFzaCIsImluZmluaXR5IiwicGx1c21pbnVzIiwibGVzc2VxdWFsIiwiZ3JlYXRlcmVxdWFsIiwieWVuIiwibXUiLCJwYXJ0aWFsZGlmZiIsInN1bW1hdGlvbiIsInByb2R1Y3QiLCJwaSIsImludGVncmFsIiwib3JkZmVtaW5pbmUiLCJvcmRtYXNjdWxpbmUiLCJPbWVnYSIsImFlIiwib3NsYXNoIiwicXVlc3Rpb25kb3duIiwiZXhjbGFtZG93biIsImxvZ2ljYWxub3QiLCJyYWRpY2FsIiwiZmxvcmluIiwiYXBwcm94ZXF1YWwiLCJEZWx0YSIsImd1aWxsZW1vdGxlZnQiLCJndWlsbGVtb3RyaWdodCIsImVsbGlwc2lzIiwic3BhY2UiLCJBZ3JhdmUiLCJBdGlsZGUiLCJPdGlsZGUiLCJPRSIsIm9lIiwiZW5kYXNoIiwiZW1kYXNoIiwicXVvdGVkYmxsZWZ0IiwicXVvdGVkYmxyaWdodCIsInF1b3RlbGVmdCIsInF1b3RlcmlnaHQiLCJkaXZpZGUiLCJsb3plbmdlIiwieWRpZXJlc2lzIiwiWWRpZXJlc2lzIiwiZnJhY3Rpb24iLCJjdXJyZW5jeSIsImd1aWxzaW5nbGxlZnQiLCJndWlsc2luZ2xyaWdodCIsImZpIiwiZmwiLCJkYWdnZXJkYmwiLCJwZXJpb2RjZW50ZXJlZCIsInF1b3Rlc2luZ2xiYXNlIiwicXVvdGVkYmxiYXNlIiwicGVydGhvdXNhbmQiLCJBY2lyY3VtZmxleCIsIkVjaXJjdW1mbGV4IiwiQWFjdXRlIiwiRWRpZXJlc2lzIiwiRWdyYXZlIiwiSWFjdXRlIiwiSWNpcmN1bWZsZXgiLCJJZGllcmVzaXMiLCJJZ3JhdmUiLCJPYWN1dGUiLCJPY2lyY3VtZmxleCIsImFwcGxlIiwiT2dyYXZlIiwiVWFjdXRlIiwiVWNpcmN1bWZsZXgiLCJVZ3JhdmUiLCJkb3RsZXNzaSIsImNpcmN1bWZsZXgiLCJ0aWxkZSIsIm1hY3JvbiIsImJyZXZlIiwiZG90YWNjZW50IiwicmluZyIsImNlZGlsbGEiLCJodW5nYXJ1bWxhdXQiLCJvZ29uZWsiLCJjYXJvbiJdLGhhPVsiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwic3BhY2UiLCJleGNsYW0iLCJxdW90ZWRibCIsIm51bWJlcnNpZ24iLCJkb2xsYXIiLCJwZXJjZW50IiwiYW1wZXJzYW5kIiwicXVvdGVyaWdodCIsInBhcmVubGVmdCIsInBhcmVucmlnaHQiLCJhc3RlcmlzayIsInBsdXMiLCJjb21tYSIsImh5cGhlbiIsInBlcmlvZCIsInNsYXNoIiwiemVybyIsIm9uZSIsInR3byIsInRocmVlIiwiZm91ciIsImZpdmUiLCJzaXgiLCJzZXZlbiIsImVpZ2h0IiwibmluZSIsImNvbG9uIiwic2VtaWNvbG9uIiwibGVzcyIsImVxdWFsIiwiZ3JlYXRlciIsInF1ZXN0aW9uIiwiYXQiLCJBIiwiQiIsIkMiLCJEIiwiRSIsIkYiLCJHIiwiSCIsIkkiLCJKIiwiSyIsIkwiLCJNIiwiTiIsIk8iLCJQIiwiUSIsIlIiLCJTIiwiVCIsIlUiLCJWIiwiVyIsIlgiLCJZIiwiWiIsImJyYWNrZXRsZWZ0IiwiYmFja3NsYXNoIiwiYnJhY2tldHJpZ2h0IiwiYXNjaWljaXJjdW0iLCJ1bmRlcnNjb3JlIiwicXVvdGVsZWZ0IiwiYSIsImIiLCJjIiwiZCIsImUiLCJmIiwiZyIsImgiLCJpIiwiaiIsImsiLCJsIiwibSIsIm4iLCJvIiwicCIsInEiLCJyIiwicyIsInQiLCJ1IiwidiIsInciLCJ4IiwieSIsInoiLCJicmFjZWxlZnQiLCJiYXIiLCJicmFjZXJpZ2h0IiwiYXNjaWl0aWxkZSIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsImV4Y2xhbWRvd24iLCJjZW50Iiwic3RlcmxpbmciLCJmcmFjdGlvbiIsInllbiIsImZsb3JpbiIsInNlY3Rpb24iLCJjdXJyZW5jeSIsInF1b3Rlc2luZ2xlIiwicXVvdGVkYmxsZWZ0IiwiZ3VpbGxlbW90bGVmdCIsImd1aWxzaW5nbGxlZnQiLCJndWlsc2luZ2xyaWdodCIsImZpIiwiZmwiLCIiLCJlbmRhc2giLCJkYWdnZXIiLCJkYWdnZXJkYmwiLCJwZXJpb2RjZW50ZXJlZCIsIiIsInBhcmFncmFwaCIsImJ1bGxldCIsInF1b3Rlc2luZ2xiYXNlIiwicXVvdGVkYmxiYXNlIiwicXVvdGVkYmxyaWdodCIsImd1aWxsZW1vdHJpZ2h0IiwiZWxsaXBzaXMiLCJwZXJ0aG91c2FuZCIsIiIsInF1ZXN0aW9uZG93biIsIiIsImdyYXZlIiwiYWN1dGUiLCJjaXJjdW1mbGV4IiwidGlsZGUiLCJtYWNyb24iLCJicmV2ZSIsImRvdGFjY2VudCIsImRpZXJlc2lzIiwiIiwicmluZyIsImNlZGlsbGEiLCIiLCJodW5nYXJ1bWxhdXQiLCJvZ29uZWsiLCJjYXJvbiIsImVtZGFzaCIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIkFFIiwiIiwib3JkZmVtaW5pbmUiLCIiLCIiLCIiLCIiLCJMc2xhc2giLCJPc2xhc2giLCJPRSIsIm9yZG1hc2N1bGluZSIsIiIsIiIsIiIsIiIsIiIsImFlIiwiIiwiIiwiIiwiZG90bGVzc2kiLCIiLCIiLCJsc2xhc2giLCJvc2xhc2giLCJvZSIsImdlcm1hbmRibHMiLCIiLCIiLCIiLCIiXSx1YT1bIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsInNwYWNlIiwiZXhjbGFtIiwicXVvdGVkYmwiLCJudW1iZXJzaWduIiwiZG9sbGFyIiwicGVyY2VudCIsImFtcGVyc2FuZCIsInF1b3Rlc2luZ2xlIiwicGFyZW5sZWZ0IiwicGFyZW5yaWdodCIsImFzdGVyaXNrIiwicGx1cyIsImNvbW1hIiwiaHlwaGVuIiwicGVyaW9kIiwic2xhc2giLCJ6ZXJvIiwib25lIiwidHdvIiwidGhyZWUiLCJmb3VyIiwiZml2ZSIsInNpeCIsInNldmVuIiwiZWlnaHQiLCJuaW5lIiwiY29sb24iLCJzZW1pY29sb24iLCJsZXNzIiwiZXF1YWwiLCJncmVhdGVyIiwicXVlc3Rpb24iLCJhdCIsIkEiLCJCIiwiQyIsIkQiLCJFIiwiRiIsIkciLCJIIiwiSSIsIkoiLCJLIiwiTCIsIk0iLCJOIiwiTyIsIlAiLCJRIiwiUiIsIlMiLCJUIiwiVSIsIlYiLCJXIiwiWCIsIlkiLCJaIiwiYnJhY2tldGxlZnQiLCJiYWNrc2xhc2giLCJicmFja2V0cmlnaHQiLCJhc2NpaWNpcmN1bSIsInVuZGVyc2NvcmUiLCJncmF2ZSIsImEiLCJiIiwiYyIsImQiLCJlIiwiZiIsImciLCJoIiwiaSIsImoiLCJrIiwibCIsIm0iLCJuIiwibyIsInAiLCJxIiwiciIsInMiLCJ0IiwidSIsInYiLCJ3IiwieCIsInkiLCJ6IiwiYnJhY2VsZWZ0IiwiYmFyIiwiYnJhY2VyaWdodCIsImFzY2lpdGlsZGUiLCJidWxsZXQiLCJFdXJvIiwiYnVsbGV0IiwicXVvdGVzaW5nbGJhc2UiLCJmbG9yaW4iLCJxdW90ZWRibGJhc2UiLCJlbGxpcHNpcyIsImRhZ2dlciIsImRhZ2dlcmRibCIsImNpcmN1bWZsZXgiLCJwZXJ0aG91c2FuZCIsIlNjYXJvbiIsImd1aWxzaW5nbGxlZnQiLCJPRSIsImJ1bGxldCIsIlpjYXJvbiIsImJ1bGxldCIsImJ1bGxldCIsInF1b3RlbGVmdCIsInF1b3RlcmlnaHQiLCJxdW90ZWRibGxlZnQiLCJxdW90ZWRibHJpZ2h0IiwiYnVsbGV0IiwiZW5kYXNoIiwiZW1kYXNoIiwidGlsZGUiLCJ0cmFkZW1hcmsiLCJzY2Fyb24iLCJndWlsc2luZ2xyaWdodCIsIm9lIiwiYnVsbGV0IiwiemNhcm9uIiwiWWRpZXJlc2lzIiwic3BhY2UiLCJleGNsYW1kb3duIiwiY2VudCIsInN0ZXJsaW5nIiwiY3VycmVuY3kiLCJ5ZW4iLCJicm9rZW5iYXIiLCJzZWN0aW9uIiwiZGllcmVzaXMiLCJjb3B5cmlnaHQiLCJvcmRmZW1pbmluZSIsImd1aWxsZW1vdGxlZnQiLCJsb2dpY2Fsbm90IiwiaHlwaGVuIiwicmVnaXN0ZXJlZCIsIm1hY3JvbiIsImRlZ3JlZSIsInBsdXNtaW51cyIsInR3b3N1cGVyaW9yIiwidGhyZWVzdXBlcmlvciIsImFjdXRlIiwibXUiLCJwYXJhZ3JhcGgiLCJwZXJpb2RjZW50ZXJlZCIsImNlZGlsbGEiLCJvbmVzdXBlcmlvciIsIm9yZG1hc2N1bGluZSIsImd1aWxsZW1vdHJpZ2h0Iiwib25lcXVhcnRlciIsIm9uZWhhbGYiLCJ0aHJlZXF1YXJ0ZXJzIiwicXVlc3Rpb25kb3duIiwiQWdyYXZlIiwiQWFjdXRlIiwiQWNpcmN1bWZsZXgiLCJBdGlsZGUiLCJBZGllcmVzaXMiLCJBcmluZyIsIkFFIiwiQ2NlZGlsbGEiLCJFZ3JhdmUiLCJFYWN1dGUiLCJFY2lyY3VtZmxleCIsIkVkaWVyZXNpcyIsIklncmF2ZSIsIklhY3V0ZSIsIkljaXJjdW1mbGV4IiwiSWRpZXJlc2lzIiwiRXRoIiwiTnRpbGRlIiwiT2dyYXZlIiwiT2FjdXRlIiwiT2NpcmN1bWZsZXgiLCJPdGlsZGUiLCJPZGllcmVzaXMiLCJtdWx0aXBseSIsIk9zbGFzaCIsIlVncmF2ZSIsIlVhY3V0ZSIsIlVjaXJjdW1mbGV4IiwiVWRpZXJlc2lzIiwiWWFjdXRlIiwiVGhvcm4iLCJnZXJtYW5kYmxzIiwiYWdyYXZlIiwiYWFjdXRlIiwiYWNpcmN1bWZsZXgiLCJhdGlsZGUiLCJhZGllcmVzaXMiLCJhcmluZyIsImFlIiwiY2NlZGlsbGEiLCJlZ3JhdmUiLCJlYWN1dGUiLCJlY2lyY3VtZmxleCIsImVkaWVyZXNpcyIsImlncmF2ZSIsImlhY3V0ZSIsImljaXJjdW1mbGV4IiwiaWRpZXJlc2lzIiwiZXRoIiwibnRpbGRlIiwib2dyYXZlIiwib2FjdXRlIiwib2NpcmN1bWZsZXgiLCJvdGlsZGUiLCJvZGllcmVzaXMiLCJkaXZpZGUiLCJvc2xhc2giLCJ1Z3JhdmUiLCJ1YWN1dGUiLCJ1Y2lyY3VtZmxleCIsInVkaWVyZXNpcyIsInlhY3V0ZSIsInRob3JuIiwieWRpZXJlc2lzIl0sZGE9WyIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCIiLCJzcGFjZSIsImV4Y2xhbSIsInVuaXZlcnNhbCIsIm51bWJlcnNpZ24iLCJleGlzdGVudGlhbCIsInBlcmNlbnQiLCJhbXBlcnNhbmQiLCJzdWNodGhhdCIsInBhcmVubGVmdCIsInBhcmVucmlnaHQiLCJhc3Rlcmlza21hdGgiLCJwbHVzIiwiY29tbWEiLCJtaW51cyIsInBlcmlvZCIsInNsYXNoIiwiemVybyIsIm9uZSIsInR3byIsInRocmVlIiwiZm91ciIsImZpdmUiLCJzaXgiLCJzZXZlbiIsImVpZ2h0IiwibmluZSIsImNvbG9uIiwic2VtaWNvbG9uIiwibGVzcyIsImVxdWFsIiwiZ3JlYXRlciIsInF1ZXN0aW9uIiwiY29uZ3J1ZW50IiwiQWxwaGEiLCJCZXRhIiwiQ2hpIiwiRGVsdGEiLCJFcHNpbG9uIiwiUGhpIiwiR2FtbWEiLCJFdGEiLCJJb3RhIiwidGhldGExIiwiS2FwcGEiLCJMYW1iZGEiLCJNdSIsIk51IiwiT21pY3JvbiIsIlBpIiwiVGhldGEiLCJSaG8iLCJTaWdtYSIsIlRhdSIsIlVwc2lsb24iLCJzaWdtYTEiLCJPbWVnYSIsIlhpIiwiUHNpIiwiWmV0YSIsImJyYWNrZXRsZWZ0IiwidGhlcmVmb3JlIiwiYnJhY2tldHJpZ2h0IiwicGVycGVuZGljdWxhciIsInVuZGVyc2NvcmUiLCJyYWRpY2FsZXgiLCJhbHBoYSIsImJldGEiLCJjaGkiLCJkZWx0YSIsImVwc2lsb24iLCJwaGkiLCJnYW1tYSIsImV0YSIsImlvdGEiLCJwaGkxIiwia2FwcGEiLCJsYW1iZGEiLCJtdSIsIm51Iiwib21pY3JvbiIsInBpIiwidGhldGEiLCJyaG8iLCJzaWdtYSIsInRhdSIsInVwc2lsb24iLCJvbWVnYTEiLCJvbWVnYSIsInhpIiwicHNpIiwiemV0YSIsImJyYWNlbGVmdCIsImJhciIsImJyYWNlcmlnaHQiLCJzaW1pbGFyIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiIiwiRXVybyIsIlVwc2lsb24xIiwibWludXRlIiwibGVzc2VxdWFsIiwiZnJhY3Rpb24iLCJpbmZpbml0eSIsImZsb3JpbiIsImNsdWIiLCJkaWFtb25kIiwiaGVhcnQiLCJzcGFkZSIsImFycm93Ym90aCIsImFycm93bGVmdCIsImFycm93dXAiLCJhcnJvd3JpZ2h0IiwiYXJyb3dkb3duIiwiZGVncmVlIiwicGx1c21pbnVzIiwic2Vjb25kIiwiZ3JlYXRlcmVxdWFsIiwibXVsdGlwbHkiLCJwcm9wb3J0aW9uYWwiLCJwYXJ0aWFsZGlmZiIsImJ1bGxldCIsImRpdmlkZSIsIm5vdGVxdWFsIiwiZXF1aXZhbGVuY2UiLCJhcHByb3hlcXVhbCIsImVsbGlwc2lzIiwiYXJyb3d2ZXJ0ZXgiLCJhcnJvd2hvcml6ZXgiLCJjYXJyaWFnZXJldHVybiIsImFsZXBoIiwiSWZyYWt0dXIiLCJSZnJha3R1ciIsIndlaWVyc3RyYXNzIiwiY2lyY2xlbXVsdGlwbHkiLCJjaXJjbGVwbHVzIiwiZW1wdHlzZXQiLCJpbnRlcnNlY3Rpb24iLCJ1bmlvbiIsInByb3BlcnN1cGVyc2V0IiwicmVmbGV4c3VwZXJzZXQiLCJub3RzdWJzZXQiLCJwcm9wZXJzdWJzZXQiLCJyZWZsZXhzdWJzZXQiLCJlbGVtZW50Iiwibm90ZWxlbWVudCIsImFuZ2xlIiwiZ3JhZGllbnQiLCJyZWdpc3RlcnNlcmlmIiwiY29weXJpZ2h0c2VyaWYiLCJ0cmFkZW1hcmtzZXJpZiIsInByb2R1Y3QiLCJyYWRpY2FsIiwiZG90bWF0aCIsImxvZ2ljYWxub3QiLCJsb2dpY2FsYW5kIiwibG9naWNhbG9yIiwiYXJyb3dkYmxib3RoIiwiYXJyb3dkYmxsZWZ0IiwiYXJyb3dkYmx1cCIsImFycm93ZGJscmlnaHQiLCJhcnJvd2RibGRvd24iLCJsb3plbmdlIiwiYW5nbGVsZWZ0IiwicmVnaXN0ZXJzYW5zIiwiY29weXJpZ2h0c2FucyIsInRyYWRlbWFya3NhbnMiLCJzdW1tYXRpb24iLCJwYXJlbmxlZnR0cCIsInBhcmVubGVmdGV4IiwicGFyZW5sZWZ0YnQiLCJicmFja2V0bGVmdHRwIiwiYnJhY2tldGxlZnRleCIsImJyYWNrZXRsZWZ0YnQiLCJicmFjZWxlZnR0cCIsImJyYWNlbGVmdG1pZCIsImJyYWNlbGVmdGJ0IiwiYnJhY2VleCIsIiIsImFuZ2xlcmlnaHQiLCJpbnRlZ3JhbCIsImludGVncmFsdHAiLCJpbnRlZ3JhbGV4IiwiaW50ZWdyYWxidCIsInBhcmVucmlnaHR0cCIsInBhcmVucmlnaHRleCIsInBhcmVucmlnaHRidCIsImJyYWNrZXRyaWdodHRwIiwiYnJhY2tldHJpZ2h0ZXgiLCJicmFja2V0cmlnaHRidCIsImJyYWNlcmlnaHR0cCIsImJyYWNlcmlnaHRtaWQiLCJicmFjZXJpZ2h0YnQiLCIiXSxmYT1bIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsInNwYWNlIiwiYTEiLCJhMiIsImEyMDIiLCJhMyIsImE0IiwiYTUiLCJhMTE5IiwiYTExOCIsImExMTciLCJhMTEiLCJhMTIiLCJhMTMiLCJhMTQiLCJhMTUiLCJhMTYiLCJhMTA1IiwiYTE3IiwiYTE4IiwiYTE5IiwiYTIwIiwiYTIxIiwiYTIyIiwiYTIzIiwiYTI0IiwiYTI1IiwiYTI2IiwiYTI3IiwiYTI4IiwiYTYiLCJhNyIsImE4IiwiYTkiLCJhMTAiLCJhMjkiLCJhMzAiLCJhMzEiLCJhMzIiLCJhMzMiLCJhMzQiLCJhMzUiLCJhMzYiLCJhMzciLCJhMzgiLCJhMzkiLCJhNDAiLCJhNDEiLCJhNDIiLCJhNDMiLCJhNDQiLCJhNDUiLCJhNDYiLCJhNDciLCJhNDgiLCJhNDkiLCJhNTAiLCJhNTEiLCJhNTIiLCJhNTMiLCJhNTQiLCJhNTUiLCJhNTYiLCJhNTciLCJhNTgiLCJhNTkiLCJhNjAiLCJhNjEiLCJhNjIiLCJhNjMiLCJhNjQiLCJhNjUiLCJhNjYiLCJhNjciLCJhNjgiLCJhNjkiLCJhNzAiLCJhNzEiLCJhNzIiLCJhNzMiLCJhNzQiLCJhMjAzIiwiYTc1IiwiYTIwNCIsImE3NiIsImE3NyIsImE3OCIsImE3OSIsImE4MSIsImE4MiIsImE4MyIsImE4NCIsImE5NyIsImE5OCIsImE5OSIsImExMDAiLCIiLCJhODkiLCJhOTAiLCJhOTMiLCJhOTQiLCJhOTEiLCJhOTIiLCJhMjA1IiwiYTg1IiwiYTIwNiIsImE4NiIsImE4NyIsImE4OCIsImE5NSIsImE5NiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsImExMDEiLCJhMTAyIiwiYTEwMyIsImExMDQiLCJhMTA2IiwiYTEwNyIsImExMDgiLCJhMTEyIiwiYTExMSIsImExMTAiLCJhMTA5IiwiYTEyMCIsImExMjEiLCJhMTIyIiwiYTEyMyIsImExMjQiLCJhMTI1IiwiYTEyNiIsImExMjciLCJhMTI4IiwiYTEyOSIsImExMzAiLCJhMTMxIiwiYTEzMiIsImExMzMiLCJhMTM0IiwiYTEzNSIsImExMzYiLCJhMTM3IiwiYTEzOCIsImExMzkiLCJhMTQwIiwiYTE0MSIsImExNDIiLCJhMTQzIiwiYTE0NCIsImExNDUiLCJhMTQ2IiwiYTE0NyIsImExNDgiLCJhMTQ5IiwiYTE1MCIsImExNTEiLCJhMTUyIiwiYTE1MyIsImExNTQiLCJhMTU1IiwiYTE1NiIsImExNTciLCJhMTU4IiwiYTE1OSIsImExNjAiLCJhMTYxIiwiYTE2MyIsImExNjQiLCJhMTk2IiwiYTE2NSIsImExOTIiLCJhMTY2IiwiYTE2NyIsImExNjgiLCJhMTY5IiwiYTE3MCIsImExNzEiLCJhMTcyIiwiYTE3MyIsImExNjIiLCJhMTc0IiwiYTE3NSIsImExNzYiLCJhMTc3IiwiYTE3OCIsImExNzkiLCJhMTkzIiwiYTE4MCIsImExOTkiLCJhMTgxIiwiYTIwMCIsImExODIiLCIiLCJhMjAxIiwiYTE4MyIsImExODQiLCJhMTk3IiwiYTE4NSIsImExOTQiLCJhMTk4IiwiYTE4NiIsImExOTUiLCJhMTg3IiwiYTE4OCIsImExODkiLCJhMTkwIiwiYTE5MSIsIiJdO2Z1bmN0aW9uIGdldEVuY29kaW5nKGUpe3N3aXRjaChlKXtjYXNlIldpbkFuc2lFbmNvZGluZyI6cmV0dXJuIHVhO2Nhc2UiU3RhbmRhcmRFbmNvZGluZyI6cmV0dXJuIGhhO2Nhc2UiTWFjUm9tYW5FbmNvZGluZyI6cmV0dXJuIGxhO2Nhc2UiU3ltYm9sU2V0RW5jb2RpbmciOnJldHVybiBkYTtjYXNlIlphcGZEaW5nYmF0c0VuY29kaW5nIjpyZXR1cm4gZmE7Y2FzZSJFeHBlcnRFbmNvZGluZyI6cmV0dXJuIG9hO2Nhc2UiTWFjRXhwZXJ0RW5jb2RpbmciOnJldHVybiBjYTtkZWZhdWx0OnJldHVybiBudWxsfX1jb25zdCBnYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5BPTY1O2UuQUU9MTk4O2UuQUVhY3V0ZT01MDg7ZS5BRW1hY3Jvbj00ODI7ZS5BRXNtYWxsPTYzNDYyO2UuQWFjdXRlPTE5MztlLkFhY3V0ZXNtYWxsPTYzNDU3O2UuQWJyZXZlPTI1ODtlLkFicmV2ZWFjdXRlPTc4NTQ7ZS5BYnJldmVjeXJpbGxpYz0xMjMyO2UuQWJyZXZlZG90YmVsb3c9Nzg2MjtlLkFicmV2ZWdyYXZlPTc4NTY7ZS5BYnJldmVob29rYWJvdmU9Nzg1ODtlLkFicmV2ZXRpbGRlPTc4NjA7ZS5BY2Fyb249NDYxO2UuQWNpcmNsZT05Mzk4O2UuQWNpcmN1bWZsZXg9MTk0O2UuQWNpcmN1bWZsZXhhY3V0ZT03ODQ0O2UuQWNpcmN1bWZsZXhkb3RiZWxvdz03ODUyO2UuQWNpcmN1bWZsZXhncmF2ZT03ODQ2O2UuQWNpcmN1bWZsZXhob29rYWJvdmU9Nzg0ODtlLkFjaXJjdW1mbGV4c21hbGw9NjM0NTg7ZS5BY2lyY3VtZmxleHRpbGRlPTc4NTA7ZS5BY3V0ZT02MzE3NztlLkFjdXRlc21hbGw9NjM0MTI7ZS5BY3lyaWxsaWM9MTA0MDtlLkFkYmxncmF2ZT01MTI7ZS5BZGllcmVzaXM9MTk2O2UuQWRpZXJlc2lzY3lyaWxsaWM9MTIzNDtlLkFkaWVyZXNpc21hY3Jvbj00Nzg7ZS5BZGllcmVzaXNzbWFsbD02MzQ2MDtlLkFkb3RiZWxvdz03ODQwO2UuQWRvdG1hY3Jvbj00ODA7ZS5BZ3JhdmU9MTkyO2UuQWdyYXZlc21hbGw9NjM0NTY7ZS5BaG9va2Fib3ZlPTc4NDI7ZS5BaWVjeXJpbGxpYz0xMjM2O2UuQWludmVydGVkYnJldmU9NTE0O2UuQWxwaGE9OTEzO2UuQWxwaGF0b25vcz05MDI7ZS5BbWFjcm9uPTI1NjtlLkFtb25vc3BhY2U9NjUzMTM7ZS5Bb2dvbmVrPTI2MDtlLkFyaW5nPTE5NztlLkFyaW5nYWN1dGU9NTA2O2UuQXJpbmdiZWxvdz03NjgwO2UuQXJpbmdzbWFsbD02MzQ2MTtlLkFzbWFsbD02MzMyOTtlLkF0aWxkZT0xOTU7ZS5BdGlsZGVzbWFsbD02MzQ1OTtlLkF5YmFybWVuaWFuPTEzMjk7ZS5CPTY2O2UuQmNpcmNsZT05Mzk5O2UuQmRvdGFjY2VudD03NjgyO2UuQmRvdGJlbG93PTc2ODQ7ZS5CZWN5cmlsbGljPTEwNDE7ZS5CZW5hcm1lbmlhbj0xMzMwO2UuQmV0YT05MTQ7ZS5CaG9vaz0zODU7ZS5CbGluZWJlbG93PTc2ODY7ZS5CbW9ub3NwYWNlPTY1MzE0O2UuQnJldmVzbWFsbD02MzIyMDtlLkJzbWFsbD02MzMzMDtlLkJ0b3BiYXI9Mzg2O2UuQz02NztlLkNhYXJtZW5pYW49MTM0MjtlLkNhY3V0ZT0yNjI7ZS5DYXJvbj02MzE3ODtlLkNhcm9uc21hbGw9NjMyMjE7ZS5DY2Fyb249MjY4O2UuQ2NlZGlsbGE9MTk5O2UuQ2NlZGlsbGFhY3V0ZT03Njg4O2UuQ2NlZGlsbGFzbWFsbD02MzQ2MztlLkNjaXJjbGU9OTQwMDtlLkNjaXJjdW1mbGV4PTI2NDtlLkNkb3Q9MjY2O2UuQ2RvdGFjY2VudD0yNjY7ZS5DZWRpbGxhc21hbGw9NjM0MTY7ZS5DaGFhcm1lbmlhbj0xMzUzO2UuQ2hlYWJraGFzaWFuY3lyaWxsaWM9MTIxMjtlLkNoZWN5cmlsbGljPTEwNjM7ZS5DaGVkZXNjZW5kZXJhYmtoYXNpYW5jeXJpbGxpYz0xMjE0O2UuQ2hlZGVzY2VuZGVyY3lyaWxsaWM9MTIwNjtlLkNoZWRpZXJlc2lzY3lyaWxsaWM9MTI2ODtlLkNoZWhhcm1lbmlhbj0xMzQ3O2UuQ2hla2hha2Fzc2lhbmN5cmlsbGljPTEyMjc7ZS5DaGV2ZXJ0aWNhbHN0cm9rZWN5cmlsbGljPTEyMDg7ZS5DaGk9OTM1O2UuQ2hvb2s9MzkxO2UuQ2lyY3VtZmxleHNtYWxsPTYzMjIyO2UuQ21vbm9zcGFjZT02NTMxNTtlLkNvYXJtZW5pYW49MTM2MTtlLkNzbWFsbD02MzMzMTtlLkQ9Njg7ZS5EWj00OTc7ZS5EWmNhcm9uPTQ1MjtlLkRhYXJtZW5pYW49MTMzMjtlLkRhZnJpY2FuPTM5MztlLkRjYXJvbj0yNzA7ZS5EY2VkaWxsYT03Njk2O2UuRGNpcmNsZT05NDAxO2UuRGNpcmN1bWZsZXhiZWxvdz03Njk4O2UuRGNyb2F0PTI3MjtlLkRkb3RhY2NlbnQ9NzY5MDtlLkRkb3RiZWxvdz03NjkyO2UuRGVjeXJpbGxpYz0xMDQ0O2UuRGVpY29wdGljPTEwMDY7ZS5EZWx0YT04NzEwO2UuRGVsdGFncmVlaz05MTY7ZS5EaG9vaz0zOTQ7ZS5EaWVyZXNpcz02MzE3OTtlLkRpZXJlc2lzQWN1dGU9NjMxODA7ZS5EaWVyZXNpc0dyYXZlPTYzMTgxO2UuRGllcmVzaXNzbWFsbD02MzQwMDtlLkRpZ2FtbWFncmVlaz05ODg7ZS5EamVjeXJpbGxpYz0xMDI2O2UuRGxpbmViZWxvdz03Njk0O2UuRG1vbm9zcGFjZT02NTMxNjtlLkRvdGFjY2VudHNtYWxsPTYzMjIzO2UuRHNsYXNoPTI3MjtlLkRzbWFsbD02MzMzMjtlLkR0b3BiYXI9Mzk1O2UuRHo9NDk4O2UuRHpjYXJvbj00NTM7ZS5EemVhYmtoYXNpYW5jeXJpbGxpYz0xMjQ4O2UuRHplY3lyaWxsaWM9MTAyOTtlLkR6aGVjeXJpbGxpYz0xMDM5O2UuRT02OTtlLkVhY3V0ZT0yMDE7ZS5FYWN1dGVzbWFsbD02MzQ2NTtlLkVicmV2ZT0yNzY7ZS5FY2Fyb249MjgyO2UuRWNlZGlsbGFicmV2ZT03NzA4O2UuRWNoYXJtZW5pYW49MTMzMztlLkVjaXJjbGU9OTQwMjtlLkVjaXJjdW1mbGV4PTIwMjtlLkVjaXJjdW1mbGV4YWN1dGU9Nzg3MDtlLkVjaXJjdW1mbGV4YmVsb3c9NzcwNDtlLkVjaXJjdW1mbGV4ZG90YmVsb3c9Nzg3ODtlLkVjaXJjdW1mbGV4Z3JhdmU9Nzg3MjtlLkVjaXJjdW1mbGV4aG9va2Fib3ZlPTc4NzQ7ZS5FY2lyY3VtZmxleHNtYWxsPTYzNDY2O2UuRWNpcmN1bWZsZXh0aWxkZT03ODc2O2UuRWN5cmlsbGljPTEwMjg7ZS5FZGJsZ3JhdmU9NTE2O2UuRWRpZXJlc2lzPTIwMztlLkVkaWVyZXNpc3NtYWxsPTYzNDY3O2UuRWRvdD0yNzg7ZS5FZG90YWNjZW50PTI3ODtlLkVkb3RiZWxvdz03ODY0O2UuRWZjeXJpbGxpYz0xMDYwO2UuRWdyYXZlPTIwMDtlLkVncmF2ZXNtYWxsPTYzNDY0O2UuRWhhcm1lbmlhbj0xMzM1O2UuRWhvb2thYm92ZT03ODY2O2UuRWlnaHRyb21hbj04NTUxO2UuRWludmVydGVkYnJldmU9NTE4O2UuRWlvdGlmaWVkY3lyaWxsaWM9MTEyNDtlLkVsY3lyaWxsaWM9MTA1MTtlLkVsZXZlbnJvbWFuPTg1NTQ7ZS5FbWFjcm9uPTI3NDtlLkVtYWNyb25hY3V0ZT03NzAyO2UuRW1hY3JvbmdyYXZlPTc3MDA7ZS5FbWN5cmlsbGljPTEwNTI7ZS5FbW9ub3NwYWNlPTY1MzE3O2UuRW5jeXJpbGxpYz0xMDUzO2UuRW5kZXNjZW5kZXJjeXJpbGxpYz0xMTg2O2UuRW5nPTMzMDtlLkVuZ2hlY3lyaWxsaWM9MTE4ODtlLkVuaG9va2N5cmlsbGljPTEyMjM7ZS5Fb2dvbmVrPTI4MDtlLkVvcGVuPTQwMDtlLkVwc2lsb249OTE3O2UuRXBzaWxvbnRvbm9zPTkwNDtlLkVyY3lyaWxsaWM9MTA1NjtlLkVyZXZlcnNlZD0zOTg7ZS5FcmV2ZXJzZWRjeXJpbGxpYz0xMDY5O2UuRXNjeXJpbGxpYz0xMDU3O2UuRXNkZXNjZW5kZXJjeXJpbGxpYz0xMTk0O2UuRXNoPTQyNTtlLkVzbWFsbD02MzMzMztlLkV0YT05MTk7ZS5FdGFybWVuaWFuPTEzMzY7ZS5FdGF0b25vcz05MDU7ZS5FdGg9MjA4O2UuRXRoc21hbGw9NjM0NzI7ZS5FdGlsZGU9Nzg2ODtlLkV0aWxkZWJlbG93PTc3MDY7ZS5FdXJvPTgzNjQ7ZS5Femg9NDM5O2UuRXpoY2Fyb249NDk0O2UuRXpocmV2ZXJzZWQ9NDQwO2UuRj03MDtlLkZjaXJjbGU9OTQwMztlLkZkb3RhY2NlbnQ9NzcxMDtlLkZlaGFybWVuaWFuPTEzNjY7ZS5GZWljb3B0aWM9OTk2O2UuRmhvb2s9NDAxO2UuRml0YWN5cmlsbGljPTExMzg7ZS5GaXZlcm9tYW49ODU0ODtlLkZtb25vc3BhY2U9NjUzMTg7ZS5Gb3Vycm9tYW49ODU0NztlLkZzbWFsbD02MzMzNDtlLkc9NzE7ZS5HQnNxdWFyZT0xMzE5MTtlLkdhY3V0ZT01MDA7ZS5HYW1tYT05MTU7ZS5HYW1tYWFmcmljYW49NDA0O2UuR2FuZ2lhY29wdGljPTEwMDI7ZS5HYnJldmU9Mjg2O2UuR2Nhcm9uPTQ4NjtlLkdjZWRpbGxhPTI5MDtlLkdjaXJjbGU9OTQwNDtlLkdjaXJjdW1mbGV4PTI4NDtlLkdjb21tYWFjY2VudD0yOTA7ZS5HZG90PTI4ODtlLkdkb3RhY2NlbnQ9Mjg4O2UuR2VjeXJpbGxpYz0xMDQzO2UuR2hhZGFybWVuaWFuPTEzNDY7ZS5HaGVtaWRkbGVob29rY3lyaWxsaWM9MTE3MjtlLkdoZXN0cm9rZWN5cmlsbGljPTExNzA7ZS5HaGV1cHR1cm5jeXJpbGxpYz0xMTY4O2UuR2hvb2s9NDAzO2UuR2ltYXJtZW5pYW49MTMzMTtlLkdqZWN5cmlsbGljPTEwMjc7ZS5HbWFjcm9uPTc3MTI7ZS5HbW9ub3NwYWNlPTY1MzE5O2UuR3JhdmU9NjMxODI7ZS5HcmF2ZXNtYWxsPTYzMzI4O2UuR3NtYWxsPTYzMzM1O2UuR3NtYWxsaG9vaz02Njc7ZS5Hc3Ryb2tlPTQ4NDtlLkg9NzI7ZS5IMTg1MzM9OTY3OTtlLkgxODU0Mz05NjQyO2UuSDE4NTUxPTk2NDM7ZS5IMjIwNzM9OTYzMztlLkhQc3F1YXJlPTEzMjU5O2UuSGFhYmtoYXNpYW5jeXJpbGxpYz0xMTkyO2UuSGFkZXNjZW5kZXJjeXJpbGxpYz0xMjAyO2UuSGFyZHNpZ25jeXJpbGxpYz0xMDY2O2UuSGJhcj0yOTQ7ZS5IYnJldmViZWxvdz03NzIyO2UuSGNlZGlsbGE9NzcyMDtlLkhjaXJjbGU9OTQwNTtlLkhjaXJjdW1mbGV4PTI5MjtlLkhkaWVyZXNpcz03NzE4O2UuSGRvdGFjY2VudD03NzE0O2UuSGRvdGJlbG93PTc3MTY7ZS5IbW9ub3NwYWNlPTY1MzIwO2UuSG9hcm1lbmlhbj0xMzQ0O2UuSG9yaWNvcHRpYz0xZTM7ZS5Ic21hbGw9NjMzMzY7ZS5IdW5nYXJ1bWxhdXQ9NjMxODM7ZS5IdW5nYXJ1bWxhdXRzbWFsbD02MzIyNDtlLkh6c3F1YXJlPTEzMjAwO2UuST03MztlLklBY3lyaWxsaWM9MTA3MTtlLklKPTMwNjtlLklVY3lyaWxsaWM9MTA3MDtlLklhY3V0ZT0yMDU7ZS5JYWN1dGVzbWFsbD02MzQ2OTtlLklicmV2ZT0zMDA7ZS5JY2Fyb249NDYzO2UuSWNpcmNsZT05NDA2O2UuSWNpcmN1bWZsZXg9MjA2O2UuSWNpcmN1bWZsZXhzbWFsbD02MzQ3MDtlLkljeXJpbGxpYz0xMDMwO2UuSWRibGdyYXZlPTUyMDtlLklkaWVyZXNpcz0yMDc7ZS5JZGllcmVzaXNhY3V0ZT03NzI2O2UuSWRpZXJlc2lzY3lyaWxsaWM9MTI1MjtlLklkaWVyZXNpc3NtYWxsPTYzNDcxO2UuSWRvdD0zMDQ7ZS5JZG90YWNjZW50PTMwNDtlLklkb3RiZWxvdz03ODgyO2UuSWVicmV2ZWN5cmlsbGljPTEyMzg7ZS5JZWN5cmlsbGljPTEwNDU7ZS5JZnJha3R1cj04NDY1O2UuSWdyYXZlPTIwNDtlLklncmF2ZXNtYWxsPTYzNDY4O2UuSWhvb2thYm92ZT03ODgwO2UuSWljeXJpbGxpYz0xMDQ4O2UuSWludmVydGVkYnJldmU9NTIyO2UuSWlzaG9ydGN5cmlsbGljPTEwNDk7ZS5JbWFjcm9uPTI5ODtlLkltYWNyb25jeXJpbGxpYz0xMjUwO2UuSW1vbm9zcGFjZT02NTMyMTtlLkluaWFybWVuaWFuPTEzMzk7ZS5Jb2N5cmlsbGljPTEwMjU7ZS5Jb2dvbmVrPTMwMjtlLklvdGE9OTIxO2UuSW90YWFmcmljYW49NDA2O2UuSW90YWRpZXJlc2lzPTkzODtlLklvdGF0b25vcz05MDY7ZS5Jc21hbGw9NjMzMzc7ZS5Jc3Ryb2tlPTQwNztlLkl0aWxkZT0yOTY7ZS5JdGlsZGViZWxvdz03NzI0O2UuSXpoaXRzYWN5cmlsbGljPTExNDA7ZS5JemhpdHNhZGJsZ3JhdmVjeXJpbGxpYz0xMTQyO2UuSj03NDtlLkphYXJtZW5pYW49MTM0NTtlLkpjaXJjbGU9OTQwNztlLkpjaXJjdW1mbGV4PTMwODtlLkplY3lyaWxsaWM9MTAzMjtlLkpoZWhhcm1lbmlhbj0xMzU1O2UuSm1vbm9zcGFjZT02NTMyMjtlLkpzbWFsbD02MzMzODtlLks9NzU7ZS5LQnNxdWFyZT0xMzE4OTtlLktLc3F1YXJlPTEzMjYxO2UuS2FiYXNoa2lyY3lyaWxsaWM9MTE4NDtlLkthY3V0ZT03NzI4O2UuS2FjeXJpbGxpYz0xMDUwO2UuS2FkZXNjZW5kZXJjeXJpbGxpYz0xMTc4O2UuS2Fob29rY3lyaWxsaWM9MTIxOTtlLkthcHBhPTkyMjtlLkthc3Ryb2tlY3lyaWxsaWM9MTE4MjtlLkthdmVydGljYWxzdHJva2VjeXJpbGxpYz0xMTgwO2UuS2Nhcm9uPTQ4ODtlLktjZWRpbGxhPTMxMDtlLktjaXJjbGU9OTQwODtlLktjb21tYWFjY2VudD0zMTA7ZS5LZG90YmVsb3c9NzczMDtlLktlaGFybWVuaWFuPTEzNjQ7ZS5LZW5hcm1lbmlhbj0xMzQzO2UuS2hhY3lyaWxsaWM9MTA2MTtlLktoZWljb3B0aWM9OTk4O2UuS2hvb2s9NDA4O2UuS2plY3lyaWxsaWM9MTAzNjtlLktsaW5lYmVsb3c9NzczMjtlLkttb25vc3BhY2U9NjUzMjM7ZS5Lb3BwYWN5cmlsbGljPTExNTI7ZS5Lb3BwYWdyZWVrPTk5MDtlLktzaWN5cmlsbGljPTExMzQ7ZS5Lc21hbGw9NjMzMzk7ZS5MPTc2O2UuTEo9NDU1O2UuTEw9NjMxNjc7ZS5MYWN1dGU9MzEzO2UuTGFtYmRhPTkyMztlLkxjYXJvbj0zMTc7ZS5MY2VkaWxsYT0zMTU7ZS5MY2lyY2xlPTk0MDk7ZS5MY2lyY3VtZmxleGJlbG93PTc3NDA7ZS5MY29tbWFhY2NlbnQ9MzE1O2UuTGRvdD0zMTk7ZS5MZG90YWNjZW50PTMxOTtlLkxkb3RiZWxvdz03NzM0O2UuTGRvdGJlbG93bWFjcm9uPTc3MzY7ZS5MaXduYXJtZW5pYW49MTM0MDtlLkxqPTQ1NjtlLkxqZWN5cmlsbGljPTEwMzM7ZS5MbGluZWJlbG93PTc3Mzg7ZS5MbW9ub3NwYWNlPTY1MzI0O2UuTHNsYXNoPTMyMTtlLkxzbGFzaHNtYWxsPTYzMjI1O2UuTHNtYWxsPTYzMzQwO2UuTT03NztlLk1Cc3F1YXJlPTEzMTkwO2UuTWFjcm9uPTYzMTg0O2UuTWFjcm9uc21hbGw9NjM0MDc7ZS5NYWN1dGU9Nzc0MjtlLk1jaXJjbGU9OTQxMDtlLk1kb3RhY2NlbnQ9Nzc0NDtlLk1kb3RiZWxvdz03NzQ2O2UuTWVuYXJtZW5pYW49MTM0ODtlLk1tb25vc3BhY2U9NjUzMjU7ZS5Nc21hbGw9NjMzNDE7ZS5NdHVybmVkPTQxMjtlLk11PTkyNDtlLk49Nzg7ZS5OSj00NTg7ZS5OYWN1dGU9MzIzO2UuTmNhcm9uPTMyNztlLk5jZWRpbGxhPTMyNTtlLk5jaXJjbGU9OTQxMTtlLk5jaXJjdW1mbGV4YmVsb3c9Nzc1NDtlLk5jb21tYWFjY2VudD0zMjU7ZS5OZG90YWNjZW50PTc3NDg7ZS5OZG90YmVsb3c9Nzc1MDtlLk5ob29rbGVmdD00MTM7ZS5OaW5lcm9tYW49ODU1MjtlLk5qPTQ1OTtlLk5qZWN5cmlsbGljPTEwMzQ7ZS5ObGluZWJlbG93PTc3NTI7ZS5ObW9ub3NwYWNlPTY1MzI2O2UuTm93YXJtZW5pYW49MTM1MDtlLk5zbWFsbD02MzM0MjtlLk50aWxkZT0yMDk7ZS5OdGlsZGVzbWFsbD02MzQ3MztlLk51PTkyNTtlLk89Nzk7ZS5PRT0zMzg7ZS5PRXNtYWxsPTYzMjI2O2UuT2FjdXRlPTIxMTtlLk9hY3V0ZXNtYWxsPTYzNDc1O2UuT2JhcnJlZGN5cmlsbGljPTEyNTY7ZS5PYmFycmVkZGllcmVzaXNjeXJpbGxpYz0xMjU4O2UuT2JyZXZlPTMzNDtlLk9jYXJvbj00NjU7ZS5PY2VudGVyZWR0aWxkZT00MTU7ZS5PY2lyY2xlPTk0MTI7ZS5PY2lyY3VtZmxleD0yMTI7ZS5PY2lyY3VtZmxleGFjdXRlPTc4ODg7ZS5PY2lyY3VtZmxleGRvdGJlbG93PTc4OTY7ZS5PY2lyY3VtZmxleGdyYXZlPTc4OTA7ZS5PY2lyY3VtZmxleGhvb2thYm92ZT03ODkyO2UuT2NpcmN1bWZsZXhzbWFsbD02MzQ3NjtlLk9jaXJjdW1mbGV4dGlsZGU9Nzg5NDtlLk9jeXJpbGxpYz0xMDU0O2UuT2RibGFjdXRlPTMzNjtlLk9kYmxncmF2ZT01MjQ7ZS5PZGllcmVzaXM9MjE0O2UuT2RpZXJlc2lzY3lyaWxsaWM9MTI1NDtlLk9kaWVyZXNpc3NtYWxsPTYzNDc4O2UuT2RvdGJlbG93PTc4ODQ7ZS5PZ29uZWtzbWFsbD02MzIyNztlLk9ncmF2ZT0yMTA7ZS5PZ3JhdmVzbWFsbD02MzQ3NDtlLk9oYXJtZW5pYW49MTM2NTtlLk9obT04NDg2O2UuT2hvb2thYm92ZT03ODg2O2UuT2hvcm49NDE2O2UuT2hvcm5hY3V0ZT03ODk4O2UuT2hvcm5kb3RiZWxvdz03OTA2O2UuT2hvcm5ncmF2ZT03OTAwO2UuT2hvcm5ob29rYWJvdmU9NzkwMjtlLk9ob3JudGlsZGU9NzkwNDtlLk9odW5nYXJ1bWxhdXQ9MzM2O2UuT2k9NDE4O2UuT2ludmVydGVkYnJldmU9NTI2O2UuT21hY3Jvbj0zMzI7ZS5PbWFjcm9uYWN1dGU9Nzc2MjtlLk9tYWNyb25ncmF2ZT03NzYwO2UuT21lZ2E9ODQ4NjtlLk9tZWdhY3lyaWxsaWM9MTEyMDtlLk9tZWdhZ3JlZWs9OTM3O2UuT21lZ2Fyb3VuZGN5cmlsbGljPTExNDY7ZS5PbWVnYXRpdGxvY3lyaWxsaWM9MTE0ODtlLk9tZWdhdG9ub3M9OTExO2UuT21pY3Jvbj05Mjc7ZS5PbWljcm9udG9ub3M9OTA4O2UuT21vbm9zcGFjZT02NTMyNztlLk9uZXJvbWFuPTg1NDQ7ZS5Pb2dvbmVrPTQ5MDtlLk9vZ29uZWttYWNyb249NDkyO2UuT29wZW49MzkwO2UuT3NsYXNoPTIxNjtlLk9zbGFzaGFjdXRlPTUxMDtlLk9zbGFzaHNtYWxsPTYzNDgwO2UuT3NtYWxsPTYzMzQzO2UuT3N0cm9rZWFjdXRlPTUxMDtlLk90Y3lyaWxsaWM9MTE1MDtlLk90aWxkZT0yMTM7ZS5PdGlsZGVhY3V0ZT03NzU2O2UuT3RpbGRlZGllcmVzaXM9Nzc1ODtlLk90aWxkZXNtYWxsPTYzNDc3O2UuUD04MDtlLlBhY3V0ZT03NzY0O2UuUGNpcmNsZT05NDEzO2UuUGRvdGFjY2VudD03NzY2O2UuUGVjeXJpbGxpYz0xMDU1O2UuUGVoYXJtZW5pYW49MTM1NDtlLlBlbWlkZGxlaG9va2N5cmlsbGljPTExOTA7ZS5QaGk9OTM0O2UuUGhvb2s9NDIwO2UuUGk9OTI4O2UuUGl3cmFybWVuaWFuPTEzNjM7ZS5QbW9ub3NwYWNlPTY1MzI4O2UuUHNpPTkzNjtlLlBzaWN5cmlsbGljPTExMzY7ZS5Qc21hbGw9NjMzNDQ7ZS5RPTgxO2UuUWNpcmNsZT05NDE0O2UuUW1vbm9zcGFjZT02NTMyOTtlLlFzbWFsbD02MzM0NTtlLlI9ODI7ZS5SYWFybWVuaWFuPTEzNTY7ZS5SYWN1dGU9MzQwO2UuUmNhcm9uPTM0NDtlLlJjZWRpbGxhPTM0MjtlLlJjaXJjbGU9OTQxNTtlLlJjb21tYWFjY2VudD0zNDI7ZS5SZGJsZ3JhdmU9NTI4O2UuUmRvdGFjY2VudD03NzY4O2UuUmRvdGJlbG93PTc3NzA7ZS5SZG90YmVsb3dtYWNyb249Nzc3MjtlLlJlaGFybWVuaWFuPTEzNjA7ZS5SZnJha3R1cj04NDc2O2UuUmhvPTkyOTtlLlJpbmdzbWFsbD02MzIyODtlLlJpbnZlcnRlZGJyZXZlPTUzMDtlLlJsaW5lYmVsb3c9Nzc3NDtlLlJtb25vc3BhY2U9NjUzMzA7ZS5Sc21hbGw9NjMzNDY7ZS5Sc21hbGxpbnZlcnRlZD02NDE7ZS5Sc21hbGxpbnZlcnRlZHN1cGVyaW9yPTY5NDtlLlM9ODM7ZS5TRjAxMDAwMD05NDg0O2UuU0YwMjAwMDA9OTQ5MjtlLlNGMDMwMDAwPTk0ODg7ZS5TRjA0MDAwMD05NDk2O2UuU0YwNTAwMDA9OTUzMjtlLlNGMDYwMDAwPTk1MTY7ZS5TRjA3MDAwMD05NTI0O2UuU0YwODAwMDA9OTUwMDtlLlNGMDkwMDAwPTk1MDg7ZS5TRjEwMDAwMD05NDcyO2UuU0YxMTAwMDA9OTQ3NDtlLlNGMTkwMDAwPTk1Njk7ZS5TRjIwMDAwMD05NTcwO2UuU0YyMTAwMDA9OTU1ODtlLlNGMjIwMDAwPTk1NTc7ZS5TRjIzMDAwMD05NTcxO2UuU0YyNDAwMDA9OTU1MztlLlNGMjUwMDAwPTk1NTk7ZS5TRjI2MDAwMD05NTY1O2UuU0YyNzAwMDA9OTU2NDtlLlNGMjgwMDAwPTk1NjM7ZS5TRjM2MDAwMD05NTY2O2UuU0YzNzAwMDA9OTU2NztlLlNGMzgwMDAwPTk1NjI7ZS5TRjM5MDAwMD05NTU2O2UuU0Y0MDAwMDA9OTU3NztlLlNGNDEwMDAwPTk1NzQ7ZS5TRjQyMDAwMD05NTY4O2UuU0Y0MzAwMDA9OTU1MjtlLlNGNDQwMDAwPTk1ODA7ZS5TRjQ1MDAwMD05NTc1O2UuU0Y0NjAwMDA9OTU3NjtlLlNGNDcwMDAwPTk1NzI7ZS5TRjQ4MDAwMD05NTczO2UuU0Y0OTAwMDA9OTU2MTtlLlNGNTAwMDAwPTk1NjA7ZS5TRjUxMDAwMD05NTU0O2UuU0Y1MjAwMDA9OTU1NTtlLlNGNTMwMDAwPTk1Nzk7ZS5TRjU0MDAwMD05NTc4O2UuU2FjdXRlPTM0NjtlLlNhY3V0ZWRvdGFjY2VudD03NzgwO2UuU2FtcGlncmVlaz05OTI7ZS5TY2Fyb249MzUyO2UuU2Nhcm9uZG90YWNjZW50PTc3ODI7ZS5TY2Fyb25zbWFsbD02MzIyOTtlLlNjZWRpbGxhPTM1MDtlLlNjaHdhPTM5OTtlLlNjaHdhY3lyaWxsaWM9MTI0MDtlLlNjaHdhZGllcmVzaXNjeXJpbGxpYz0xMjQyO2UuU2NpcmNsZT05NDE2O2UuU2NpcmN1bWZsZXg9MzQ4O2UuU2NvbW1hYWNjZW50PTUzNjtlLlNkb3RhY2NlbnQ9Nzc3NjtlLlNkb3RiZWxvdz03Nzc4O2UuU2RvdGJlbG93ZG90YWNjZW50PTc3ODQ7ZS5TZWhhcm1lbmlhbj0xMzU3O2UuU2V2ZW5yb21hbj04NTUwO2UuU2hhYXJtZW5pYW49MTM1MTtlLlNoYWN5cmlsbGljPTEwNjQ7ZS5TaGNoYWN5cmlsbGljPTEwNjU7ZS5TaGVpY29wdGljPTk5NDtlLlNoaGFjeXJpbGxpYz0xMjEwO2UuU2hpbWFjb3B0aWM9MTAwNDtlLlNpZ21hPTkzMTtlLlNpeHJvbWFuPTg1NDk7ZS5TbW9ub3NwYWNlPTY1MzMxO2UuU29mdHNpZ25jeXJpbGxpYz0xMDY4O2UuU3NtYWxsPTYzMzQ3O2UuU3RpZ21hZ3JlZWs9OTg2O2UuVD04NDtlLlRhdT05MzI7ZS5UYmFyPTM1ODtlLlRjYXJvbj0zNTY7ZS5UY2VkaWxsYT0zNTQ7ZS5UY2lyY2xlPTk0MTc7ZS5UY2lyY3VtZmxleGJlbG93PTc3OTI7ZS5UY29tbWFhY2NlbnQ9MzU0O2UuVGRvdGFjY2VudD03Nzg2O2UuVGRvdGJlbG93PTc3ODg7ZS5UZWN5cmlsbGljPTEwNTg7ZS5UZWRlc2NlbmRlcmN5cmlsbGljPTExOTY7ZS5UZW5yb21hbj04NTUzO2UuVGV0c2VjeXJpbGxpYz0xMjA0O2UuVGhldGE9OTIwO2UuVGhvb2s9NDI4O2UuVGhvcm49MjIyO2UuVGhvcm5zbWFsbD02MzQ4NjtlLlRocmVlcm9tYW49ODU0NjtlLlRpbGRlc21hbGw9NjMyMzA7ZS5UaXduYXJtZW5pYW49MTM1OTtlLlRsaW5lYmVsb3c9Nzc5MDtlLlRtb25vc3BhY2U9NjUzMzI7ZS5Ub2FybWVuaWFuPTEzMzc7ZS5Ub25lZml2ZT00NDQ7ZS5Ub25lc2l4PTM4ODtlLlRvbmV0d289NDIzO2UuVHJldHJvZmxleGhvb2s9NDMwO2UuVHNlY3lyaWxsaWM9MTA2MjtlLlRzaGVjeXJpbGxpYz0xMDM1O2UuVHNtYWxsPTYzMzQ4O2UuVHdlbHZlcm9tYW49ODU1NTtlLlR3b3JvbWFuPTg1NDU7ZS5VPTg1O2UuVWFjdXRlPTIxODtlLlVhY3V0ZXNtYWxsPTYzNDgyO2UuVWJyZXZlPTM2NDtlLlVjYXJvbj00Njc7ZS5VY2lyY2xlPTk0MTg7ZS5VY2lyY3VtZmxleD0yMTk7ZS5VY2lyY3VtZmxleGJlbG93PTc3OTg7ZS5VY2lyY3VtZmxleHNtYWxsPTYzNDgzO2UuVWN5cmlsbGljPTEwNTk7ZS5VZGJsYWN1dGU9MzY4O2UuVWRibGdyYXZlPTUzMjtlLlVkaWVyZXNpcz0yMjA7ZS5VZGllcmVzaXNhY3V0ZT00NzE7ZS5VZGllcmVzaXNiZWxvdz03Nzk0O2UuVWRpZXJlc2lzY2Fyb249NDczO2UuVWRpZXJlc2lzY3lyaWxsaWM9MTI2NDtlLlVkaWVyZXNpc2dyYXZlPTQ3NTtlLlVkaWVyZXNpc21hY3Jvbj00Njk7ZS5VZGllcmVzaXNzbWFsbD02MzQ4NDtlLlVkb3RiZWxvdz03OTA4O2UuVWdyYXZlPTIxNztlLlVncmF2ZXNtYWxsPTYzNDgxO2UuVWhvb2thYm92ZT03OTEwO2UuVWhvcm49NDMxO2UuVWhvcm5hY3V0ZT03OTEyO2UuVWhvcm5kb3RiZWxvdz03OTIwO2UuVWhvcm5ncmF2ZT03OTE0O2UuVWhvcm5ob29rYWJvdmU9NzkxNjtlLlVob3JudGlsZGU9NzkxODtlLlVodW5nYXJ1bWxhdXQ9MzY4O2UuVWh1bmdhcnVtbGF1dGN5cmlsbGljPTEyNjY7ZS5VaW52ZXJ0ZWRicmV2ZT01MzQ7ZS5Va2N5cmlsbGljPTExNDQ7ZS5VbWFjcm9uPTM2MjtlLlVtYWNyb25jeXJpbGxpYz0xMjYyO2UuVW1hY3JvbmRpZXJlc2lzPTc4MDI7ZS5VbW9ub3NwYWNlPTY1MzMzO2UuVW9nb25laz0zNzA7ZS5VcHNpbG9uPTkzMztlLlVwc2lsb24xPTk3ODtlLlVwc2lsb25hY3V0ZWhvb2tzeW1ib2xncmVlaz05Nzk7ZS5VcHNpbG9uYWZyaWNhbj00MzM7ZS5VcHNpbG9uZGllcmVzaXM9OTM5O2UuVXBzaWxvbmRpZXJlc2lzaG9va3N5bWJvbGdyZWVrPTk4MDtlLlVwc2lsb25ob29rc3ltYm9sPTk3ODtlLlVwc2lsb250b25vcz05MTA7ZS5VcmluZz0zNjY7ZS5Vc2hvcnRjeXJpbGxpYz0xMDM4O2UuVXNtYWxsPTYzMzQ5O2UuVXN0cmFpZ2h0Y3lyaWxsaWM9MTE5ODtlLlVzdHJhaWdodHN0cm9rZWN5cmlsbGljPTEyMDA7ZS5VdGlsZGU9MzYwO2UuVXRpbGRlYWN1dGU9NzgwMDtlLlV0aWxkZWJlbG93PTc3OTY7ZS5WPTg2O2UuVmNpcmNsZT05NDE5O2UuVmRvdGJlbG93PTc4MDY7ZS5WZWN5cmlsbGljPTEwNDI7ZS5WZXdhcm1lbmlhbj0xMzU4O2UuVmhvb2s9NDM0O2UuVm1vbm9zcGFjZT02NTMzNDtlLlZvYXJtZW5pYW49MTM1MjtlLlZzbWFsbD02MzM1MDtlLlZ0aWxkZT03ODA0O2UuVz04NztlLldhY3V0ZT03ODEwO2UuV2NpcmNsZT05NDIwO2UuV2NpcmN1bWZsZXg9MzcyO2UuV2RpZXJlc2lzPTc4MTI7ZS5XZG90YWNjZW50PTc4MTQ7ZS5XZG90YmVsb3c9NzgxNjtlLldncmF2ZT03ODA4O2UuV21vbm9zcGFjZT02NTMzNTtlLldzbWFsbD02MzM1MTtlLlg9ODg7ZS5YY2lyY2xlPTk0MjE7ZS5YZGllcmVzaXM9NzgyMDtlLlhkb3RhY2NlbnQ9NzgxODtlLlhlaGFybWVuaWFuPTEzNDE7ZS5YaT05MjY7ZS5YbW9ub3NwYWNlPTY1MzM2O2UuWHNtYWxsPTYzMzUyO2UuWT04OTtlLllhY3V0ZT0yMjE7ZS5ZYWN1dGVzbWFsbD02MzQ4NTtlLllhdGN5cmlsbGljPTExMjI7ZS5ZY2lyY2xlPTk0MjI7ZS5ZY2lyY3VtZmxleD0zNzQ7ZS5ZZGllcmVzaXM9Mzc2O2UuWWRpZXJlc2lzc21hbGw9NjM0ODc7ZS5ZZG90YWNjZW50PTc4MjI7ZS5ZZG90YmVsb3c9NzkyNDtlLlllcmljeXJpbGxpYz0xMDY3O2UuWWVydWRpZXJlc2lzY3lyaWxsaWM9MTI3MjtlLllncmF2ZT03OTIyO2UuWWhvb2s9NDM1O2UuWWhvb2thYm92ZT03OTI2O2UuWWlhcm1lbmlhbj0xMzQ5O2UuWWljeXJpbGxpYz0xMDMxO2UuWWl3bmFybWVuaWFuPTEzNjI7ZS5ZbW9ub3NwYWNlPTY1MzM3O2UuWXNtYWxsPTYzMzUzO2UuWXRpbGRlPTc5Mjg7ZS5ZdXNiaWdjeXJpbGxpYz0xMTMwO2UuWXVzYmlnaW90aWZpZWRjeXJpbGxpYz0xMTMyO2UuWXVzbGl0dGxlY3lyaWxsaWM9MTEyNjtlLll1c2xpdHRsZWlvdGlmaWVkY3lyaWxsaWM9MTEyODtlLlo9OTA7ZS5aYWFybWVuaWFuPTEzMzQ7ZS5aYWN1dGU9Mzc3O2UuWmNhcm9uPTM4MTtlLlpjYXJvbnNtYWxsPTYzMjMxO2UuWmNpcmNsZT05NDIzO2UuWmNpcmN1bWZsZXg9NzgyNDtlLlpkb3Q9Mzc5O2UuWmRvdGFjY2VudD0zNzk7ZS5aZG90YmVsb3c9NzgyNjtlLlplY3lyaWxsaWM9MTA0NztlLlplZGVzY2VuZGVyY3lyaWxsaWM9MTE3NjtlLlplZGllcmVzaXNjeXJpbGxpYz0xMjQ2O2UuWmV0YT05MTg7ZS5aaGVhcm1lbmlhbj0xMzM4O2UuWmhlYnJldmVjeXJpbGxpYz0xMjE3O2UuWmhlY3lyaWxsaWM9MTA0NjtlLlpoZWRlc2NlbmRlcmN5cmlsbGljPTExNzQ7ZS5aaGVkaWVyZXNpc2N5cmlsbGljPTEyNDQ7ZS5abGluZWJlbG93PTc4Mjg7ZS5abW9ub3NwYWNlPTY1MzM4O2UuWnNtYWxsPTYzMzU0O2UuWnN0cm9rZT00Mzc7ZS5hPTk3O2UuYWFiZW5nYWxpPTI0Mzg7ZS5hYWN1dGU9MjI1O2UuYWFkZXZhPTIzMTA7ZS5hYWd1amFyYXRpPTI2OTQ7ZS5hYWd1cm11a2hpPTI1NjY7ZS5hYW1hdHJhZ3VybXVraGk9MjYyMjtlLmFhcnVzcXVhcmU9MTMwNTk7ZS5hYXZvd2Vsc2lnbmJlbmdhbGk9MjQ5NDtlLmFhdm93ZWxzaWduZGV2YT0yMzY2O2UuYWF2b3dlbHNpZ25ndWphcmF0aT0yNzUwO2UuYWJicmV2aWF0aW9ubWFya2FybWVuaWFuPTEzNzU7ZS5hYmJyZXZpYXRpb25zaWduZGV2YT0yNDE2O2UuYWJlbmdhbGk9MjQzNztlLmFib3BvbW9mbz0xMjU3MDtlLmFicmV2ZT0yNTk7ZS5hYnJldmVhY3V0ZT03ODU1O2UuYWJyZXZlY3lyaWxsaWM9MTIzMztlLmFicmV2ZWRvdGJlbG93PTc4NjM7ZS5hYnJldmVncmF2ZT03ODU3O2UuYWJyZXZlaG9va2Fib3ZlPTc4NTk7ZS5hYnJldmV0aWxkZT03ODYxO2UuYWNhcm9uPTQ2MjtlLmFjaXJjbGU9OTQyNDtlLmFjaXJjdW1mbGV4PTIyNjtlLmFjaXJjdW1mbGV4YWN1dGU9Nzg0NTtlLmFjaXJjdW1mbGV4ZG90YmVsb3c9Nzg1MztlLmFjaXJjdW1mbGV4Z3JhdmU9Nzg0NztlLmFjaXJjdW1mbGV4aG9va2Fib3ZlPTc4NDk7ZS5hY2lyY3VtZmxleHRpbGRlPTc4NTE7ZS5hY3V0ZT0xODA7ZS5hY3V0ZWJlbG93Y21iPTc5MTtlLmFjdXRlY21iPTc2OTtlLmFjdXRlY29tYj03Njk7ZS5hY3V0ZWRldmE9MjM4ODtlLmFjdXRlbG93bW9kPTcxOTtlLmFjdXRldG9uZWNtYj04MzM7ZS5hY3lyaWxsaWM9MTA3MjtlLmFkYmxncmF2ZT01MTM7ZS5hZGRha2d1cm11a2hpPTI2NzM7ZS5hZGV2YT0yMzA5O2UuYWRpZXJlc2lzPTIyODtlLmFkaWVyZXNpc2N5cmlsbGljPTEyMzU7ZS5hZGllcmVzaXNtYWNyb249NDc5O2UuYWRvdGJlbG93PTc4NDE7ZS5hZG90bWFjcm9uPTQ4MTtlLmFlPTIzMDtlLmFlYWN1dGU9NTA5O2UuYWVrb3JlYW49MTI2MjQ7ZS5hZW1hY3Jvbj00ODM7ZS5hZmlpMDAyMDg9ODIxMztlLmFmaWkwODk0MT04MzU2O2UuYWZpaTEwMDE3PTEwNDA7ZS5hZmlpMTAwMTg9MTA0MTtlLmFmaWkxMDAxOT0xMDQyO2UuYWZpaTEwMDIwPTEwNDM7ZS5hZmlpMTAwMjE9MTA0NDtlLmFmaWkxMDAyMj0xMDQ1O2UuYWZpaTEwMDIzPTEwMjU7ZS5hZmlpMTAwMjQ9MTA0NjtlLmFmaWkxMDAyNT0xMDQ3O2UuYWZpaTEwMDI2PTEwNDg7ZS5hZmlpMTAwMjc9MTA0OTtlLmFmaWkxMDAyOD0xMDUwO2UuYWZpaTEwMDI5PTEwNTE7ZS5hZmlpMTAwMzA9MTA1MjtlLmFmaWkxMDAzMT0xMDUzO2UuYWZpaTEwMDMyPTEwNTQ7ZS5hZmlpMTAwMzM9MTA1NTtlLmFmaWkxMDAzND0xMDU2O2UuYWZpaTEwMDM1PTEwNTc7ZS5hZmlpMTAwMzY9MTA1ODtlLmFmaWkxMDAzNz0xMDU5O2UuYWZpaTEwMDM4PTEwNjA7ZS5hZmlpMTAwMzk9MTA2MTtlLmFmaWkxMDA0MD0xMDYyO2UuYWZpaTEwMDQxPTEwNjM7ZS5hZmlpMTAwNDI9MTA2NDtlLmFmaWkxMDA0Mz0xMDY1O2UuYWZpaTEwMDQ0PTEwNjY7ZS5hZmlpMTAwNDU9MTA2NztlLmFmaWkxMDA0Nj0xMDY4O2UuYWZpaTEwMDQ3PTEwNjk7ZS5hZmlpMTAwNDg9MTA3MDtlLmFmaWkxMDA0OT0xMDcxO2UuYWZpaTEwMDUwPTExNjg7ZS5hZmlpMTAwNTE9MTAyNjtlLmFmaWkxMDA1Mj0xMDI3O2UuYWZpaTEwMDUzPTEwMjg7ZS5hZmlpMTAwNTQ9MTAyOTtlLmFmaWkxMDA1NT0xMDMwO2UuYWZpaTEwMDU2PTEwMzE7ZS5hZmlpMTAwNTc9MTAzMjtlLmFmaWkxMDA1OD0xMDMzO2UuYWZpaTEwMDU5PTEwMzQ7ZS5hZmlpMTAwNjA9MTAzNTtlLmFmaWkxMDA2MT0xMDM2O2UuYWZpaTEwMDYyPTEwMzg7ZS5hZmlpMTAwNjM9NjMxNzI7ZS5hZmlpMTAwNjQ9NjMxNzM7ZS5hZmlpMTAwNjU9MTA3MjtlLmFmaWkxMDA2Nj0xMDczO2UuYWZpaTEwMDY3PTEwNzQ7ZS5hZmlpMTAwNjg9MTA3NTtlLmFmaWkxMDA2OT0xMDc2O2UuYWZpaTEwMDcwPTEwNzc7ZS5hZmlpMTAwNzE9MTEwNTtlLmFmaWkxMDA3Mj0xMDc4O2UuYWZpaTEwMDczPTEwNzk7ZS5hZmlpMTAwNzQ9MTA4MDtlLmFmaWkxMDA3NT0xMDgxO2UuYWZpaTEwMDc2PTEwODI7ZS5hZmlpMTAwNzc9MTA4MztlLmFmaWkxMDA3OD0xMDg0O2UuYWZpaTEwMDc5PTEwODU7ZS5hZmlpMTAwODA9MTA4NjtlLmFmaWkxMDA4MT0xMDg3O2UuYWZpaTEwMDgyPTEwODg7ZS5hZmlpMTAwODM9MTA4OTtlLmFmaWkxMDA4ND0xMDkwO2UuYWZpaTEwMDg1PTEwOTE7ZS5hZmlpMTAwODY9MTA5MjtlLmFmaWkxMDA4Nz0xMDkzO2UuYWZpaTEwMDg4PTEwOTQ7ZS5hZmlpMTAwODk9MTA5NTtlLmFmaWkxMDA5MD0xMDk2O2UuYWZpaTEwMDkxPTEwOTc7ZS5hZmlpMTAwOTI9MTA5ODtlLmFmaWkxMDA5Mz0xMDk5O2UuYWZpaTEwMDk0PTExMDA7ZS5hZmlpMTAwOTU9MTEwMTtlLmFmaWkxMDA5Nj0xMTAyO2UuYWZpaTEwMDk3PTExMDM7ZS5hZmlpMTAwOTg9MTE2OTtlLmFmaWkxMDA5OT0xMTA2O2UuYWZpaTEwMTAwPTExMDc7ZS5hZmlpMTAxMDE9MTEwODtlLmFmaWkxMDEwMj0xMTA5O2UuYWZpaTEwMTAzPTExMTA7ZS5hZmlpMTAxMDQ9MTExMTtlLmFmaWkxMDEwNT0xMTEyO2UuYWZpaTEwMTA2PTExMTM7ZS5hZmlpMTAxMDc9MTExNDtlLmFmaWkxMDEwOD0xMTE1O2UuYWZpaTEwMTA5PTExMTY7ZS5hZmlpMTAxMTA9MTExODtlLmFmaWkxMDE0NT0xMDM5O2UuYWZpaTEwMTQ2PTExMjI7ZS5hZmlpMTAxNDc9MTEzODtlLmFmaWkxMDE0OD0xMTQwO2UuYWZpaTEwMTkyPTYzMTc0O2UuYWZpaTEwMTkzPTExMTk7ZS5hZmlpMTAxOTQ9MTEyMztlLmFmaWkxMDE5NT0xMTM5O2UuYWZpaTEwMTk2PTExNDE7ZS5hZmlpMTA4MzE9NjMxNzU7ZS5hZmlpMTA4MzI9NjMxNzY7ZS5hZmlpMTA4NDY9MTI0MTtlLmFmaWkyOTk9ODIwNjtlLmFmaWkzMDA9ODIwNztlLmFmaWkzMDE9ODIwNTtlLmFmaWk1NzM4MT0xNjQyO2UuYWZpaTU3Mzg4PTE1NDg7ZS5hZmlpNTczOTI9MTYzMjtlLmFmaWk1NzM5Mz0xNjMzO2UuYWZpaTU3Mzk0PTE2MzQ7ZS5hZmlpNTczOTU9MTYzNTtlLmFmaWk1NzM5Nj0xNjM2O2UuYWZpaTU3Mzk3PTE2Mzc7ZS5hZmlpNTczOTg9MTYzODtlLmFmaWk1NzM5OT0xNjM5O2UuYWZpaTU3NDAwPTE2NDA7ZS5hZmlpNTc0MDE9MTY0MTtlLmFmaWk1NzQwMz0xNTYzO2UuYWZpaTU3NDA3PTE1Njc7ZS5hZmlpNTc0MDk9MTU2OTtlLmFmaWk1NzQxMD0xNTcwO2UuYWZpaTU3NDExPTE1NzE7ZS5hZmlpNTc0MTI9MTU3MjtlLmFmaWk1NzQxMz0xNTczO2UuYWZpaTU3NDE0PTE1NzQ7ZS5hZmlpNTc0MTU9MTU3NTtlLmFmaWk1NzQxNj0xNTc2O2UuYWZpaTU3NDE3PTE1Nzc7ZS5hZmlpNTc0MTg9MTU3ODtlLmFmaWk1NzQxOT0xNTc5O2UuYWZpaTU3NDIwPTE1ODA7ZS5hZmlpNTc0MjE9MTU4MTtlLmFmaWk1NzQyMj0xNTgyO2UuYWZpaTU3NDIzPTE1ODM7ZS5hZmlpNTc0MjQ9MTU4NDtlLmFmaWk1NzQyNT0xNTg1O2UuYWZpaTU3NDI2PTE1ODY7ZS5hZmlpNTc0Mjc9MTU4NztlLmFmaWk1NzQyOD0xNTg4O2UuYWZpaTU3NDI5PTE1ODk7ZS5hZmlpNTc0MzA9MTU5MDtlLmFmaWk1NzQzMT0xNTkxO2UuYWZpaTU3NDMyPTE1OTI7ZS5hZmlpNTc0MzM9MTU5MztlLmFmaWk1NzQzND0xNTk0O2UuYWZpaTU3NDQwPTE2MDA7ZS5hZmlpNTc0NDE9MTYwMTtlLmFmaWk1NzQ0Mj0xNjAyO2UuYWZpaTU3NDQzPTE2MDM7ZS5hZmlpNTc0NDQ9MTYwNDtlLmFmaWk1NzQ0NT0xNjA1O2UuYWZpaTU3NDQ2PTE2MDY7ZS5hZmlpNTc0NDg9MTYwODtlLmFmaWk1NzQ0OT0xNjA5O2UuYWZpaTU3NDUwPTE2MTA7ZS5hZmlpNTc0NTE9MTYxMTtlLmFmaWk1NzQ1Mj0xNjEyO2UuYWZpaTU3NDUzPTE2MTM7ZS5hZmlpNTc0NTQ9MTYxNDtlLmFmaWk1NzQ1NT0xNjE1O2UuYWZpaTU3NDU2PTE2MTY7ZS5hZmlpNTc0NTc9MTYxNztlLmFmaWk1NzQ1OD0xNjE4O2UuYWZpaTU3NDcwPTE2MDc7ZS5hZmlpNTc1MDU9MTcwMDtlLmFmaWk1NzUwNj0xNjYyO2UuYWZpaTU3NTA3PTE2NzA7ZS5hZmlpNTc1MDg9MTY4ODtlLmFmaWk1NzUwOT0xNzExO2UuYWZpaTU3NTExPTE2NTc7ZS5hZmlpNTc1MTI9MTY3MjtlLmFmaWk1NzUxMz0xNjgxO2UuYWZpaTU3NTE0PTE3MjI7ZS5hZmlpNTc1MTk9MTc0NjtlLmFmaWk1NzUzND0xNzQ5O2UuYWZpaTU3NjM2PTgzNjI7ZS5hZmlpNTc2NDU9MTQ3MDtlLmFmaWk1NzY1OD0xNDc1O2UuYWZpaTU3NjY0PTE0ODg7ZS5hZmlpNTc2NjU9MTQ4OTtlLmFmaWk1NzY2Nj0xNDkwO2UuYWZpaTU3NjY3PTE0OTE7ZS5hZmlpNTc2Njg9MTQ5MjtlLmFmaWk1NzY2OT0xNDkzO2UuYWZpaTU3NjcwPTE0OTQ7ZS5hZmlpNTc2NzE9MTQ5NTtlLmFmaWk1NzY3Mj0xNDk2O2UuYWZpaTU3NjczPTE0OTc7ZS5hZmlpNTc2NzQ9MTQ5ODtlLmFmaWk1NzY3NT0xNDk5O2UuYWZpaTU3Njc2PTE1MDA7ZS5hZmlpNTc2Nzc9MTUwMTtlLmFmaWk1NzY3OD0xNTAyO2UuYWZpaTU3Njc5PTE1MDM7ZS5hZmlpNTc2ODA9MTUwNDtlLmFmaWk1NzY4MT0xNTA1O2UuYWZpaTU3NjgyPTE1MDY7ZS5hZmlpNTc2ODM9MTUwNztlLmFmaWk1NzY4ND0xNTA4O2UuYWZpaTU3Njg1PTE1MDk7ZS5hZmlpNTc2ODY9MTUxMDtlLmFmaWk1NzY4Nz0xNTExO2UuYWZpaTU3Njg4PTE1MTI7ZS5hZmlpNTc2ODk9MTUxMztlLmFmaWk1NzY5MD0xNTE0O2UuYWZpaTU3Njk0PTY0Mjk4O2UuYWZpaTU3Njk1PTY0Mjk5O2UuYWZpaTU3NzAwPTY0MzMxO2UuYWZpaTU3NzA1PTY0Mjg3O2UuYWZpaTU3NzE2PTE1MjA7ZS5hZmlpNTc3MTc9MTUyMTtlLmFmaWk1NzcxOD0xNTIyO2UuYWZpaTU3NzIzPTY0MzA5O2UuYWZpaTU3NzkzPTE0NjA7ZS5hZmlpNTc3OTQ9MTQ2MTtlLmFmaWk1Nzc5NT0xNDYyO2UuYWZpaTU3Nzk2PTE0Njc7ZS5hZmlpNTc3OTc9MTQ2NDtlLmFmaWk1Nzc5OD0xNDYzO2UuYWZpaTU3Nzk5PTE0NTY7ZS5hZmlpNTc4MDA9MTQ1ODtlLmFmaWk1NzgwMT0xNDU3O2UuYWZpaTU3ODAyPTE0NTk7ZS5hZmlpNTc4MDM9MTQ3NDtlLmFmaWk1NzgwND0xNDczO2UuYWZpaTU3ODA2PTE0NjU7ZS5hZmlpNTc4MDc9MTQ2ODtlLmFmaWk1NzgzOT0xNDY5O2UuYWZpaTU3ODQxPTE0NzE7ZS5hZmlpNTc4NDI9MTQ3MjtlLmFmaWk1NzkyOT03MDA7ZS5hZmlpNjEyNDg9ODQ1MztlLmFmaWk2MTI4OT04NDY3O2UuYWZpaTYxMzUyPTg0NzA7ZS5hZmlpNjE1NzM9ODIzNjtlLmFmaWk2MTU3ND04MjM3O2UuYWZpaTYxNTc1PTgyMzg7ZS5hZmlpNjE2NjQ9ODIwNDtlLmFmaWk2MzE2Nz0xNjQ1O2UuYWZpaTY0OTM3PTcwMTtlLmFncmF2ZT0yMjQ7ZS5hZ3VqYXJhdGk9MjY5MztlLmFndXJtdWtoaT0yNTY1O2UuYWhpcmFnYW5hPTEyMzU0O2UuYWhvb2thYm92ZT03ODQzO2UuYWliZW5nYWxpPTI0NDg7ZS5haWJvcG9tb2ZvPTEyNTc0O2UuYWlkZXZhPTIzMjA7ZS5haWVjeXJpbGxpYz0xMjM3O2UuYWlndWphcmF0aT0yNzA0O2UuYWlndXJtdWtoaT0yNTc2O2UuYWltYXRyYWd1cm11a2hpPTI2MzI7ZS5haW5hcmFiaWM9MTU5MztlLmFpbmZpbmFsYXJhYmljPTY1MjI2O2UuYWluaW5pdGlhbGFyYWJpYz02NTIyNztlLmFpbm1lZGlhbGFyYWJpYz02NTIyODtlLmFpbnZlcnRlZGJyZXZlPTUxNTtlLmFpdm93ZWxzaWduYmVuZ2FsaT0yNTA0O2UuYWl2b3dlbHNpZ25kZXZhPTIzNzY7ZS5haXZvd2Vsc2lnbmd1amFyYXRpPTI3NjA7ZS5ha2F0YWthbmE9MTI0NTA7ZS5ha2F0YWthbmFoYWxmd2lkdGg9NjUzOTM7ZS5ha29yZWFuPTEyNjIzO2UuYWxlZj0xNDg4O2UuYWxlZmFyYWJpYz0xNTc1O2UuYWxlZmRhZ2VzaGhlYnJldz02NDMwNDtlLmFsZWZmaW5hbGFyYWJpYz02NTE2NjtlLmFsZWZoYW16YWFib3ZlYXJhYmljPTE1NzE7ZS5hbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljPTY1MTU2O2UuYWxlZmhhbXphYmVsb3dhcmFiaWM9MTU3MztlLmFsZWZoYW16YWJlbG93ZmluYWxhcmFiaWM9NjUxNjA7ZS5hbGVmaGVicmV3PTE0ODg7ZS5hbGVmbGFtZWRoZWJyZXc9NjQzMzU7ZS5hbGVmbWFkZGFhYm92ZWFyYWJpYz0xNTcwO2UuYWxlZm1hZGRhYWJvdmVmaW5hbGFyYWJpYz02NTE1NDtlLmFsZWZtYWtzdXJhYXJhYmljPTE2MDk7ZS5hbGVmbWFrc3VyYWZpbmFsYXJhYmljPTY1MjY0O2UuYWxlZm1ha3N1cmFpbml0aWFsYXJhYmljPTY1MjY3O2UuYWxlZm1ha3N1cmFtZWRpYWxhcmFiaWM9NjUyNjg7ZS5hbGVmcGF0YWhoZWJyZXc9NjQzMDI7ZS5hbGVmcWFtYXRzaGVicmV3PTY0MzAzO2UuYWxlcGg9ODUwMTtlLmFsbGVxdWFsPTg3ODA7ZS5hbHBoYT05NDU7ZS5hbHBoYXRvbm9zPTk0MDtlLmFtYWNyb249MjU3O2UuYW1vbm9zcGFjZT02NTM0NTtlLmFtcGVyc2FuZD0zODtlLmFtcGVyc2FuZG1vbm9zcGFjZT02NTI4NjtlLmFtcGVyc2FuZHNtYWxsPTYzMjcwO2UuYW1zcXVhcmU9MTMyNTA7ZS5hbmJvcG9tb2ZvPTEyNTc4O2UuYW5nYm9wb21vZm89MTI1ODA7ZS5hbmdicmFja2V0bGVmdD0xMjI5NjtlLmFuZ2JyYWNrZXRyaWdodD0xMjI5NztlLmFuZ2toYW5raHV0aGFpPTM2NzQ7ZS5hbmdsZT04NzM2O2UuYW5nbGVicmFja2V0bGVmdD0xMjI5NjtlLmFuZ2xlYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA4NztlLmFuZ2xlYnJhY2tldHJpZ2h0PTEyMjk3O2UuYW5nbGVicmFja2V0cmlnaHR2ZXJ0aWNhbD02NTA4ODtlLmFuZ2xlbGVmdD05MDAxO2UuYW5nbGVyaWdodD05MDAyO2UuYW5nc3Ryb209ODQ5MTtlLmFub3RlbGVpYT05MDM7ZS5hbnVkYXR0YWRldmE9MjM4NjtlLmFudXN2YXJhYmVuZ2FsaT0yNDM0O2UuYW51c3ZhcmFkZXZhPTIzMDY7ZS5hbnVzdmFyYWd1amFyYXRpPTI2OTA7ZS5hb2dvbmVrPTI2MTtlLmFwYWF0b3NxdWFyZT0xMzA1NjtlLmFwYXJlbj05MzcyO2UuYXBvc3Ryb3BoZWFybWVuaWFuPTEzNzA7ZS5hcG9zdHJvcGhlbW9kPTcwMDtlLmFwcGxlPTYzNzQzO2UuYXBwcm9hY2hlcz04Nzg0O2UuYXBwcm94ZXF1YWw9ODc3NjtlLmFwcHJveGVxdWFsb3JpbWFnZT04Nzg2O2UuYXBwcm94aW1hdGVseWVxdWFsPTg3NzM7ZS5hcmFlYWVrb3JlYW49MTI2ODY7ZS5hcmFlYWtvcmVhbj0xMjY4NTtlLmFyYz04OTc4O2UuYXJpZ2h0aGFsZnJpbmc9NzgzNDtlLmFyaW5nPTIyOTtlLmFyaW5nYWN1dGU9NTA3O2UuYXJpbmdiZWxvdz03NjgxO2UuYXJyb3dib3RoPTg1OTY7ZS5hcnJvd2Rhc2hkb3duPTg2NzU7ZS5hcnJvd2Rhc2hsZWZ0PTg2NzI7ZS5hcnJvd2Rhc2hyaWdodD04Njc0O2UuYXJyb3dkYXNodXA9ODY3MztlLmFycm93ZGJsYm90aD04NjYwO2UuYXJyb3dkYmxkb3duPTg2NTk7ZS5hcnJvd2RibGxlZnQ9ODY1NjtlLmFycm93ZGJscmlnaHQ9ODY1ODtlLmFycm93ZGJsdXA9ODY1NztlLmFycm93ZG93bj04NTk1O2UuYXJyb3dkb3dubGVmdD04NjAxO2UuYXJyb3dkb3ducmlnaHQ9ODYwMDtlLmFycm93ZG93bndoaXRlPTg2ODE7ZS5hcnJvd2hlYWRkb3dubW9kPTcwOTtlLmFycm93aGVhZGxlZnRtb2Q9NzA2O2UuYXJyb3doZWFkcmlnaHRtb2Q9NzA3O2UuYXJyb3doZWFkdXBtb2Q9NzA4O2UuYXJyb3dob3JpemV4PTYzNzE5O2UuYXJyb3dsZWZ0PTg1OTI7ZS5hcnJvd2xlZnRkYmw9ODY1NjtlLmFycm93bGVmdGRibHN0cm9rZT04NjUzO2UuYXJyb3dsZWZ0b3ZlcnJpZ2h0PTg2NDY7ZS5hcnJvd2xlZnR3aGl0ZT04Njc4O2UuYXJyb3dyaWdodD04NTk0O2UuYXJyb3dyaWdodGRibHN0cm9rZT04NjU1O2UuYXJyb3dyaWdodGhlYXZ5PTEwMTQyO2UuYXJyb3dyaWdodG92ZXJsZWZ0PTg2NDQ7ZS5hcnJvd3JpZ2h0d2hpdGU9ODY4MDtlLmFycm93dGFibGVmdD04Njc2O2UuYXJyb3d0YWJyaWdodD04Njc3O2UuYXJyb3d1cD04NTkzO2UuYXJyb3d1cGRuPTg1OTc7ZS5hcnJvd3VwZG5ic2U9ODYxNjtlLmFycm93dXBkb3duYmFzZT04NjE2O2UuYXJyb3d1cGxlZnQ9ODU5ODtlLmFycm93dXBsZWZ0b2Zkb3duPTg2NDU7ZS5hcnJvd3VwcmlnaHQ9ODU5OTtlLmFycm93dXB3aGl0ZT04Njc5O2UuYXJyb3d2ZXJ0ZXg9NjM3MTg7ZS5hc2NpaWNpcmN1bT05NDtlLmFzY2lpY2lyY3VtbW9ub3NwYWNlPTY1MzQyO2UuYXNjaWl0aWxkZT0xMjY7ZS5hc2NpaXRpbGRlbW9ub3NwYWNlPTY1Mzc0O2UuYXNjcmlwdD01OTM7ZS5hc2NyaXB0dHVybmVkPTU5NDtlLmFzbWFsbGhpcmFnYW5hPTEyMzUzO2UuYXNtYWxsa2F0YWthbmE9MTI0NDk7ZS5hc21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM4MztlLmFzdGVyaXNrPTQyO2UuYXN0ZXJpc2thbHRvbmVhcmFiaWM9MTY0NTtlLmFzdGVyaXNrYXJhYmljPTE2NDU7ZS5hc3Rlcmlza21hdGg9ODcyNztlLmFzdGVyaXNrbW9ub3NwYWNlPTY1MjkwO2UuYXN0ZXJpc2tzbWFsbD02NTEyMTtlLmFzdGVyaXNtPTgyNTg7ZS5hc3VwZXJpb3I9NjMyMDk7ZS5hc3ltcHRvdGljYWxseWVxdWFsPTg3NzE7ZS5hdD02NDtlLmF0aWxkZT0yMjc7ZS5hdG1vbm9zcGFjZT02NTMxMjtlLmF0c21hbGw9NjUxMzE7ZS5hdHVybmVkPTU5MjtlLmF1YmVuZ2FsaT0yNDUyO2UuYXVib3BvbW9mbz0xMjU3NjtlLmF1ZGV2YT0yMzI0O2UuYXVndWphcmF0aT0yNzA4O2UuYXVndXJtdWtoaT0yNTgwO2UuYXVsZW5ndGhtYXJrYmVuZ2FsaT0yNTE5O2UuYXVtYXRyYWd1cm11a2hpPTI2MzY7ZS5hdXZvd2Vsc2lnbmJlbmdhbGk9MjUwODtlLmF1dm93ZWxzaWduZGV2YT0yMzgwO2UuYXV2b3dlbHNpZ25ndWphcmF0aT0yNzY0O2UuYXZhZ3JhaGFkZXZhPTIzNjU7ZS5heWJhcm1lbmlhbj0xMzc3O2UuYXlpbj0xNTA2O2UuYXlpbmFsdG9uZWhlYnJldz02NDI4ODtlLmF5aW5oZWJyZXc9MTUwNjtlLmI9OTg7ZS5iYWJlbmdhbGk9MjQ3NjtlLmJhY2tzbGFzaD05MjtlLmJhY2tzbGFzaG1vbm9zcGFjZT02NTM0MDtlLmJhZGV2YT0yMzQ4O2UuYmFndWphcmF0aT0yNzMyO2UuYmFndXJtdWtoaT0yNjA0O2UuYmFoaXJhZ2FuYT0xMjQwMDtlLmJhaHR0aGFpPTM2NDc7ZS5iYWthdGFrYW5hPTEyNDk2O2UuYmFyPTEyNDtlLmJhcm1vbm9zcGFjZT02NTM3MjtlLmJib3BvbW9mbz0xMjU0OTtlLmJjaXJjbGU9OTQyNTtlLmJkb3RhY2NlbnQ9NzY4MztlLmJkb3RiZWxvdz03Njg1O2UuYmVhbWVkc2l4dGVlbnRobm90ZXM9OTgzNjtlLmJlY2F1c2U9ODc1NztlLmJlY3lyaWxsaWM9MTA3MztlLmJlaGFyYWJpYz0xNTc2O2UuYmVoZmluYWxhcmFiaWM9NjUxNjg7ZS5iZWhpbml0aWFsYXJhYmljPTY1MTY5O2UuYmVoaXJhZ2FuYT0xMjQwOTtlLmJlaG1lZGlhbGFyYWJpYz02NTE3MDtlLmJlaG1lZW1pbml0aWFsYXJhYmljPTY0NjcxO2UuYmVobWVlbWlzb2xhdGVkYXJhYmljPTY0NTIwO2UuYmVobm9vbmZpbmFsYXJhYmljPTY0NjIxO2UuYmVrYXRha2FuYT0xMjUwNTtlLmJlbmFybWVuaWFuPTEzNzg7ZS5iZXQ9MTQ4OTtlLmJldGE9OTQ2O2UuYmV0YXN5bWJvbGdyZWVrPTk3NjtlLmJldGRhZ2VzaD02NDMwNTtlLmJldGRhZ2VzaGhlYnJldz02NDMwNTtlLmJldGhlYnJldz0xNDg5O2UuYmV0cmFmZWhlYnJldz02NDMzMjtlLmJoYWJlbmdhbGk9MjQ3NztlLmJoYWRldmE9MjM0OTtlLmJoYWd1amFyYXRpPTI3MzM7ZS5iaGFndXJtdWtoaT0yNjA1O2UuYmhvb2s9NTk1O2UuYmloaXJhZ2FuYT0xMjQwMztlLmJpa2F0YWthbmE9MTI0OTk7ZS5iaWxhYmlhbGNsaWNrPTY2NDtlLmJpbmRpZ3VybXVraGk9MjU2MjtlLmJpcnVzcXVhcmU9MTMxMDU7ZS5ibGFja2NpcmNsZT05Njc5O2UuYmxhY2tkaWFtb25kPTk2NzA7ZS5ibGFja2Rvd25wb2ludGluZ3RyaWFuZ2xlPTk2NjA7ZS5ibGFja2xlZnRwb2ludGluZ3BvaW50ZXI9OTY2ODtlLmJsYWNrbGVmdHBvaW50aW5ndHJpYW5nbGU9OTY2NDtlLmJsYWNrbGVudGljdWxhcmJyYWNrZXRsZWZ0PTEyMzA0O2UuYmxhY2tsZW50aWN1bGFyYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA4MztlLmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodD0xMjMwNTtlLmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodHZlcnRpY2FsPTY1MDg0O2UuYmxhY2tsb3dlcmxlZnR0cmlhbmdsZT05Njk5O2UuYmxhY2tsb3dlcnJpZ2h0dHJpYW5nbGU9OTY5ODtlLmJsYWNrcmVjdGFuZ2xlPTk2NDQ7ZS5ibGFja3JpZ2h0cG9pbnRpbmdwb2ludGVyPTk2NTg7ZS5ibGFja3JpZ2h0cG9pbnRpbmd0cmlhbmdsZT05NjU0O2UuYmxhY2tzbWFsbHNxdWFyZT05NjQyO2UuYmxhY2tzbWlsaW5nZmFjZT05Nzg3O2UuYmxhY2tzcXVhcmU9OTYzMjtlLmJsYWNrc3Rhcj05NzMzO2UuYmxhY2t1cHBlcmxlZnR0cmlhbmdsZT05NzAwO2UuYmxhY2t1cHBlcnJpZ2h0dHJpYW5nbGU9OTcwMTtlLmJsYWNrdXBwb2ludGluZ3NtYWxsdHJpYW5nbGU9OTY1MjtlLmJsYWNrdXBwb2ludGluZ3RyaWFuZ2xlPTk2NTA7ZS5ibGFuaz05MjUxO2UuYmxpbmViZWxvdz03Njg3O2UuYmxvY2s9OTYwODtlLmJtb25vc3BhY2U9NjUzNDY7ZS5ib2JhaW1haXRoYWk9MzYxMDtlLmJvaGlyYWdhbmE9MTI0MTI7ZS5ib2thdGFrYW5hPTEyNTA4O2UuYnBhcmVuPTkzNzM7ZS5icXNxdWFyZT0xMzI1MTtlLmJyYWNlZXg9NjM3MzI7ZS5icmFjZWxlZnQ9MTIzO2UuYnJhY2VsZWZ0YnQ9NjM3MzE7ZS5icmFjZWxlZnRtaWQ9NjM3MzA7ZS5icmFjZWxlZnRtb25vc3BhY2U9NjUzNzE7ZS5icmFjZWxlZnRzbWFsbD02NTExNTtlLmJyYWNlbGVmdHRwPTYzNzI5O2UuYnJhY2VsZWZ0dmVydGljYWw9NjUwNzk7ZS5icmFjZXJpZ2h0PTEyNTtlLmJyYWNlcmlnaHRidD02Mzc0MjtlLmJyYWNlcmlnaHRtaWQ9NjM3NDE7ZS5icmFjZXJpZ2h0bW9ub3NwYWNlPTY1MzczO2UuYnJhY2VyaWdodHNtYWxsPTY1MTE2O2UuYnJhY2VyaWdodHRwPTYzNzQwO2UuYnJhY2VyaWdodHZlcnRpY2FsPTY1MDgwO2UuYnJhY2tldGxlZnQ9OTE7ZS5icmFja2V0bGVmdGJ0PTYzNzI4O2UuYnJhY2tldGxlZnRleD02MzcyNztlLmJyYWNrZXRsZWZ0bW9ub3NwYWNlPTY1MzM5O2UuYnJhY2tldGxlZnR0cD02MzcyNjtlLmJyYWNrZXRyaWdodD05MztlLmJyYWNrZXRyaWdodGJ0PTYzNzM5O2UuYnJhY2tldHJpZ2h0ZXg9NjM3Mzg7ZS5icmFja2V0cmlnaHRtb25vc3BhY2U9NjUzNDE7ZS5icmFja2V0cmlnaHR0cD02MzczNztlLmJyZXZlPTcyODtlLmJyZXZlYmVsb3djbWI9ODE0O2UuYnJldmVjbWI9Nzc0O2UuYnJldmVpbnZlcnRlZGJlbG93Y21iPTgxNTtlLmJyZXZlaW52ZXJ0ZWRjbWI9Nzg1O2UuYnJldmVpbnZlcnRlZGRvdWJsZWNtYj04NjU7ZS5icmlkZ2ViZWxvd2NtYj04MTA7ZS5icmlkZ2VpbnZlcnRlZGJlbG93Y21iPTgyNjtlLmJyb2tlbmJhcj0xNjY7ZS5ic3Ryb2tlPTM4NDtlLmJzdXBlcmlvcj02MzIxMDtlLmJ0b3BiYXI9Mzg3O2UuYnVoaXJhZ2FuYT0xMjQwNjtlLmJ1a2F0YWthbmE9MTI1MDI7ZS5idWxsZXQ9ODIyNjtlLmJ1bGxldGludmVyc2U9OTY4ODtlLmJ1bGxldG9wZXJhdG9yPTg3Mjk7ZS5idWxsc2V5ZT05Njc4O2UuYz05OTtlLmNhYXJtZW5pYW49MTM5MDtlLmNhYmVuZ2FsaT0yNDU4O2UuY2FjdXRlPTI2MztlLmNhZGV2YT0yMzMwO2UuY2FndWphcmF0aT0yNzE0O2UuY2FndXJtdWtoaT0yNTg2O2UuY2Fsc3F1YXJlPTEzMTkyO2UuY2FuZHJhYmluZHViZW5nYWxpPTI0MzM7ZS5jYW5kcmFiaW5kdWNtYj03ODQ7ZS5jYW5kcmFiaW5kdWRldmE9MjMwNTtlLmNhbmRyYWJpbmR1Z3VqYXJhdGk9MjY4OTtlLmNhcHNsb2NrPTg2ODI7ZS5jYXJlb2Y9ODQ1MztlLmNhcm9uPTcxMTtlLmNhcm9uYmVsb3djbWI9ODEyO2UuY2Fyb25jbWI9NzgwO2UuY2FycmlhZ2VyZXR1cm49ODYyOTtlLmNib3BvbW9mbz0xMjU2ODtlLmNjYXJvbj0yNjk7ZS5jY2VkaWxsYT0yMzE7ZS5jY2VkaWxsYWFjdXRlPTc2ODk7ZS5jY2lyY2xlPTk0MjY7ZS5jY2lyY3VtZmxleD0yNjU7ZS5jY3VybD01OTc7ZS5jZG90PTI2NztlLmNkb3RhY2NlbnQ9MjY3O2UuY2RzcXVhcmU9MTMyNTM7ZS5jZWRpbGxhPTE4NDtlLmNlZGlsbGFjbWI9ODA3O2UuY2VudD0xNjI7ZS5jZW50aWdyYWRlPTg0NTE7ZS5jZW50aW5mZXJpb3I9NjMxOTk7ZS5jZW50bW9ub3NwYWNlPTY1NTA0O2UuY2VudG9sZHN0eWxlPTYzMzk0O2UuY2VudHN1cGVyaW9yPTYzMjAwO2UuY2hhYXJtZW5pYW49MTQwMTtlLmNoYWJlbmdhbGk9MjQ1OTtlLmNoYWRldmE9MjMzMTtlLmNoYWd1amFyYXRpPTI3MTU7ZS5jaGFndXJtdWtoaT0yNTg3O2UuY2hib3BvbW9mbz0xMjU2NDtlLmNoZWFia2hhc2lhbmN5cmlsbGljPTEyMTM7ZS5jaGVja21hcms9MTAwMDM7ZS5jaGVjeXJpbGxpYz0xMDk1O2UuY2hlZGVzY2VuZGVyYWJraGFzaWFuY3lyaWxsaWM9MTIxNTtlLmNoZWRlc2NlbmRlcmN5cmlsbGljPTEyMDc7ZS5jaGVkaWVyZXNpc2N5cmlsbGljPTEyNjk7ZS5jaGVoYXJtZW5pYW49MTM5NTtlLmNoZWtoYWthc3NpYW5jeXJpbGxpYz0xMjI4O2UuY2hldmVydGljYWxzdHJva2VjeXJpbGxpYz0xMjA5O2UuY2hpPTk2NztlLmNoaWV1Y2hhY2lyY2xla29yZWFuPTEyOTE5O2UuY2hpZXVjaGFwYXJlbmtvcmVhbj0xMjgyMztlLmNoaWV1Y2hjaXJjbGVrb3JlYW49MTI5MDU7ZS5jaGlldWNoa29yZWFuPTEyNjE4O2UuY2hpZXVjaHBhcmVua29yZWFuPTEyODA5O2UuY2hvY2hhbmd0aGFpPTM1OTQ7ZS5jaG9jaGFudGhhaT0zNTkyO2UuY2hvY2hpbmd0aGFpPTM1OTM7ZS5jaG9jaG9ldGhhaT0zNTk2O2UuY2hvb2s9MzkyO2UuY2lldWNhY2lyY2xla29yZWFuPTEyOTE4O2UuY2lldWNhcGFyZW5rb3JlYW49MTI4MjI7ZS5jaWV1Y2NpcmNsZWtvcmVhbj0xMjkwNDtlLmNpZXVja29yZWFuPTEyNjE2O2UuY2lldWNwYXJlbmtvcmVhbj0xMjgwODtlLmNpZXVjdXBhcmVua29yZWFuPTEyODI4O2UuY2lyY2xlPTk2NzU7ZS5jaXJjbGVjb3B5cnQ9MTY5O2UuY2lyY2xlbXVsdGlwbHk9ODg1NTtlLmNpcmNsZW90PTg4NTc7ZS5jaXJjbGVwbHVzPTg4NTM7ZS5jaXJjbGVwb3N0YWxtYXJrPTEyMzQyO2UuY2lyY2xld2l0aGxlZnRoYWxmYmxhY2s9OTY4MDtlLmNpcmNsZXdpdGhyaWdodGhhbGZibGFjaz05NjgxO2UuY2lyY3VtZmxleD03MTA7ZS5jaXJjdW1mbGV4YmVsb3djbWI9ODEzO2UuY2lyY3VtZmxleGNtYj03NzA7ZS5jbGVhcj04OTk5O2UuY2xpY2thbHZlb2xhcj00NTA7ZS5jbGlja2RlbnRhbD00NDg7ZS5jbGlja2xhdGVyYWw9NDQ5O2UuY2xpY2tyZXRyb2ZsZXg9NDUxO2UuY2x1Yj05ODI3O2UuY2x1YnN1aXRibGFjaz05ODI3O2UuY2x1YnN1aXR3aGl0ZT05ODMxO2UuY21jdWJlZHNxdWFyZT0xMzIyMDtlLmNtb25vc3BhY2U9NjUzNDc7ZS5jbXNxdWFyZWRzcXVhcmU9MTMyMTY7ZS5jb2FybWVuaWFuPTE0MDk7ZS5jb2xvbj01ODtlLmNvbG9ubW9uZXRhcnk9ODM1MztlLmNvbG9ubW9ub3NwYWNlPTY1MzA2O2UuY29sb25zaWduPTgzNTM7ZS5jb2xvbnNtYWxsPTY1MTA5O2UuY29sb250cmlhbmd1bGFyaGFsZm1vZD03MjE7ZS5jb2xvbnRyaWFuZ3VsYXJtb2Q9NzIwO2UuY29tbWE9NDQ7ZS5jb21tYWFib3ZlY21iPTc4NztlLmNvbW1hYWJvdmVyaWdodGNtYj03ODk7ZS5jb21tYWFjY2VudD02MzE3MTtlLmNvbW1hYXJhYmljPTE1NDg7ZS5jb21tYWFybWVuaWFuPTEzNzM7ZS5jb21tYWluZmVyaW9yPTYzMjAxO2UuY29tbWFtb25vc3BhY2U9NjUyOTI7ZS5jb21tYXJldmVyc2VkYWJvdmVjbWI9Nzg4O2UuY29tbWFyZXZlcnNlZG1vZD03MDE7ZS5jb21tYXNtYWxsPTY1MTA0O2UuY29tbWFzdXBlcmlvcj02MzIwMjtlLmNvbW1hdHVybmVkYWJvdmVjbWI9Nzg2O2UuY29tbWF0dXJuZWRtb2Q9Njk5O2UuY29tcGFzcz05Nzg4O2UuY29uZ3J1ZW50PTg3NzM7ZS5jb250b3VyaW50ZWdyYWw9ODc1MDtlLmNvbnRyb2w9ODk2MztlLmNvbnRyb2xBQ0s9NjtlLmNvbnRyb2xCRUw9NztlLmNvbnRyb2xCUz04O2UuY29udHJvbENBTj0yNDtlLmNvbnRyb2xDUj0xMztlLmNvbnRyb2xEQzE9MTc7ZS5jb250cm9sREMyPTE4O2UuY29udHJvbERDMz0xOTtlLmNvbnRyb2xEQzQ9MjA7ZS5jb250cm9sREVMPTEyNztlLmNvbnRyb2xETEU9MTY7ZS5jb250cm9sRU09MjU7ZS5jb250cm9sRU5RPTU7ZS5jb250cm9sRU9UPTQ7ZS5jb250cm9sRVNDPTI3O2UuY29udHJvbEVUQj0yMztlLmNvbnRyb2xFVFg9MztlLmNvbnRyb2xGRj0xMjtlLmNvbnRyb2xGUz0yODtlLmNvbnRyb2xHUz0yOTtlLmNvbnRyb2xIVD05O2UuY29udHJvbExGPTEwO2UuY29udHJvbE5BSz0yMTtlLmNvbnRyb2xOVUxMPTA7ZS5jb250cm9sUlM9MzA7ZS5jb250cm9sU0k9MTU7ZS5jb250cm9sU089MTQ7ZS5jb250cm9sU09UPTI7ZS5jb250cm9sU1RYPTE7ZS5jb250cm9sU1VCPTI2O2UuY29udHJvbFNZTj0yMjtlLmNvbnRyb2xVUz0zMTtlLmNvbnRyb2xWVD0xMTtlLmNvcHlyaWdodD0xNjk7ZS5jb3B5cmlnaHRzYW5zPTYzNzIxO2UuY29weXJpZ2h0c2VyaWY9NjMxOTM7ZS5jb3JuZXJicmFja2V0bGVmdD0xMjMwMDtlLmNvcm5lcmJyYWNrZXRsZWZ0aGFsZndpZHRoPTY1Mzc4O2UuY29ybmVyYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA4OTtlLmNvcm5lcmJyYWNrZXRyaWdodD0xMjMwMTtlLmNvcm5lcmJyYWNrZXRyaWdodGhhbGZ3aWR0aD02NTM3OTtlLmNvcm5lcmJyYWNrZXRyaWdodHZlcnRpY2FsPTY1MDkwO2UuY29ycG9yYXRpb25zcXVhcmU9MTMxODM7ZS5jb3NxdWFyZT0xMzI1NTtlLmNvdmVya2dzcXVhcmU9MTMyNTQ7ZS5jcGFyZW49OTM3NDtlLmNydXplaXJvPTgzNTQ7ZS5jc3RyZXRjaGVkPTY2MztlLmN1cmx5YW5kPTg5MTE7ZS5jdXJseW9yPTg5MTA7ZS5jdXJyZW5jeT0xNjQ7ZS5jeXJCcmV2ZT02MzE4NTtlLmN5ckZsZXg9NjMxODY7ZS5jeXJicmV2ZT02MzE4ODtlLmN5cmZsZXg9NjMxODk7ZS5kPTEwMDtlLmRhYXJtZW5pYW49MTM4MDtlLmRhYmVuZ2FsaT0yNDcwO2UuZGFkYXJhYmljPTE1OTA7ZS5kYWRldmE9MjM0MjtlLmRhZGZpbmFsYXJhYmljPTY1MjE0O2UuZGFkaW5pdGlhbGFyYWJpYz02NTIxNTtlLmRhZG1lZGlhbGFyYWJpYz02NTIxNjtlLmRhZ2VzaD0xNDY4O2UuZGFnZXNoaGVicmV3PTE0Njg7ZS5kYWdnZXI9ODIyNDtlLmRhZ2dlcmRibD04MjI1O2UuZGFndWphcmF0aT0yNzI2O2UuZGFndXJtdWtoaT0yNTk4O2UuZGFoaXJhZ2FuYT0xMjM4NDtlLmRha2F0YWthbmE9MTI0ODA7ZS5kYWxhcmFiaWM9MTU4MztlLmRhbGV0PTE0OTE7ZS5kYWxldGRhZ2VzaD02NDMwNztlLmRhbGV0ZGFnZXNoaGVicmV3PTY0MzA3O2UuZGFsZXRoZWJyZXc9MTQ5MTtlLmRhbGZpbmFsYXJhYmljPTY1MTk0O2UuZGFtbWFhcmFiaWM9MTYxNTtlLmRhbW1hbG93YXJhYmljPTE2MTU7ZS5kYW1tYXRhbmFsdG9uZWFyYWJpYz0xNjEyO2UuZGFtbWF0YW5hcmFiaWM9MTYxMjtlLmRhbmRhPTI0MDQ7ZS5kYXJnYWhlYnJldz0xNDQ3O2UuZGFyZ2FsZWZ0aGVicmV3PTE0NDc7ZS5kYXNpYXBuZXVtYXRhY3lyaWxsaWNjbWI9MTE1NztlLmRibEdyYXZlPTYzMTg3O2UuZGJsYW5nbGVicmFja2V0bGVmdD0xMjI5ODtlLmRibGFuZ2xlYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA4NTtlLmRibGFuZ2xlYnJhY2tldHJpZ2h0PTEyMjk5O2UuZGJsYW5nbGVicmFja2V0cmlnaHR2ZXJ0aWNhbD02NTA4NjtlLmRibGFyY2hpbnZlcnRlZGJlbG93Y21iPTgxMTtlLmRibGFycm93bGVmdD04NjYwO2UuZGJsYXJyb3dyaWdodD04NjU4O2UuZGJsZGFuZGE9MjQwNTtlLmRibGdyYXZlPTYzMTkwO2UuZGJsZ3JhdmVjbWI9NzgzO2UuZGJsaW50ZWdyYWw9ODc0ODtlLmRibGxvd2xpbmU9ODIxNTtlLmRibGxvd2xpbmVjbWI9ODE5O2UuZGJsb3ZlcmxpbmVjbWI9ODMxO2UuZGJscHJpbWVtb2Q9Njk4O2UuZGJsdmVydGljYWxiYXI9ODIxNDtlLmRibHZlcnRpY2FsbGluZWFib3ZlY21iPTc4MjtlLmRib3BvbW9mbz0xMjU1MztlLmRic3F1YXJlPTEzMjU2O2UuZGNhcm9uPTI3MTtlLmRjZWRpbGxhPTc2OTc7ZS5kY2lyY2xlPTk0Mjc7ZS5kY2lyY3VtZmxleGJlbG93PTc2OTk7ZS5kY3JvYXQ9MjczO2UuZGRhYmVuZ2FsaT0yNDY1O2UuZGRhZGV2YT0yMzM3O2UuZGRhZ3VqYXJhdGk9MjcyMTtlLmRkYWd1cm11a2hpPTI1OTM7ZS5kZGFsYXJhYmljPTE2NzI7ZS5kZGFsZmluYWxhcmFiaWM9NjQzOTM7ZS5kZGRoYWRldmE9MjM5NjtlLmRkaGFiZW5nYWxpPTI0NjY7ZS5kZGhhZGV2YT0yMzM4O2UuZGRoYWd1amFyYXRpPTI3MjI7ZS5kZGhhZ3VybXVraGk9MjU5NDtlLmRkb3RhY2NlbnQ9NzY5MTtlLmRkb3RiZWxvdz03NjkzO2UuZGVjaW1hbHNlcGFyYXRvcmFyYWJpYz0xNjQzO2UuZGVjaW1hbHNlcGFyYXRvcnBlcnNpYW49MTY0MztlLmRlY3lyaWxsaWM9MTA3NjtlLmRlZ3JlZT0xNzY7ZS5kZWhpaGVicmV3PTE0NTM7ZS5kZWhpcmFnYW5hPTEyMzkxO2UuZGVpY29wdGljPTEwMDc7ZS5kZWthdGFrYW5hPTEyNDg3O2UuZGVsZXRlbGVmdD05MDAzO2UuZGVsZXRlcmlnaHQ9ODk5ODtlLmRlbHRhPTk0ODtlLmRlbHRhdHVybmVkPTM5NztlLmRlbm9taW5hdG9ybWludXNvbmVudW1lcmF0b3JiZW5nYWxpPTI1NTI7ZS5kZXpoPTY3NjtlLmRoYWJlbmdhbGk9MjQ3MTtlLmRoYWRldmE9MjM0MztlLmRoYWd1amFyYXRpPTI3Mjc7ZS5kaGFndXJtdWtoaT0yNTk5O2UuZGhvb2s9NTk5O2UuZGlhbHl0aWthdG9ub3M9OTAxO2UuZGlhbHl0aWthdG9ub3NjbWI9ODM2O2UuZGlhbW9uZD05ODMwO2UuZGlhbW9uZHN1aXR3aGl0ZT05ODI2O2UuZGllcmVzaXM9MTY4O2UuZGllcmVzaXNhY3V0ZT02MzE5MTtlLmRpZXJlc2lzYmVsb3djbWI9ODA0O2UuZGllcmVzaXNjbWI9Nzc2O2UuZGllcmVzaXNncmF2ZT02MzE5MjtlLmRpZXJlc2lzdG9ub3M9OTAxO2UuZGloaXJhZ2FuYT0xMjM4NjtlLmRpa2F0YWthbmE9MTI0ODI7ZS5kaXR0b21hcms9MTIyOTE7ZS5kaXZpZGU9MjQ3O2UuZGl2aWRlcz04NzM5O2UuZGl2aXNpb25zbGFzaD04NzI1O2UuZGplY3lyaWxsaWM9MTEwNjtlLmRrc2hhZGU9OTYxOTtlLmRsaW5lYmVsb3c9NzY5NTtlLmRsc3F1YXJlPTEzMjA3O2UuZG1hY3Jvbj0yNzM7ZS5kbW9ub3NwYWNlPTY1MzQ4O2UuZG5ibG9jaz05NjA0O2UuZG9jaGFkYXRoYWk9MzU5ODtlLmRvZGVrdGhhaT0zNjA0O2UuZG9oaXJhZ2FuYT0xMjM5MztlLmRva2F0YWthbmE9MTI0ODk7ZS5kb2xsYXI9MzY7ZS5kb2xsYXJpbmZlcmlvcj02MzIwMztlLmRvbGxhcm1vbm9zcGFjZT02NTI4NDtlLmRvbGxhcm9sZHN0eWxlPTYzMjY4O2UuZG9sbGFyc21hbGw9NjUxMjk7ZS5kb2xsYXJzdXBlcmlvcj02MzIwNDtlLmRvbmc9ODM2MztlLmRvcnVzcXVhcmU9MTMwOTQ7ZS5kb3RhY2NlbnQ9NzI5O2UuZG90YWNjZW50Y21iPTc3NTtlLmRvdGJlbG93Y21iPTgwMztlLmRvdGJlbG93Y29tYj04MDM7ZS5kb3RrYXRha2FuYT0xMjUzOTtlLmRvdGxlc3NpPTMwNTtlLmRvdGxlc3NqPTYzMTY2O2UuZG90bGVzc2pzdHJva2Vob29rPTY0NDtlLmRvdG1hdGg9ODkwMTtlLmRvdHRlZGNpcmNsZT05Njc2O2UuZG91YmxleW9kcGF0YWg9NjQyODc7ZS5kb3VibGV5b2RwYXRhaGhlYnJldz02NDI4NztlLmRvd250YWNrYmVsb3djbWI9Nzk4O2UuZG93bnRhY2ttb2Q9NzI1O2UuZHBhcmVuPTkzNzU7ZS5kc3VwZXJpb3I9NjMyMTE7ZS5kdGFpbD01OTg7ZS5kdG9wYmFyPTM5NjtlLmR1aGlyYWdhbmE9MTIzODk7ZS5kdWthdGFrYW5hPTEyNDg1O2UuZHo9NDk5O2UuZHphbHRvbmU9Njc1O2UuZHpjYXJvbj00NTQ7ZS5kemN1cmw9Njc3O2UuZHplYWJraGFzaWFuY3lyaWxsaWM9MTI0OTtlLmR6ZWN5cmlsbGljPTExMDk7ZS5kemhlY3lyaWxsaWM9MTExOTtlLmU9MTAxO2UuZWFjdXRlPTIzMztlLmVhcnRoPTk3OTM7ZS5lYmVuZ2FsaT0yNDQ3O2UuZWJvcG9tb2ZvPTEyNTcyO2UuZWJyZXZlPTI3NztlLmVjYW5kcmFkZXZhPTIzMTc7ZS5lY2FuZHJhZ3VqYXJhdGk9MjcwMTtlLmVjYW5kcmF2b3dlbHNpZ25kZXZhPTIzNzM7ZS5lY2FuZHJhdm93ZWxzaWduZ3VqYXJhdGk9Mjc1NztlLmVjYXJvbj0yODM7ZS5lY2VkaWxsYWJyZXZlPTc3MDk7ZS5lY2hhcm1lbmlhbj0xMzgxO2UuZWNoeWl3bmFybWVuaWFuPTE0MTU7ZS5lY2lyY2xlPTk0Mjg7ZS5lY2lyY3VtZmxleD0yMzQ7ZS5lY2lyY3VtZmxleGFjdXRlPTc4NzE7ZS5lY2lyY3VtZmxleGJlbG93PTc3MDU7ZS5lY2lyY3VtZmxleGRvdGJlbG93PTc4Nzk7ZS5lY2lyY3VtZmxleGdyYXZlPTc4NzM7ZS5lY2lyY3VtZmxleGhvb2thYm92ZT03ODc1O2UuZWNpcmN1bWZsZXh0aWxkZT03ODc3O2UuZWN5cmlsbGljPTExMDg7ZS5lZGJsZ3JhdmU9NTE3O2UuZWRldmE9MjMxOTtlLmVkaWVyZXNpcz0yMzU7ZS5lZG90PTI3OTtlLmVkb3RhY2NlbnQ9Mjc5O2UuZWRvdGJlbG93PTc4NjU7ZS5lZWd1cm11a2hpPTI1NzU7ZS5lZW1hdHJhZ3VybXVraGk9MjYzMTtlLmVmY3lyaWxsaWM9MTA5MjtlLmVncmF2ZT0yMzI7ZS5lZ3VqYXJhdGk9MjcwMztlLmVoYXJtZW5pYW49MTM4MztlLmVoYm9wb21vZm89MTI1NzM7ZS5laGlyYWdhbmE9MTIzNjA7ZS5laG9va2Fib3ZlPTc4Njc7ZS5laWJvcG9tb2ZvPTEyNTc1O2UuZWlnaHQ9NTY7ZS5laWdodGFyYWJpYz0xNjQwO2UuZWlnaHRiZW5nYWxpPTI1NDI7ZS5laWdodGNpcmNsZT05MzE5O2UuZWlnaHRjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmPTEwMTI5O2UuZWlnaHRkZXZhPTI0MTQ7ZS5laWdodGVlbmNpcmNsZT05MzI5O2UuZWlnaHRlZW5wYXJlbj05MzQ5O2UuZWlnaHRlZW5wZXJpb2Q9OTM2OTtlLmVpZ2h0Z3VqYXJhdGk9Mjc5ODtlLmVpZ2h0Z3VybXVraGk9MjY3MDtlLmVpZ2h0aGFja2FyYWJpYz0xNjQwO2UuZWlnaHRoYW5nemhvdT0xMjMyODtlLmVpZ2h0aG5vdGViZWFtZWQ9OTgzNTtlLmVpZ2h0aWRlb2dyYXBoaWNwYXJlbj0xMjgzOTtlLmVpZ2h0aW5mZXJpb3I9ODMyODtlLmVpZ2h0bW9ub3NwYWNlPTY1MzA0O2UuZWlnaHRvbGRzdHlsZT02MzI4ODtlLmVpZ2h0cGFyZW49OTMzOTtlLmVpZ2h0cGVyaW9kPTkzNTk7ZS5laWdodHBlcnNpYW49MTc4NDtlLmVpZ2h0cm9tYW49ODU2NztlLmVpZ2h0c3VwZXJpb3I9ODMxMjtlLmVpZ2h0dGhhaT0zNjcyO2UuZWludmVydGVkYnJldmU9NTE5O2UuZWlvdGlmaWVkY3lyaWxsaWM9MTEyNTtlLmVrYXRha2FuYT0xMjQ1NjtlLmVrYXRha2FuYWhhbGZ3aWR0aD02NTM5NjtlLmVrb25rYXJndXJtdWtoaT0yNjc2O2UuZWtvcmVhbj0xMjYyODtlLmVsY3lyaWxsaWM9MTA4MztlLmVsZW1lbnQ9ODcxMjtlLmVsZXZlbmNpcmNsZT05MzIyO2UuZWxldmVucGFyZW49OTM0MjtlLmVsZXZlbnBlcmlvZD05MzYyO2UuZWxldmVucm9tYW49ODU3MDtlLmVsbGlwc2lzPTgyMzA7ZS5lbGxpcHNpc3ZlcnRpY2FsPTg5NDI7ZS5lbWFjcm9uPTI3NTtlLmVtYWNyb25hY3V0ZT03NzAzO2UuZW1hY3JvbmdyYXZlPTc3MDE7ZS5lbWN5cmlsbGljPTEwODQ7ZS5lbWRhc2g9ODIxMjtlLmVtZGFzaHZlcnRpY2FsPTY1MDczO2UuZW1vbm9zcGFjZT02NTM0OTtlLmVtcGhhc2lzbWFya2FybWVuaWFuPTEzNzE7ZS5lbXB0eXNldD04NzA5O2UuZW5ib3BvbW9mbz0xMjU3OTtlLmVuY3lyaWxsaWM9MTA4NTtlLmVuZGFzaD04MjExO2UuZW5kYXNodmVydGljYWw9NjUwNzQ7ZS5lbmRlc2NlbmRlcmN5cmlsbGljPTExODc7ZS5lbmc9MzMxO2UuZW5nYm9wb21vZm89MTI1ODE7ZS5lbmdoZWN5cmlsbGljPTExODk7ZS5lbmhvb2tjeXJpbGxpYz0xMjI0O2UuZW5zcGFjZT04MTk0O2UuZW9nb25laz0yODE7ZS5lb2tvcmVhbj0xMjYyNztlLmVvcGVuPTYwMztlLmVvcGVuY2xvc2VkPTY2NjtlLmVvcGVucmV2ZXJzZWQ9NjA0O2UuZW9wZW5yZXZlcnNlZGNsb3NlZD02MDY7ZS5lb3BlbnJldmVyc2VkaG9vaz02MDU7ZS5lcGFyZW49OTM3NjtlLmVwc2lsb249OTQ5O2UuZXBzaWxvbnRvbm9zPTk0MTtlLmVxdWFsPTYxO2UuZXF1YWxtb25vc3BhY2U9NjUzMDk7ZS5lcXVhbHNtYWxsPTY1MTI2O2UuZXF1YWxzdXBlcmlvcj04MzE2O2UuZXF1aXZhbGVuY2U9ODgwMTtlLmVyYm9wb21vZm89MTI1ODI7ZS5lcmN5cmlsbGljPTEwODg7ZS5lcmV2ZXJzZWQ9NjAwO2UuZXJldmVyc2VkY3lyaWxsaWM9MTEwMTtlLmVzY3lyaWxsaWM9MTA4OTtlLmVzZGVzY2VuZGVyY3lyaWxsaWM9MTE5NTtlLmVzaD02NDM7ZS5lc2hjdXJsPTY0NjtlLmVzaG9ydGRldmE9MjMxODtlLmVzaG9ydHZvd2Vsc2lnbmRldmE9MjM3NDtlLmVzaHJldmVyc2VkbG9vcD00MjY7ZS5lc2hzcXVhdHJldmVyc2VkPTY0NTtlLmVzbWFsbGhpcmFnYW5hPTEyMzU5O2UuZXNtYWxsa2F0YWthbmE9MTI0NTU7ZS5lc21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM4NjtlLmVzdGltYXRlZD04NDk0O2UuZXN1cGVyaW9yPTYzMjEyO2UuZXRhPTk1MTtlLmV0YXJtZW5pYW49MTM4NDtlLmV0YXRvbm9zPTk0MjtlLmV0aD0yNDA7ZS5ldGlsZGU9Nzg2OTtlLmV0aWxkZWJlbG93PTc3MDc7ZS5ldG5haHRhZm91a2hoZWJyZXc9MTQyNTtlLmV0bmFodGFmb3VraGxlZnRoZWJyZXc9MTQyNTtlLmV0bmFodGFoZWJyZXc9MTQyNTtlLmV0bmFodGFsZWZ0aGVicmV3PTE0MjU7ZS5ldHVybmVkPTQ3NztlLmV1a29yZWFuPTEyNjQxO2UuZXVybz04MzY0O2UuZXZvd2Vsc2lnbmJlbmdhbGk9MjUwMztlLmV2b3dlbHNpZ25kZXZhPTIzNzU7ZS5ldm93ZWxzaWduZ3VqYXJhdGk9Mjc1OTtlLmV4Y2xhbT0zMztlLmV4Y2xhbWFybWVuaWFuPTEzNzI7ZS5leGNsYW1kYmw9ODI1MjtlLmV4Y2xhbWRvd249MTYxO2UuZXhjbGFtZG93bnNtYWxsPTYzMzkzO2UuZXhjbGFtbW9ub3NwYWNlPTY1MjgxO2UuZXhjbGFtc21hbGw9NjMyNjU7ZS5leGlzdGVudGlhbD04NzA3O2UuZXpoPTY1ODtlLmV6aGNhcm9uPTQ5NTtlLmV6aGN1cmw9NjU5O2UuZXpocmV2ZXJzZWQ9NDQxO2UuZXpodGFpbD00NDI7ZS5mPTEwMjtlLmZhZGV2YT0yMzk4O2UuZmFndXJtdWtoaT0yNjU0O2UuZmFocmVuaGVpdD04NDU3O2UuZmF0aGFhcmFiaWM9MTYxNDtlLmZhdGhhbG93YXJhYmljPTE2MTQ7ZS5mYXRoYXRhbmFyYWJpYz0xNjExO2UuZmJvcG9tb2ZvPTEyNTUyO2UuZmNpcmNsZT05NDI5O2UuZmRvdGFjY2VudD03NzExO2UuZmVoYXJhYmljPTE2MDE7ZS5mZWhhcm1lbmlhbj0xNDE0O2UuZmVoZmluYWxhcmFiaWM9NjUyMzQ7ZS5mZWhpbml0aWFsYXJhYmljPTY1MjM1O2UuZmVobWVkaWFsYXJhYmljPTY1MjM2O2UuZmVpY29wdGljPTk5NztlLmZlbWFsZT05NzkyO2UuZmY9NjQyNTY7ZS5mX2Y9NjQyNTY7ZS5mZmk9NjQyNTk7ZS5mX2ZfaT02NDI1OTtlLmZmbD02NDI2MDtlLmZfZl9sPTY0MjYwO2UuZmk9NjQyNTc7ZS5mX2k9NjQyNTc7ZS5maWZ0ZWVuY2lyY2xlPTkzMjY7ZS5maWZ0ZWVucGFyZW49OTM0NjtlLmZpZnRlZW5wZXJpb2Q9OTM2NjtlLmZpZ3VyZWRhc2g9ODIxMDtlLmZpbGxlZGJveD05NjMyO2UuZmlsbGVkcmVjdD05NjQ0O2UuZmluYWxrYWY9MTQ5ODtlLmZpbmFsa2FmZGFnZXNoPTY0MzE0O2UuZmluYWxrYWZkYWdlc2hoZWJyZXc9NjQzMTQ7ZS5maW5hbGthZmhlYnJldz0xNDk4O2UuZmluYWxtZW09MTUwMTtlLmZpbmFsbWVtaGVicmV3PTE1MDE7ZS5maW5hbG51bj0xNTAzO2UuZmluYWxudW5oZWJyZXc9MTUwMztlLmZpbmFscGU9MTUwNztlLmZpbmFscGVoZWJyZXc9MTUwNztlLmZpbmFsdHNhZGk9MTUwOTtlLmZpbmFsdHNhZGloZWJyZXc9MTUwOTtlLmZpcnN0dG9uZWNoaW5lc2U9NzEzO2UuZmlzaGV5ZT05NjczO2UuZml0YWN5cmlsbGljPTExMzk7ZS5maXZlPTUzO2UuZml2ZWFyYWJpYz0xNjM3O2UuZml2ZWJlbmdhbGk9MjUzOTtlLmZpdmVjaXJjbGU9OTMxNjtlLmZpdmVjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmPTEwMTI2O2UuZml2ZWRldmE9MjQxMTtlLmZpdmVlaWdodGhzPTg1NDE7ZS5maXZlZ3VqYXJhdGk9Mjc5NTtlLmZpdmVndXJtdWtoaT0yNjY3O2UuZml2ZWhhY2thcmFiaWM9MTYzNztlLmZpdmVoYW5nemhvdT0xMjMyNTtlLmZpdmVpZGVvZ3JhcGhpY3BhcmVuPTEyODM2O2UuZml2ZWluZmVyaW9yPTgzMjU7ZS5maXZlbW9ub3NwYWNlPTY1MzAxO2UuZml2ZW9sZHN0eWxlPTYzMjg1O2UuZml2ZXBhcmVuPTkzMzY7ZS5maXZlcGVyaW9kPTkzNTY7ZS5maXZlcGVyc2lhbj0xNzgxO2UuZml2ZXJvbWFuPTg1NjQ7ZS5maXZlc3VwZXJpb3I9ODMwOTtlLmZpdmV0aGFpPTM2Njk7ZS5mbD02NDI1ODtlLmZfbD02NDI1ODtlLmZsb3Jpbj00MDI7ZS5mbW9ub3NwYWNlPTY1MzUwO2UuZm1zcXVhcmU9MTMyMDk7ZS5mb2ZhbnRoYWk9MzYxNTtlLmZvZmF0aGFpPTM2MTM7ZS5mb25nbWFudGhhaT0zNjYzO2UuZm9yYWxsPTg3MDQ7ZS5mb3VyPTUyO2UuZm91cmFyYWJpYz0xNjM2O2UuZm91cmJlbmdhbGk9MjUzODtlLmZvdXJjaXJjbGU9OTMxNTtlLmZvdXJjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmPTEwMTI1O2UuZm91cmRldmE9MjQxMDtlLmZvdXJndWphcmF0aT0yNzk0O2UuZm91cmd1cm11a2hpPTI2NjY7ZS5mb3VyaGFja2FyYWJpYz0xNjM2O2UuZm91cmhhbmd6aG91PTEyMzI0O2UuZm91cmlkZW9ncmFwaGljcGFyZW49MTI4MzU7ZS5mb3VyaW5mZXJpb3I9ODMyNDtlLmZvdXJtb25vc3BhY2U9NjUzMDA7ZS5mb3VybnVtZXJhdG9yYmVuZ2FsaT0yNTUxO2UuZm91cm9sZHN0eWxlPTYzMjg0O2UuZm91cnBhcmVuPTkzMzU7ZS5mb3VycGVyaW9kPTkzNTU7ZS5mb3VycGVyc2lhbj0xNzgwO2UuZm91cnJvbWFuPTg1NjM7ZS5mb3Vyc3VwZXJpb3I9ODMwODtlLmZvdXJ0ZWVuY2lyY2xlPTkzMjU7ZS5mb3VydGVlbnBhcmVuPTkzNDU7ZS5mb3VydGVlbnBlcmlvZD05MzY1O2UuZm91cnRoYWk9MzY2ODtlLmZvdXJ0aHRvbmVjaGluZXNlPTcxNTtlLmZwYXJlbj05Mzc3O2UuZnJhY3Rpb249ODI2MDtlLmZyYW5jPTgzNTU7ZS5nPTEwMztlLmdhYmVuZ2FsaT0yNDU1O2UuZ2FjdXRlPTUwMTtlLmdhZGV2YT0yMzI3O2UuZ2FmYXJhYmljPTE3MTE7ZS5nYWZmaW5hbGFyYWJpYz02NDQwMztlLmdhZmluaXRpYWxhcmFiaWM9NjQ0MDQ7ZS5nYWZtZWRpYWxhcmFiaWM9NjQ0MDU7ZS5nYWd1amFyYXRpPTI3MTE7ZS5nYWd1cm11a2hpPTI1ODM7ZS5nYWhpcmFnYW5hPTEyMzY0O2UuZ2FrYXRha2FuYT0xMjQ2MDtlLmdhbW1hPTk0NztlLmdhbW1hbGF0aW5zbWFsbD02MTE7ZS5nYW1tYXN1cGVyaW9yPTczNjtlLmdhbmdpYWNvcHRpYz0xMDAzO2UuZ2JvcG9tb2ZvPTEyNTU3O2UuZ2JyZXZlPTI4NztlLmdjYXJvbj00ODc7ZS5nY2VkaWxsYT0yOTE7ZS5nY2lyY2xlPTk0MzA7ZS5nY2lyY3VtZmxleD0yODU7ZS5nY29tbWFhY2NlbnQ9MjkxO2UuZ2RvdD0yODk7ZS5nZG90YWNjZW50PTI4OTtlLmdlY3lyaWxsaWM9MTA3NTtlLmdlaGlyYWdhbmE9MTIzNzA7ZS5nZWthdGFrYW5hPTEyNDY2O2UuZ2VvbWV0cmljYWxseWVxdWFsPTg3ODU7ZS5nZXJlc2hhY2NlbnRoZWJyZXc9MTQzNjtlLmdlcmVzaGhlYnJldz0xNTIzO2UuZ2VyZXNobXVxZGFtaGVicmV3PTE0Mzc7ZS5nZXJtYW5kYmxzPTIyMztlLmdlcnNoYXlpbWFjY2VudGhlYnJldz0xNDM4O2UuZ2Vyc2hheWltaGVicmV3PTE1MjQ7ZS5nZXRhbWFyaz0xMjMwNztlLmdoYWJlbmdhbGk9MjQ1NjtlLmdoYWRhcm1lbmlhbj0xMzk0O2UuZ2hhZGV2YT0yMzI4O2UuZ2hhZ3VqYXJhdGk9MjcxMjtlLmdoYWd1cm11a2hpPTI1ODQ7ZS5naGFpbmFyYWJpYz0xNTk0O2UuZ2hhaW5maW5hbGFyYWJpYz02NTIzMDtlLmdoYWluaW5pdGlhbGFyYWJpYz02NTIzMTtlLmdoYWlubWVkaWFsYXJhYmljPTY1MjMyO2UuZ2hlbWlkZGxlaG9va2N5cmlsbGljPTExNzM7ZS5naGVzdHJva2VjeXJpbGxpYz0xMTcxO2UuZ2hldXB0dXJuY3lyaWxsaWM9MTE2OTtlLmdoaGFkZXZhPTIzOTQ7ZS5naGhhZ3VybXVraGk9MjY1MDtlLmdob29rPTYwODtlLmdoenNxdWFyZT0xMzIwMztlLmdpaGlyYWdhbmE9MTIzNjY7ZS5naWthdGFrYW5hPTEyNDYyO2UuZ2ltYXJtZW5pYW49MTM3OTtlLmdpbWVsPTE0OTA7ZS5naW1lbGRhZ2VzaD02NDMwNjtlLmdpbWVsZGFnZXNoaGVicmV3PTY0MzA2O2UuZ2ltZWxoZWJyZXc9MTQ5MDtlLmdqZWN5cmlsbGljPTExMDc7ZS5nbG90dGFsaW52ZXJ0ZWRzdHJva2U9NDQ2O2UuZ2xvdHRhbHN0b3A9NjYwO2UuZ2xvdHRhbHN0b3BpbnZlcnRlZD02NjI7ZS5nbG90dGFsc3RvcG1vZD03MDQ7ZS5nbG90dGFsc3RvcHJldmVyc2VkPTY2MTtlLmdsb3R0YWxzdG9wcmV2ZXJzZWRtb2Q9NzA1O2UuZ2xvdHRhbHN0b3ByZXZlcnNlZHN1cGVyaW9yPTc0MDtlLmdsb3R0YWxzdG9wc3Ryb2tlPTY3MztlLmdsb3R0YWxzdG9wc3Ryb2tlcmV2ZXJzZWQ9Njc0O2UuZ21hY3Jvbj03NzEzO2UuZ21vbm9zcGFjZT02NTM1MTtlLmdvaGlyYWdhbmE9MTIzNzI7ZS5nb2thdGFrYW5hPTEyNDY4O2UuZ3BhcmVuPTkzNzg7ZS5ncGFzcXVhcmU9MTMyMjg7ZS5ncmFkaWVudD04NzExO2UuZ3JhdmU9OTY7ZS5ncmF2ZWJlbG93Y21iPTc5MDtlLmdyYXZlY21iPTc2ODtlLmdyYXZlY29tYj03Njg7ZS5ncmF2ZWRldmE9MjM4NztlLmdyYXZlbG93bW9kPTcxODtlLmdyYXZlbW9ub3NwYWNlPTY1MzQ0O2UuZ3JhdmV0b25lY21iPTgzMjtlLmdyZWF0ZXI9NjI7ZS5ncmVhdGVyZXF1YWw9ODgwNTtlLmdyZWF0ZXJlcXVhbG9ybGVzcz04OTIzO2UuZ3JlYXRlcm1vbm9zcGFjZT02NTMxMDtlLmdyZWF0ZXJvcmVxdWl2YWxlbnQ9ODgxOTtlLmdyZWF0ZXJvcmxlc3M9ODgyMztlLmdyZWF0ZXJvdmVyZXF1YWw9ODgwNztlLmdyZWF0ZXJzbWFsbD02NTEyNTtlLmdzY3JpcHQ9NjA5O2UuZ3N0cm9rZT00ODU7ZS5ndWhpcmFnYW5hPTEyMzY4O2UuZ3VpbGxlbW90bGVmdD0xNzE7ZS5ndWlsbGVtb3RyaWdodD0xODc7ZS5ndWlsc2luZ2xsZWZ0PTgyNDk7ZS5ndWlsc2luZ2xyaWdodD04MjUwO2UuZ3VrYXRha2FuYT0xMjQ2NDtlLmd1cmFtdXNxdWFyZT0xMzA4MDtlLmd5c3F1YXJlPTEzMjU3O2UuaD0xMDQ7ZS5oYWFia2hhc2lhbmN5cmlsbGljPTExOTM7ZS5oYWFsdG9uZWFyYWJpYz0xNzI5O2UuaGFiZW5nYWxpPTI0ODk7ZS5oYWRlc2NlbmRlcmN5cmlsbGljPTEyMDM7ZS5oYWRldmE9MjM2MTtlLmhhZ3VqYXJhdGk9Mjc0NTtlLmhhZ3VybXVraGk9MjYxNztlLmhhaGFyYWJpYz0xNTgxO2UuaGFoZmluYWxhcmFiaWM9NjUxODY7ZS5oYWhpbml0aWFsYXJhYmljPTY1MTg3O2UuaGFoaXJhZ2FuYT0xMjM5OTtlLmhhaG1lZGlhbGFyYWJpYz02NTE4ODtlLmhhaXR1c3F1YXJlPTEzMDk4O2UuaGFrYXRha2FuYT0xMjQ5NTtlLmhha2F0YWthbmFoYWxmd2lkdGg9NjU0MTg7ZS5oYWxhbnRndXJtdWtoaT0yNjM3O2UuaGFtemFhcmFiaWM9MTU2OTtlLmhhbXphbG93YXJhYmljPTE1Njk7ZS5oYW5ndWxmaWxsZXI9MTI2NDQ7ZS5oYXJkc2lnbmN5cmlsbGljPTEwOTg7ZS5oYXJwb29ubGVmdGJhcmJ1cD04NjM2O2UuaGFycG9vbnJpZ2h0YmFyYnVwPTg2NDA7ZS5oYXNxdWFyZT0xMzI1ODtlLmhhdGFmcGF0YWg9MTQ1ODtlLmhhdGFmcGF0YWgxNj0xNDU4O2UuaGF0YWZwYXRhaDIzPTE0NTg7ZS5oYXRhZnBhdGFoMmY9MTQ1ODtlLmhhdGFmcGF0YWhoZWJyZXc9MTQ1ODtlLmhhdGFmcGF0YWhuYXJyb3doZWJyZXc9MTQ1ODtlLmhhdGFmcGF0YWhxdWFydGVyaGVicmV3PTE0NTg7ZS5oYXRhZnBhdGFod2lkZWhlYnJldz0xNDU4O2UuaGF0YWZxYW1hdHM9MTQ1OTtlLmhhdGFmcWFtYXRzMWI9MTQ1OTtlLmhhdGFmcWFtYXRzMjg9MTQ1OTtlLmhhdGFmcWFtYXRzMzQ9MTQ1OTtlLmhhdGFmcWFtYXRzaGVicmV3PTE0NTk7ZS5oYXRhZnFhbWF0c25hcnJvd2hlYnJldz0xNDU5O2UuaGF0YWZxYW1hdHNxdWFydGVyaGVicmV3PTE0NTk7ZS5oYXRhZnFhbWF0c3dpZGVoZWJyZXc9MTQ1OTtlLmhhdGFmc2Vnb2w9MTQ1NztlLmhhdGFmc2Vnb2wxNz0xNDU3O2UuaGF0YWZzZWdvbDI0PTE0NTc7ZS5oYXRhZnNlZ29sMzA9MTQ1NztlLmhhdGFmc2Vnb2xoZWJyZXc9MTQ1NztlLmhhdGFmc2Vnb2xuYXJyb3doZWJyZXc9MTQ1NztlLmhhdGFmc2Vnb2xxdWFydGVyaGVicmV3PTE0NTc7ZS5oYXRhZnNlZ29sd2lkZWhlYnJldz0xNDU3O2UuaGJhcj0yOTU7ZS5oYm9wb21vZm89MTI1NTk7ZS5oYnJldmViZWxvdz03NzIzO2UuaGNlZGlsbGE9NzcyMTtlLmhjaXJjbGU9OTQzMTtlLmhjaXJjdW1mbGV4PTI5MztlLmhkaWVyZXNpcz03NzE5O2UuaGRvdGFjY2VudD03NzE1O2UuaGRvdGJlbG93PTc3MTc7ZS5oZT0xNDkyO2UuaGVhcnQ9OTgyOTtlLmhlYXJ0c3VpdGJsYWNrPTk4Mjk7ZS5oZWFydHN1aXR3aGl0ZT05ODI1O2UuaGVkYWdlc2g9NjQzMDg7ZS5oZWRhZ2VzaGhlYnJldz02NDMwODtlLmhlaGFsdG9uZWFyYWJpYz0xNzI5O2UuaGVoYXJhYmljPTE2MDc7ZS5oZWhlYnJldz0xNDkyO2UuaGVoZmluYWxhbHRvbmVhcmFiaWM9NjQ0MjM7ZS5oZWhmaW5hbGFsdHR3b2FyYWJpYz02NTI1ODtlLmhlaGZpbmFsYXJhYmljPTY1MjU4O2UuaGVoaGFtemFhYm92ZWZpbmFsYXJhYmljPTY0NDIxO2UuaGVoaGFtemFhYm92ZWlzb2xhdGVkYXJhYmljPTY0NDIwO2UuaGVoaW5pdGlhbGFsdG9uZWFyYWJpYz02NDQyNDtlLmhlaGluaXRpYWxhcmFiaWM9NjUyNTk7ZS5oZWhpcmFnYW5hPTEyNDA4O2UuaGVobWVkaWFsYWx0b25lYXJhYmljPTY0NDI1O2UuaGVobWVkaWFsYXJhYmljPTY1MjYwO2UuaGVpc2VpZXJhc3F1YXJlPTEzMTc5O2UuaGVrYXRha2FuYT0xMjUwNDtlLmhla2F0YWthbmFoYWxmd2lkdGg9NjU0MjE7ZS5oZWt1dGFhcnVzcXVhcmU9MTMxMTA7ZS5oZW5naG9vaz02MTU7ZS5oZXJ1dHVzcXVhcmU9MTMxMTM7ZS5oZXQ9MTQ5NTtlLmhldGhlYnJldz0xNDk1O2UuaGhvb2s9NjE0O2UuaGhvb2tzdXBlcmlvcj02ODk7ZS5oaWV1aGFjaXJjbGVrb3JlYW49MTI5MjM7ZS5oaWV1aGFwYXJlbmtvcmVhbj0xMjgyNztlLmhpZXVoY2lyY2xla29yZWFuPTEyOTA5O2UuaGlldWhrb3JlYW49MTI2MjI7ZS5oaWV1aHBhcmVua29yZWFuPTEyODEzO2UuaGloaXJhZ2FuYT0xMjQwMjtlLmhpa2F0YWthbmE9MTI0OTg7ZS5oaWthdGFrYW5haGFsZndpZHRoPTY1NDE5O2UuaGlyaXE9MTQ2MDtlLmhpcmlxMTQ9MTQ2MDtlLmhpcmlxMjE9MTQ2MDtlLmhpcmlxMmQ9MTQ2MDtlLmhpcmlxaGVicmV3PTE0NjA7ZS5oaXJpcW5hcnJvd2hlYnJldz0xNDYwO2UuaGlyaXFxdWFydGVyaGVicmV3PTE0NjA7ZS5oaXJpcXdpZGVoZWJyZXc9MTQ2MDtlLmhsaW5lYmVsb3c9NzgzMDtlLmhtb25vc3BhY2U9NjUzNTI7ZS5ob2FybWVuaWFuPTEzOTI7ZS5ob2hpcHRoYWk9MzYyNztlLmhvaGlyYWdhbmE9MTI0MTE7ZS5ob2thdGFrYW5hPTEyNTA3O2UuaG9rYXRha2FuYWhhbGZ3aWR0aD02NTQyMjtlLmhvbGFtPTE0NjU7ZS5ob2xhbTE5PTE0NjU7ZS5ob2xhbTI2PTE0NjU7ZS5ob2xhbTMyPTE0NjU7ZS5ob2xhbWhlYnJldz0xNDY1O2UuaG9sYW1uYXJyb3doZWJyZXc9MTQ2NTtlLmhvbGFtcXVhcnRlcmhlYnJldz0xNDY1O2UuaG9sYW13aWRlaGVicmV3PTE0NjU7ZS5ob25va2h1a3RoYWk9MzYzMDtlLmhvb2thYm92ZWNvbWI9Nzc3O2UuaG9va2NtYj03Nzc7ZS5ob29rcGFsYXRhbGl6ZWRiZWxvd2NtYj04MDE7ZS5ob29rcmV0cm9mbGV4YmVsb3djbWI9ODAyO2UuaG9vbnNxdWFyZT0xMzEyMjtlLmhvcmljb3B0aWM9MTAwMTtlLmhvcml6b250YWxiYXI9ODIxMztlLmhvcm5jbWI9Nzk1O2UuaG90c3ByaW5ncz05ODMyO2UuaG91c2U9ODk2MjtlLmhwYXJlbj05Mzc5O2UuaHN1cGVyaW9yPTY4ODtlLmh0dXJuZWQ9NjEzO2UuaHVoaXJhZ2FuYT0xMjQwNTtlLmh1aWl0b3NxdWFyZT0xMzEwNztlLmh1a2F0YWthbmE9MTI1MDE7ZS5odWthdGFrYW5haGFsZndpZHRoPTY1NDIwO2UuaHVuZ2FydW1sYXV0PTczMztlLmh1bmdhcnVtbGF1dGNtYj03Nzk7ZS5odj00MDU7ZS5oeXBoZW49NDU7ZS5oeXBoZW5pbmZlcmlvcj02MzIwNTtlLmh5cGhlbm1vbm9zcGFjZT02NTI5MztlLmh5cGhlbnNtYWxsPTY1MTIzO2UuaHlwaGVuc3VwZXJpb3I9NjMyMDY7ZS5oeXBoZW50d289ODIwODtlLmk9MTA1O2UuaWFjdXRlPTIzNztlLmlhY3lyaWxsaWM9MTEwMztlLmliZW5nYWxpPTI0Mzk7ZS5pYm9wb21vZm89MTI1ODM7ZS5pYnJldmU9MzAxO2UuaWNhcm9uPTQ2NDtlLmljaXJjbGU9OTQzMjtlLmljaXJjdW1mbGV4PTIzODtlLmljeXJpbGxpYz0xMTEwO2UuaWRibGdyYXZlPTUyMTtlLmlkZW9ncmFwaGVhcnRoY2lyY2xlPTEyOTQzO2UuaWRlb2dyYXBoZmlyZWNpcmNsZT0xMjkzOTtlLmlkZW9ncmFwaGljYWxsaWFuY2VwYXJlbj0xMjg2MztlLmlkZW9ncmFwaGljY2FsbHBhcmVuPTEyODU4O2UuaWRlb2dyYXBoaWNjZW50cmVjaXJjbGU9MTI5NjU7ZS5pZGVvZ3JhcGhpY2Nsb3NlPTEyMjk0O2UuaWRlb2dyYXBoaWNjb21tYT0xMjI4OTtlLmlkZW9ncmFwaGljY29tbWFsZWZ0PTY1MzgwO2UuaWRlb2dyYXBoaWNjb25ncmF0dWxhdGlvbnBhcmVuPTEyODU1O2UuaWRlb2dyYXBoaWNjb3JyZWN0Y2lyY2xlPTEyOTYzO2UuaWRlb2dyYXBoaWNlYXJ0aHBhcmVuPTEyODQ3O2UuaWRlb2dyYXBoaWNlbnRlcnByaXNlcGFyZW49MTI4NjE7ZS5pZGVvZ3JhcGhpY2V4Y2VsbGVudGNpcmNsZT0xMjk1NztlLmlkZW9ncmFwaGljZmVzdGl2YWxwYXJlbj0xMjg2NDtlLmlkZW9ncmFwaGljZmluYW5jaWFsY2lyY2xlPTEyOTUwO2UuaWRlb2dyYXBoaWNmaW5hbmNpYWxwYXJlbj0xMjg1NDtlLmlkZW9ncmFwaGljZmlyZXBhcmVuPTEyODQzO2UuaWRlb2dyYXBoaWNoYXZlcGFyZW49MTI4NTA7ZS5pZGVvZ3JhcGhpY2hpZ2hjaXJjbGU9MTI5NjQ7ZS5pZGVvZ3JhcGhpY2l0ZXJhdGlvbm1hcms9MTIyOTM7ZS5pZGVvZ3JhcGhpY2xhYm9yY2lyY2xlPTEyOTUyO2UuaWRlb2dyYXBoaWNsYWJvcnBhcmVuPTEyODU2O2UuaWRlb2dyYXBoaWNsZWZ0Y2lyY2xlPTEyOTY3O2UuaWRlb2dyYXBoaWNsb3djaXJjbGU9MTI5NjY7ZS5pZGVvZ3JhcGhpY21lZGljaW5lY2lyY2xlPTEyOTY5O2UuaWRlb2dyYXBoaWNtZXRhbHBhcmVuPTEyODQ2O2UuaWRlb2dyYXBoaWNtb29ucGFyZW49MTI4NDI7ZS5pZGVvZ3JhcGhpY25hbWVwYXJlbj0xMjg1MjtlLmlkZW9ncmFwaGljcGVyaW9kPTEyMjkwO2UuaWRlb2dyYXBoaWNwcmludGNpcmNsZT0xMjk1ODtlLmlkZW9ncmFwaGljcmVhY2hwYXJlbj0xMjg2NztlLmlkZW9ncmFwaGljcmVwcmVzZW50cGFyZW49MTI4NTc7ZS5pZGVvZ3JhcGhpY3Jlc291cmNlcGFyZW49MTI4NjI7ZS5pZGVvZ3JhcGhpY3JpZ2h0Y2lyY2xlPTEyOTY4O2UuaWRlb2dyYXBoaWNzZWNyZXRjaXJjbGU9MTI5NTM7ZS5pZGVvZ3JhcGhpY3NlbGZwYXJlbj0xMjg2NjtlLmlkZW9ncmFwaGljc29jaWV0eXBhcmVuPTEyODUxO2UuaWRlb2dyYXBoaWNzcGFjZT0xMjI4ODtlLmlkZW9ncmFwaGljc3BlY2lhbHBhcmVuPTEyODUzO2UuaWRlb2dyYXBoaWNzdG9ja3BhcmVuPTEyODQ5O2UuaWRlb2dyYXBoaWNzdHVkeXBhcmVuPTEyODU5O2UuaWRlb2dyYXBoaWNzdW5wYXJlbj0xMjg0ODtlLmlkZW9ncmFwaGljc3VwZXJ2aXNlcGFyZW49MTI4NjA7ZS5pZGVvZ3JhcGhpY3dhdGVycGFyZW49MTI4NDQ7ZS5pZGVvZ3JhcGhpY3dvb2RwYXJlbj0xMjg0NTtlLmlkZW9ncmFwaGljemVybz0xMjI5NTtlLmlkZW9ncmFwaG1ldGFsY2lyY2xlPTEyOTQyO2UuaWRlb2dyYXBobW9vbmNpcmNsZT0xMjkzODtlLmlkZW9ncmFwaG5hbWVjaXJjbGU9MTI5NDg7ZS5pZGVvZ3JhcGhzdW5jaXJjbGU9MTI5NDQ7ZS5pZGVvZ3JhcGh3YXRlcmNpcmNsZT0xMjk0MDtlLmlkZW9ncmFwaHdvb2RjaXJjbGU9MTI5NDE7ZS5pZGV2YT0yMzExO2UuaWRpZXJlc2lzPTIzOTtlLmlkaWVyZXNpc2FjdXRlPTc3Mjc7ZS5pZGllcmVzaXNjeXJpbGxpYz0xMjUzO2UuaWRvdGJlbG93PTc4ODM7ZS5pZWJyZXZlY3lyaWxsaWM9MTIzOTtlLmllY3lyaWxsaWM9MTA3NztlLmlldW5nYWNpcmNsZWtvcmVhbj0xMjkxNztlLmlldW5nYXBhcmVua29yZWFuPTEyODIxO2UuaWV1bmdjaXJjbGVrb3JlYW49MTI5MDM7ZS5pZXVuZ2tvcmVhbj0xMjYxNTtlLmlldW5ncGFyZW5rb3JlYW49MTI4MDc7ZS5pZ3JhdmU9MjM2O2UuaWd1amFyYXRpPTI2OTU7ZS5pZ3VybXVraGk9MjU2NztlLmloaXJhZ2FuYT0xMjM1NjtlLmlob29rYWJvdmU9Nzg4MTtlLmlpYmVuZ2FsaT0yNDQwO2UuaWljeXJpbGxpYz0xMDgwO2UuaWlkZXZhPTIzMTI7ZS5paWd1amFyYXRpPTI2OTY7ZS5paWd1cm11a2hpPTI1Njg7ZS5paW1hdHJhZ3VybXVraGk9MjYyNDtlLmlpbnZlcnRlZGJyZXZlPTUyMztlLmlpc2hvcnRjeXJpbGxpYz0xMDgxO2UuaWl2b3dlbHNpZ25iZW5nYWxpPTI0OTY7ZS5paXZvd2Vsc2lnbmRldmE9MjM2ODtlLmlpdm93ZWxzaWduZ3VqYXJhdGk9Mjc1MjtlLmlqPTMwNztlLmlrYXRha2FuYT0xMjQ1MjtlLmlrYXRha2FuYWhhbGZ3aWR0aD02NTM5NDtlLmlrb3JlYW49MTI2NDM7ZS5pbGRlPTczMjtlLmlsdXloZWJyZXc9MTQ1MjtlLmltYWNyb249Mjk5O2UuaW1hY3JvbmN5cmlsbGljPTEyNTE7ZS5pbWFnZW9yYXBwcm94aW1hdGVseWVxdWFsPTg3ODc7ZS5pbWF0cmFndXJtdWtoaT0yNjIzO2UuaW1vbm9zcGFjZT02NTM1MztlLmluY3JlbWVudD04NzEwO2UuaW5maW5pdHk9ODczNDtlLmluaWFybWVuaWFuPTEzODc7ZS5pbnRlZ3JhbD04NzQ3O2UuaW50ZWdyYWxib3R0b209ODk5MztlLmludGVncmFsYnQ9ODk5MztlLmludGVncmFsZXg9NjM3MzM7ZS5pbnRlZ3JhbHRvcD04OTkyO2UuaW50ZWdyYWx0cD04OTkyO2UuaW50ZXJzZWN0aW9uPTg3NDU7ZS5pbnRpc3F1YXJlPTEzMDYxO2UuaW52YnVsbGV0PTk2ODg7ZS5pbnZjaXJjbGU9OTY4OTtlLmludnNtaWxlZmFjZT05Nzg3O2UuaW9jeXJpbGxpYz0xMTA1O2UuaW9nb25laz0zMDM7ZS5pb3RhPTk1MztlLmlvdGFkaWVyZXNpcz05NzA7ZS5pb3RhZGllcmVzaXN0b25vcz05MTI7ZS5pb3RhbGF0aW49NjE3O2UuaW90YXRvbm9zPTk0MztlLmlwYXJlbj05MzgwO2UuaXJpZ3VybXVraGk9MjY3NDtlLmlzbWFsbGhpcmFnYW5hPTEyMzU1O2UuaXNtYWxsa2F0YWthbmE9MTI0NTE7ZS5pc21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM4NDtlLmlzc2hhcmJlbmdhbGk9MjU1NDtlLmlzdHJva2U9NjE2O2UuaXN1cGVyaW9yPTYzMjEzO2UuaXRlcmF0aW9uaGlyYWdhbmE9MTI0NDU7ZS5pdGVyYXRpb25rYXRha2FuYT0xMjU0MTtlLml0aWxkZT0yOTc7ZS5pdGlsZGViZWxvdz03NzI1O2UuaXVib3BvbW9mbz0xMjU4NTtlLml1Y3lyaWxsaWM9MTEwMjtlLml2b3dlbHNpZ25iZW5nYWxpPTI0OTU7ZS5pdm93ZWxzaWduZGV2YT0yMzY3O2UuaXZvd2Vsc2lnbmd1amFyYXRpPTI3NTE7ZS5pemhpdHNhY3lyaWxsaWM9MTE0MTtlLml6aGl0c2FkYmxncmF2ZWN5cmlsbGljPTExNDM7ZS5qPTEwNjtlLmphYXJtZW5pYW49MTM5MztlLmphYmVuZ2FsaT0yNDYwO2UuamFkZXZhPTIzMzI7ZS5qYWd1amFyYXRpPTI3MTY7ZS5qYWd1cm11a2hpPTI1ODg7ZS5qYm9wb21vZm89MTI1NjA7ZS5qY2Fyb249NDk2O2UuamNpcmNsZT05NDMzO2UuamNpcmN1bWZsZXg9MzA5O2UuamNyb3NzZWR0YWlsPTY2OTtlLmpkb3RsZXNzc3Ryb2tlPTYwNztlLmplY3lyaWxsaWM9MTExMjtlLmplZW1hcmFiaWM9MTU4MDtlLmplZW1maW5hbGFyYWJpYz02NTE4MjtlLmplZW1pbml0aWFsYXJhYmljPTY1MTgzO2UuamVlbW1lZGlhbGFyYWJpYz02NTE4NDtlLmplaGFyYWJpYz0xNjg4O2UuamVoZmluYWxhcmFiaWM9NjQzOTU7ZS5qaGFiZW5nYWxpPTI0NjE7ZS5qaGFkZXZhPTIzMzM7ZS5qaGFndWphcmF0aT0yNzE3O2UuamhhZ3VybXVraGk9MjU4OTtlLmpoZWhhcm1lbmlhbj0xNDAzO2UuamlzPTEyMjkyO2Uuam1vbm9zcGFjZT02NTM1NDtlLmpwYXJlbj05MzgxO2UuanN1cGVyaW9yPTY5MDtlLms9MTA3O2Uua2FiYXNoa2lyY3lyaWxsaWM9MTE4NTtlLmthYmVuZ2FsaT0yNDUzO2Uua2FjdXRlPTc3Mjk7ZS5rYWN5cmlsbGljPTEwODI7ZS5rYWRlc2NlbmRlcmN5cmlsbGljPTExNzk7ZS5rYWRldmE9MjMyNTtlLmthZj0xNDk5O2Uua2FmYXJhYmljPTE2MDM7ZS5rYWZkYWdlc2g9NjQzMTU7ZS5rYWZkYWdlc2hoZWJyZXc9NjQzMTU7ZS5rYWZmaW5hbGFyYWJpYz02NTI0MjtlLmthZmhlYnJldz0xNDk5O2Uua2FmaW5pdGlhbGFyYWJpYz02NTI0MztlLmthZm1lZGlhbGFyYWJpYz02NTI0NDtlLmthZnJhZmVoZWJyZXc9NjQzMzM7ZS5rYWd1amFyYXRpPTI3MDk7ZS5rYWd1cm11a2hpPTI1ODE7ZS5rYWhpcmFnYW5hPTEyMzYzO2Uua2Fob29rY3lyaWxsaWM9MTIyMDtlLmtha2F0YWthbmE9MTI0NTk7ZS5rYWthdGFrYW5haGFsZndpZHRoPTY1Mzk4O2Uua2FwcGE9OTU0O2Uua2FwcGFzeW1ib2xncmVlaz0xMDA4O2Uua2FweWVvdW5taWV1bWtvcmVhbj0xMjY1NztlLmthcHllb3VucGhpZXVwaGtvcmVhbj0xMjY3NjtlLmthcHllb3VucGlldXBrb3JlYW49MTI2NjQ7ZS5rYXB5ZW91bnNzYW5ncGlldXBrb3JlYW49MTI2NjU7ZS5rYXJvcmlpc3F1YXJlPTEzMDY5O2Uua2FzaGlkYWF1dG9hcmFiaWM9MTYwMDtlLmthc2hpZGFhdXRvbm9zaWRlYmVhcmluZ2FyYWJpYz0xNjAwO2Uua2FzbWFsbGthdGFrYW5hPTEyNTMzO2Uua2FzcXVhcmU9MTMxODg7ZS5rYXNyYWFyYWJpYz0xNjE2O2Uua2FzcmF0YW5hcmFiaWM9MTYxMztlLmthc3Ryb2tlY3lyaWxsaWM9MTE4MztlLmthdGFoaXJhcHJvbG9uZ21hcmtoYWxmd2lkdGg9NjUzOTI7ZS5rYXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWM9MTE4MTtlLmtib3BvbW9mbz0xMjU1ODtlLmtjYWxzcXVhcmU9MTMxOTM7ZS5rY2Fyb249NDg5O2Uua2NlZGlsbGE9MzExO2Uua2NpcmNsZT05NDM0O2Uua2NvbW1hYWNjZW50PTMxMTtlLmtkb3RiZWxvdz03NzMxO2Uua2VoYXJtZW5pYW49MTQxMjtlLmtlaGlyYWdhbmE9MTIzNjk7ZS5rZWthdGFrYW5hPTEyNDY1O2Uua2VrYXRha2FuYWhhbGZ3aWR0aD02NTQwMTtlLmtlbmFybWVuaWFuPTEzOTE7ZS5rZXNtYWxsa2F0YWthbmE9MTI1MzQ7ZS5rZ3JlZW5sYW5kaWM9MzEyO2Uua2hhYmVuZ2FsaT0yNDU0O2Uua2hhY3lyaWxsaWM9MTA5MztlLmtoYWRldmE9MjMyNjtlLmtoYWd1amFyYXRpPTI3MTA7ZS5raGFndXJtdWtoaT0yNTgyO2Uua2hhaGFyYWJpYz0xNTgyO2Uua2hhaGZpbmFsYXJhYmljPTY1MTkwO2Uua2hhaGluaXRpYWxhcmFiaWM9NjUxOTE7ZS5raGFobWVkaWFsYXJhYmljPTY1MTkyO2Uua2hlaWNvcHRpYz05OTk7ZS5raGhhZGV2YT0yMzkzO2Uua2hoYWd1cm11a2hpPTI2NDk7ZS5raGlldWtoYWNpcmNsZWtvcmVhbj0xMjkyMDtlLmtoaWV1a2hhcGFyZW5rb3JlYW49MTI4MjQ7ZS5raGlldWtoY2lyY2xla29yZWFuPTEyOTA2O2Uua2hpZXVraGtvcmVhbj0xMjYxOTtlLmtoaWV1a2hwYXJlbmtvcmVhbj0xMjgxMDtlLmtob2toYWl0aGFpPTM1ODY7ZS5raG9raG9udGhhaT0zNTg5O2Uua2hva2h1YXR0aGFpPTM1ODc7ZS5raG9raHdhaXRoYWk9MzU4ODtlLmtob211dHRoYWk9MzY3NTtlLmtob29rPTQwOTtlLmtob3Jha2hhbmd0aGFpPTM1OTA7ZS5raHpzcXVhcmU9MTMyMDE7ZS5raWhpcmFnYW5hPTEyMzY1O2Uua2lrYXRha2FuYT0xMjQ2MTtlLmtpa2F0YWthbmFoYWxmd2lkdGg9NjUzOTk7ZS5raXJvZ3VyYW11c3F1YXJlPTEzMDc3O2Uua2lyb21lZXRvcnVzcXVhcmU9MTMwNzg7ZS5raXJvc3F1YXJlPTEzMDc2O2Uua2l5ZW9rYWNpcmNsZWtvcmVhbj0xMjkxMDtlLmtpeWVva2FwYXJlbmtvcmVhbj0xMjgxNDtlLmtpeWVva2NpcmNsZWtvcmVhbj0xMjg5NjtlLmtpeWVva2tvcmVhbj0xMjU5MztlLmtpeWVva3BhcmVua29yZWFuPTEyODAwO2Uua2l5ZW9rc2lvc2tvcmVhbj0xMjU5NTtlLmtqZWN5cmlsbGljPTExMTY7ZS5rbGluZWJlbG93PTc3MzM7ZS5rbHNxdWFyZT0xMzIwODtlLmttY3ViZWRzcXVhcmU9MTMyMjI7ZS5rbW9ub3NwYWNlPTY1MzU1O2Uua21zcXVhcmVkc3F1YXJlPTEzMjE4O2Uua29oaXJhZ2FuYT0xMjM3MTtlLmtvaG1zcXVhcmU9MTMyNDg7ZS5rb2thaXRoYWk9MzU4NTtlLmtva2F0YWthbmE9MTI0Njc7ZS5rb2thdGFrYW5haGFsZndpZHRoPTY1NDAyO2Uua29vcG9zcXVhcmU9MTMwODY7ZS5rb3BwYWN5cmlsbGljPTExNTM7ZS5rb3JlYW5zdGFuZGFyZHN5bWJvbD0xMjkyNztlLmtvcm9uaXNjbWI9ODM1O2Uua3BhcmVuPTkzODI7ZS5rcGFzcXVhcmU9MTMyMjY7ZS5rc2ljeXJpbGxpYz0xMTM1O2Uua3RzcXVhcmU9MTMyNjM7ZS5rdHVybmVkPTY3MDtlLmt1aGlyYWdhbmE9MTIzNjc7ZS5rdWthdGFrYW5hPTEyNDYzO2Uua3VrYXRha2FuYWhhbGZ3aWR0aD02NTQwMDtlLmt2c3F1YXJlPTEzMjQwO2Uua3dzcXVhcmU9MTMyNDY7ZS5sPTEwODtlLmxhYmVuZ2FsaT0yNDgyO2UubGFjdXRlPTMxNDtlLmxhZGV2YT0yMzU0O2UubGFndWphcmF0aT0yNzM4O2UubGFndXJtdWtoaT0yNjEwO2UubGFra2hhbmd5YW90aGFpPTM2NTM7ZS5sYW1hbGVmZmluYWxhcmFiaWM9NjUyNzY7ZS5sYW1hbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljPTY1MjcyO2UubGFtYWxlZmhhbXphYWJvdmVpc29sYXRlZGFyYWJpYz02NTI3MTtlLmxhbWFsZWZoYW16YWJlbG93ZmluYWxhcmFiaWM9NjUyNzQ7ZS5sYW1hbGVmaGFtemFiZWxvd2lzb2xhdGVkYXJhYmljPTY1MjczO2UubGFtYWxlZmlzb2xhdGVkYXJhYmljPTY1Mjc1O2UubGFtYWxlZm1hZGRhYWJvdmVmaW5hbGFyYWJpYz02NTI3MDtlLmxhbWFsZWZtYWRkYWFib3ZlaXNvbGF0ZWRhcmFiaWM9NjUyNjk7ZS5sYW1hcmFiaWM9MTYwNDtlLmxhbWJkYT05NTU7ZS5sYW1iZGFzdHJva2U9NDExO2UubGFtZWQ9MTUwMDtlLmxhbWVkZGFnZXNoPTY0MzE2O2UubGFtZWRkYWdlc2hoZWJyZXc9NjQzMTY7ZS5sYW1lZGhlYnJldz0xNTAwO2UubGFtZmluYWxhcmFiaWM9NjUyNDY7ZS5sYW1oYWhpbml0aWFsYXJhYmljPTY0NzE0O2UubGFtaW5pdGlhbGFyYWJpYz02NTI0NztlLmxhbWplZW1pbml0aWFsYXJhYmljPTY0NzEzO2UubGFta2hhaGluaXRpYWxhcmFiaWM9NjQ3MTU7ZS5sYW1sYW1oZWhpc29sYXRlZGFyYWJpYz02NTAxMDtlLmxhbW1lZGlhbGFyYWJpYz02NTI0ODtlLmxhbW1lZW1oYWhpbml0aWFsYXJhYmljPTY0OTA0O2UubGFtbWVlbWluaXRpYWxhcmFiaWM9NjQ3MTY7ZS5sYXJnZWNpcmNsZT05NzExO2UubGJhcj00MTA7ZS5sYmVsdD02MjA7ZS5sYm9wb21vZm89MTI1NTY7ZS5sY2Fyb249MzE4O2UubGNlZGlsbGE9MzE2O2UubGNpcmNsZT05NDM1O2UubGNpcmN1bWZsZXhiZWxvdz03NzQxO2UubGNvbW1hYWNjZW50PTMxNjtlLmxkb3Q9MzIwO2UubGRvdGFjY2VudD0zMjA7ZS5sZG90YmVsb3c9NzczNTtlLmxkb3RiZWxvd21hY3Jvbj03NzM3O2UubGVmdGFuZ2xlYWJvdmVjbWI9Nzk0O2UubGVmdHRhY2tiZWxvd2NtYj03OTI7ZS5sZXNzPTYwO2UubGVzc2VxdWFsPTg4MDQ7ZS5sZXNzZXF1YWxvcmdyZWF0ZXI9ODkyMjtlLmxlc3Ntb25vc3BhY2U9NjUzMDg7ZS5sZXNzb3JlcXVpdmFsZW50PTg4MTg7ZS5sZXNzb3JncmVhdGVyPTg4MjI7ZS5sZXNzb3ZlcmVxdWFsPTg4MDY7ZS5sZXNzc21hbGw9NjUxMjQ7ZS5sZXpoPTYyMjtlLmxmYmxvY2s9OTYxMjtlLmxob29rcmV0cm9mbGV4PTYyMTtlLmxpcmE9ODM1NjtlLmxpd25hcm1lbmlhbj0xMzg4O2UubGo9NDU3O2UubGplY3lyaWxsaWM9MTExMztlLmxsPTYzMTY4O2UubGxhZGV2YT0yMzU1O2UubGxhZ3VqYXJhdGk9MjczOTtlLmxsaW5lYmVsb3c9NzczOTtlLmxsbGFkZXZhPTIzNTY7ZS5sbHZvY2FsaWNiZW5nYWxpPTI1Mjk7ZS5sbHZvY2FsaWNkZXZhPTI0MDE7ZS5sbHZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpPTI1MzE7ZS5sbHZvY2FsaWN2b3dlbHNpZ25kZXZhPTI0MDM7ZS5sbWlkZGxldGlsZGU9NjE5O2UubG1vbm9zcGFjZT02NTM1NjtlLmxtc3F1YXJlPTEzMjY0O2UubG9jaHVsYXRoYWk9MzYyODtlLmxvZ2ljYWxhbmQ9ODc0MztlLmxvZ2ljYWxub3Q9MTcyO2UubG9naWNhbG5vdHJldmVyc2VkPTg5NzY7ZS5sb2dpY2Fsb3I9ODc0NDtlLmxvbGluZ3RoYWk9MzYyMTtlLmxvbmdzPTM4MztlLmxvd2xpbmVjZW50ZXJsaW5lPTY1MTAyO2UubG93bGluZWNtYj04MTg7ZS5sb3dsaW5lZGFzaGVkPTY1MTAxO2UubG96ZW5nZT05Njc0O2UubHBhcmVuPTkzODM7ZS5sc2xhc2g9MzIyO2UubHNxdWFyZT04NDY3O2UubHN1cGVyaW9yPTYzMjE0O2UubHRzaGFkZT05NjE3O2UubHV0aGFpPTM2MjI7ZS5sdm9jYWxpY2JlbmdhbGk9MjQ0NDtlLmx2b2NhbGljZGV2YT0yMzE2O2UubHZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpPTI1MzA7ZS5sdm9jYWxpY3Zvd2Vsc2lnbmRldmE9MjQwMjtlLmx4c3F1YXJlPTEzMjY3O2UubT0xMDk7ZS5tYWJlbmdhbGk9MjQ3ODtlLm1hY3Jvbj0xNzU7ZS5tYWNyb25iZWxvd2NtYj04MTc7ZS5tYWNyb25jbWI9NzcyO2UubWFjcm9ubG93bW9kPTcxNztlLm1hY3Jvbm1vbm9zcGFjZT02NTUwNztlLm1hY3V0ZT03NzQzO2UubWFkZXZhPTIzNTA7ZS5tYWd1amFyYXRpPTI3MzQ7ZS5tYWd1cm11a2hpPTI2MDY7ZS5tYWhhcGFraGhlYnJldz0xNDQ0O2UubWFoYXBha2hsZWZ0aGVicmV3PTE0NDQ7ZS5tYWhpcmFnYW5hPTEyNDE0O2UubWFpY2hhdHRhd2Fsb3dsZWZ0dGhhaT02MzYzNztlLm1haWNoYXR0YXdhbG93cmlnaHR0aGFpPTYzNjM2O2UubWFpY2hhdHRhd2F0aGFpPTM2NTk7ZS5tYWljaGF0dGF3YXVwcGVybGVmdHRoYWk9NjM2MzU7ZS5tYWlla2xvd2xlZnR0aGFpPTYzNjI4O2UubWFpZWtsb3dyaWdodHRoYWk9NjM2Mjc7ZS5tYWlla3RoYWk9MzY1NjtlLm1haWVrdXBwZXJsZWZ0dGhhaT02MzYyNjtlLm1haWhhbmFrYXRsZWZ0dGhhaT02MzYyMDtlLm1haWhhbmFrYXR0aGFpPTM2MzM7ZS5tYWl0YWlraHVsZWZ0dGhhaT02MzYyNTtlLm1haXRhaWtodXRoYWk9MzY1NTtlLm1haXRob2xvd2xlZnR0aGFpPTYzNjMxO2UubWFpdGhvbG93cmlnaHR0aGFpPTYzNjMwO2UubWFpdGhvdGhhaT0zNjU3O2UubWFpdGhvdXBwZXJsZWZ0dGhhaT02MzYyOTtlLm1haXRyaWxvd2xlZnR0aGFpPTYzNjM0O2UubWFpdHJpbG93cmlnaHR0aGFpPTYzNjMzO2UubWFpdHJpdGhhaT0zNjU4O2UubWFpdHJpdXBwZXJsZWZ0dGhhaT02MzYzMjtlLm1haXlhbW9rdGhhaT0zNjU0O2UubWFrYXRha2FuYT0xMjUxMDtlLm1ha2F0YWthbmFoYWxmd2lkdGg9NjU0MjM7ZS5tYWxlPTk3OTQ7ZS5tYW5zeW9uc3F1YXJlPTEzMTI3O2UubWFxYWZoZWJyZXc9MTQ3MDtlLm1hcnM9OTc5NDtlLm1hc29yYWNpcmNsZWhlYnJldz0xNDU1O2UubWFzcXVhcmU9MTMxODc7ZS5tYm9wb21vZm89MTI1NTE7ZS5tYnNxdWFyZT0xMzI2ODtlLm1jaXJjbGU9OTQzNjtlLm1jdWJlZHNxdWFyZT0xMzIyMTtlLm1kb3RhY2NlbnQ9Nzc0NTtlLm1kb3RiZWxvdz03NzQ3O2UubWVlbWFyYWJpYz0xNjA1O2UubWVlbWZpbmFsYXJhYmljPTY1MjUwO2UubWVlbWluaXRpYWxhcmFiaWM9NjUyNTE7ZS5tZWVtbWVkaWFsYXJhYmljPTY1MjUyO2UubWVlbW1lZW1pbml0aWFsYXJhYmljPTY0NzIxO2UubWVlbW1lZW1pc29sYXRlZGFyYWJpYz02NDU4NDtlLm1lZXRvcnVzcXVhcmU9MTMxMzM7ZS5tZWhpcmFnYW5hPTEyNDE3O2UubWVpemllcmFzcXVhcmU9MTMxODI7ZS5tZWthdGFrYW5hPTEyNTEzO2UubWVrYXRha2FuYWhhbGZ3aWR0aD02NTQyNjtlLm1lbT0xNTAyO2UubWVtZGFnZXNoPTY0MzE4O2UubWVtZGFnZXNoaGVicmV3PTY0MzE4O2UubWVtaGVicmV3PTE1MDI7ZS5tZW5hcm1lbmlhbj0xMzk2O2UubWVya2hhaGVicmV3PTE0NDU7ZS5tZXJraGFrZWZ1bGFoZWJyZXc9MTQ0NjtlLm1lcmtoYWtlZnVsYWxlZnRoZWJyZXc9MTQ0NjtlLm1lcmtoYWxlZnRoZWJyZXc9MTQ0NTtlLm1ob29rPTYyNTtlLm1oenNxdWFyZT0xMzIwMjtlLm1pZGRsZWRvdGthdGFrYW5haGFsZndpZHRoPTY1MzgxO2UubWlkZG90PTE4MztlLm1pZXVtYWNpcmNsZWtvcmVhbj0xMjkxNDtlLm1pZXVtYXBhcmVua29yZWFuPTEyODE4O2UubWlldW1jaXJjbGVrb3JlYW49MTI5MDA7ZS5taWV1bWtvcmVhbj0xMjYwOTtlLm1pZXVtcGFuc2lvc2tvcmVhbj0xMjY1NjtlLm1pZXVtcGFyZW5rb3JlYW49MTI4MDQ7ZS5taWV1bXBpZXVwa29yZWFuPTEyNjU0O2UubWlldW1zaW9za29yZWFuPTEyNjU1O2UubWloaXJhZ2FuYT0xMjQxNTtlLm1pa2F0YWthbmE9MTI1MTE7ZS5taWthdGFrYW5haGFsZndpZHRoPTY1NDI0O2UubWludXM9ODcyMjtlLm1pbnVzYmVsb3djbWI9ODAwO2UubWludXNjaXJjbGU9ODg1NDtlLm1pbnVzbW9kPTcyNztlLm1pbnVzcGx1cz04NzIzO2UubWludXRlPTgyNDI7ZS5taXJpYmFhcnVzcXVhcmU9MTMxMzA7ZS5taXJpc3F1YXJlPTEzMTI5O2UubWxvbmdsZWd0dXJuZWQ9NjI0O2UubWxzcXVhcmU9MTMyMDY7ZS5tbWN1YmVkc3F1YXJlPTEzMjE5O2UubW1vbm9zcGFjZT02NTM1NztlLm1tc3F1YXJlZHNxdWFyZT0xMzIxNTtlLm1vaGlyYWdhbmE9MTI0MTg7ZS5tb2htc3F1YXJlPTEzMjQ5O2UubW9rYXRha2FuYT0xMjUxNDtlLm1va2F0YWthbmFoYWxmd2lkdGg9NjU0Mjc7ZS5tb2xzcXVhcmU9MTMyNzA7ZS5tb21hdGhhaT0zNjE3O2UubW92ZXJzc3F1YXJlPTEzMjIzO2UubW92ZXJzc3F1YXJlZHNxdWFyZT0xMzIyNDtlLm1wYXJlbj05Mzg0O2UubXBhc3F1YXJlPTEzMjI3O2UubXNzcXVhcmU9MTMyMzU7ZS5tc3VwZXJpb3I9NjMyMTU7ZS5tdHVybmVkPTYyMztlLm11PTE4MTtlLm11MT0xODE7ZS5tdWFzcXVhcmU9MTMxODY7ZS5tdWNoZ3JlYXRlcj04ODExO2UubXVjaGxlc3M9ODgxMDtlLm11ZnNxdWFyZT0xMzE5NjtlLm11Z3JlZWs9OTU2O2UubXVnc3F1YXJlPTEzMTk3O2UubXVoaXJhZ2FuYT0xMjQxNjtlLm11a2F0YWthbmE9MTI1MTI7ZS5tdWthdGFrYW5haGFsZndpZHRoPTY1NDI1O2UubXVsc3F1YXJlPTEzMjA1O2UubXVsdGlwbHk9MjE1O2UubXVtc3F1YXJlPTEzMjExO2UubXVuYWhoZWJyZXc9MTQ0MztlLm11bmFobGVmdGhlYnJldz0xNDQzO2UubXVzaWNhbG5vdGU9OTgzNDtlLm11c2ljYWxub3RlZGJsPTk4MzU7ZS5tdXNpY2ZsYXRzaWduPTk4Mzc7ZS5tdXNpY3NoYXJwc2lnbj05ODM5O2UubXVzc3F1YXJlPTEzMjM0O2UubXV2c3F1YXJlPTEzMjM4O2UubXV3c3F1YXJlPTEzMjQ0O2UubXZtZWdhc3F1YXJlPTEzMjQxO2UubXZzcXVhcmU9MTMyMzk7ZS5td21lZ2FzcXVhcmU9MTMyNDc7ZS5td3NxdWFyZT0xMzI0NTtlLm49MTEwO2UubmFiZW5nYWxpPTI0NzI7ZS5uYWJsYT04NzExO2UubmFjdXRlPTMyNDtlLm5hZGV2YT0yMzQ0O2UubmFndWphcmF0aT0yNzI4O2UubmFndXJtdWtoaT0yNjAwO2UubmFoaXJhZ2FuYT0xMjM5NDtlLm5ha2F0YWthbmE9MTI0OTA7ZS5uYWthdGFrYW5haGFsZndpZHRoPTY1NDEzO2UubmFwb3N0cm9waGU9MzI5O2UubmFzcXVhcmU9MTMxODU7ZS5uYm9wb21vZm89MTI1NTU7ZS5uYnNwYWNlPTE2MDtlLm5jYXJvbj0zMjg7ZS5uY2VkaWxsYT0zMjY7ZS5uY2lyY2xlPTk0Mzc7ZS5uY2lyY3VtZmxleGJlbG93PTc3NTU7ZS5uY29tbWFhY2NlbnQ9MzI2O2UubmRvdGFjY2VudD03NzQ5O2UubmRvdGJlbG93PTc3NTE7ZS5uZWhpcmFnYW5hPTEyMzk3O2UubmVrYXRha2FuYT0xMjQ5MztlLm5la2F0YWthbmFoYWxmd2lkdGg9NjU0MTY7ZS5uZXdzaGVxZWxzaWduPTgzNjI7ZS5uZnNxdWFyZT0xMzE5NTtlLm5nYWJlbmdhbGk9MjQ1NztlLm5nYWRldmE9MjMyOTtlLm5nYWd1amFyYXRpPTI3MTM7ZS5uZ2FndXJtdWtoaT0yNTg1O2Uubmdvbmd1dGhhaT0zNTkxO2UubmhpcmFnYW5hPTEyNDM1O2Uubmhvb2tsZWZ0PTYyNjtlLm5ob29rcmV0cm9mbGV4PTYyNztlLm5pZXVuYWNpcmNsZWtvcmVhbj0xMjkxMTtlLm5pZXVuYXBhcmVua29yZWFuPTEyODE1O2UubmlldW5jaWV1Y2tvcmVhbj0xMjU5NztlLm5pZXVuY2lyY2xla29yZWFuPTEyODk3O2UubmlldW5oaWV1aGtvcmVhbj0xMjU5ODtlLm5pZXVua29yZWFuPTEyNTk2O2UubmlldW5wYW5zaW9za29yZWFuPTEyNjQ4O2UubmlldW5wYXJlbmtvcmVhbj0xMjgwMTtlLm5pZXVuc2lvc2tvcmVhbj0xMjY0NztlLm5pZXVudGlrZXV0a29yZWFuPTEyNjQ2O2UubmloaXJhZ2FuYT0xMjM5NTtlLm5pa2F0YWthbmE9MTI0OTE7ZS5uaWthdGFrYW5haGFsZndpZHRoPTY1NDE0O2UubmlraGFoaXRsZWZ0dGhhaT02MzY0MTtlLm5pa2hhaGl0dGhhaT0zNjYxO2UubmluZT01NztlLm5pbmVhcmFiaWM9MTY0MTtlLm5pbmViZW5nYWxpPTI1NDM7ZS5uaW5lY2lyY2xlPTkzMjA7ZS5uaW5lY2lyY2xlaW52ZXJzZXNhbnNzZXJpZj0xMDEzMDtlLm5pbmVkZXZhPTI0MTU7ZS5uaW5lZ3VqYXJhdGk9Mjc5OTtlLm5pbmVndXJtdWtoaT0yNjcxO2UubmluZWhhY2thcmFiaWM9MTY0MTtlLm5pbmVoYW5nemhvdT0xMjMyOTtlLm5pbmVpZGVvZ3JhcGhpY3BhcmVuPTEyODQwO2UubmluZWluZmVyaW9yPTgzMjk7ZS5uaW5lbW9ub3NwYWNlPTY1MzA1O2UubmluZW9sZHN0eWxlPTYzMjg5O2UubmluZXBhcmVuPTkzNDA7ZS5uaW5lcGVyaW9kPTkzNjA7ZS5uaW5lcGVyc2lhbj0xNzg1O2UubmluZXJvbWFuPTg1Njg7ZS5uaW5lc3VwZXJpb3I9ODMxMztlLm5pbmV0ZWVuY2lyY2xlPTkzMzA7ZS5uaW5ldGVlbnBhcmVuPTkzNTA7ZS5uaW5ldGVlbnBlcmlvZD05MzcwO2UubmluZXRoYWk9MzY3MztlLm5qPTQ2MDtlLm5qZWN5cmlsbGljPTExMTQ7ZS5ua2F0YWthbmE9MTI1MzE7ZS5ua2F0YWthbmFoYWxmd2lkdGg9NjU0Mzc7ZS5ubGVncmlnaHRsb25nPTQxNDtlLm5saW5lYmVsb3c9Nzc1MztlLm5tb25vc3BhY2U9NjUzNTg7ZS5ubXNxdWFyZT0xMzIxMDtlLm5uYWJlbmdhbGk9MjQ2NztlLm5uYWRldmE9MjMzOTtlLm5uYWd1amFyYXRpPTI3MjM7ZS5ubmFndXJtdWtoaT0yNTk1O2Uubm5uYWRldmE9MjM0NTtlLm5vaGlyYWdhbmE9MTIzOTg7ZS5ub2thdGFrYW5hPTEyNDk0O2Uubm9rYXRha2FuYWhhbGZ3aWR0aD02NTQxNztlLm5vbmJyZWFraW5nc3BhY2U9MTYwO2Uubm9uZW50aGFpPTM2MDM7ZS5ub251dGhhaT0zNjA5O2Uubm9vbmFyYWJpYz0xNjA2O2Uubm9vbmZpbmFsYXJhYmljPTY1MjU0O2Uubm9vbmdodW5uYWFyYWJpYz0xNzIyO2Uubm9vbmdodW5uYWZpbmFsYXJhYmljPTY0NDE1O2Uubm9vbmluaXRpYWxhcmFiaWM9NjUyNTU7ZS5ub29uamVlbWluaXRpYWxhcmFiaWM9NjQ3MjI7ZS5ub29uamVlbWlzb2xhdGVkYXJhYmljPTY0NTg3O2Uubm9vbm1lZGlhbGFyYWJpYz02NTI1NjtlLm5vb25tZWVtaW5pdGlhbGFyYWJpYz02NDcyNTtlLm5vb25tZWVtaXNvbGF0ZWRhcmFiaWM9NjQ1OTA7ZS5ub29ubm9vbmZpbmFsYXJhYmljPTY0NjUzO2Uubm90Y29udGFpbnM9ODcxNjtlLm5vdGVsZW1lbnQ9ODcxMztlLm5vdGVsZW1lbnRvZj04NzEzO2Uubm90ZXF1YWw9ODgwMDtlLm5vdGdyZWF0ZXI9ODgxNTtlLm5vdGdyZWF0ZXJub3JlcXVhbD04ODE3O2Uubm90Z3JlYXRlcm5vcmxlc3M9ODgyNTtlLm5vdGlkZW50aWNhbD04ODAyO2Uubm90bGVzcz04ODE0O2Uubm90bGVzc25vcmVxdWFsPTg4MTY7ZS5ub3RwYXJhbGxlbD04NzQyO2Uubm90cHJlY2VkZXM9ODgzMjtlLm5vdHN1YnNldD04ODM2O2Uubm90c3VjY2VlZHM9ODgzMztlLm5vdHN1cGVyc2V0PTg4Mzc7ZS5ub3dhcm1lbmlhbj0xMzk4O2UubnBhcmVuPTkzODU7ZS5uc3NxdWFyZT0xMzIzMztlLm5zdXBlcmlvcj04MzE5O2UubnRpbGRlPTI0MTtlLm51PTk1NztlLm51aGlyYWdhbmE9MTIzOTY7ZS5udWthdGFrYW5hPTEyNDkyO2UubnVrYXRha2FuYWhhbGZ3aWR0aD02NTQxNTtlLm51a3RhYmVuZ2FsaT0yNDkyO2UubnVrdGFkZXZhPTIzNjQ7ZS5udWt0YWd1amFyYXRpPTI3NDg7ZS5udWt0YWd1cm11a2hpPTI2MjA7ZS5udW1iZXJzaWduPTM1O2UubnVtYmVyc2lnbm1vbm9zcGFjZT02NTI4MztlLm51bWJlcnNpZ25zbWFsbD02NTExOTtlLm51bWVyYWxzaWduZ3JlZWs9ODg0O2UubnVtZXJhbHNpZ25sb3dlcmdyZWVrPTg4NTtlLm51bWVybz04NDcwO2UubnVuPTE1MDQ7ZS5udW5kYWdlc2g9NjQzMjA7ZS5udW5kYWdlc2hoZWJyZXc9NjQzMjA7ZS5udW5oZWJyZXc9MTUwNDtlLm52c3F1YXJlPTEzMjM3O2UubndzcXVhcmU9MTMyNDM7ZS5ueWFiZW5nYWxpPTI0NjI7ZS5ueWFkZXZhPTIzMzQ7ZS5ueWFndWphcmF0aT0yNzE4O2UubnlhZ3VybXVraGk9MjU5MDtlLm89MTExO2Uub2FjdXRlPTI0MztlLm9hbmd0aGFpPTM2Mjk7ZS5vYmFycmVkPTYyOTtlLm9iYXJyZWRjeXJpbGxpYz0xMjU3O2Uub2JhcnJlZGRpZXJlc2lzY3lyaWxsaWM9MTI1OTtlLm9iZW5nYWxpPTI0NTE7ZS5vYm9wb21vZm89MTI1NzE7ZS5vYnJldmU9MzM1O2Uub2NhbmRyYWRldmE9MjMyMTtlLm9jYW5kcmFndWphcmF0aT0yNzA1O2Uub2NhbmRyYXZvd2Vsc2lnbmRldmE9MjM3NztlLm9jYW5kcmF2b3dlbHNpZ25ndWphcmF0aT0yNzYxO2Uub2Nhcm9uPTQ2NjtlLm9jaXJjbGU9OTQzODtlLm9jaXJjdW1mbGV4PTI0NDtlLm9jaXJjdW1mbGV4YWN1dGU9Nzg4OTtlLm9jaXJjdW1mbGV4ZG90YmVsb3c9Nzg5NztlLm9jaXJjdW1mbGV4Z3JhdmU9Nzg5MTtlLm9jaXJjdW1mbGV4aG9va2Fib3ZlPTc4OTM7ZS5vY2lyY3VtZmxleHRpbGRlPTc4OTU7ZS5vY3lyaWxsaWM9MTA4NjtlLm9kYmxhY3V0ZT0zMzc7ZS5vZGJsZ3JhdmU9NTI1O2Uub2RldmE9MjMyMztlLm9kaWVyZXNpcz0yNDY7ZS5vZGllcmVzaXNjeXJpbGxpYz0xMjU1O2Uub2RvdGJlbG93PTc4ODU7ZS5vZT0zMzk7ZS5vZWtvcmVhbj0xMjYzNDtlLm9nb25laz03MzE7ZS5vZ29uZWtjbWI9ODA4O2Uub2dyYXZlPTI0MjtlLm9ndWphcmF0aT0yNzA3O2Uub2hhcm1lbmlhbj0xNDEzO2Uub2hpcmFnYW5hPTEyMzYyO2Uub2hvb2thYm92ZT03ODg3O2Uub2hvcm49NDE3O2Uub2hvcm5hY3V0ZT03ODk5O2Uub2hvcm5kb3RiZWxvdz03OTA3O2Uub2hvcm5ncmF2ZT03OTAxO2Uub2hvcm5ob29rYWJvdmU9NzkwMztlLm9ob3JudGlsZGU9NzkwNTtlLm9odW5nYXJ1bWxhdXQ9MzM3O2Uub2k9NDE5O2Uub2ludmVydGVkYnJldmU9NTI3O2Uub2thdGFrYW5hPTEyNDU4O2Uub2thdGFrYW5haGFsZndpZHRoPTY1Mzk3O2Uub2tvcmVhbj0xMjYzMTtlLm9sZWhlYnJldz0xNDUxO2Uub21hY3Jvbj0zMzM7ZS5vbWFjcm9uYWN1dGU9Nzc2MztlLm9tYWNyb25ncmF2ZT03NzYxO2Uub21kZXZhPTIzODQ7ZS5vbWVnYT05Njk7ZS5vbWVnYTE9OTgyO2Uub21lZ2FjeXJpbGxpYz0xMTIxO2Uub21lZ2FsYXRpbmNsb3NlZD02MzE7ZS5vbWVnYXJvdW5kY3lyaWxsaWM9MTE0NztlLm9tZWdhdGl0bG9jeXJpbGxpYz0xMTQ5O2Uub21lZ2F0b25vcz05NzQ7ZS5vbWd1amFyYXRpPTI3Njg7ZS5vbWljcm9uPTk1OTtlLm9taWNyb250b25vcz05NzI7ZS5vbW9ub3NwYWNlPTY1MzU5O2Uub25lPTQ5O2Uub25lYXJhYmljPTE2MzM7ZS5vbmViZW5nYWxpPTI1MzU7ZS5vbmVjaXJjbGU9OTMxMjtlLm9uZWNpcmNsZWludmVyc2VzYW5zc2VyaWY9MTAxMjI7ZS5vbmVkZXZhPTI0MDc7ZS5vbmVkb3RlbmxlYWRlcj04MjI4O2Uub25lZWlnaHRoPTg1Mzk7ZS5vbmVmaXR0ZWQ9NjMxOTY7ZS5vbmVndWphcmF0aT0yNzkxO2Uub25lZ3VybXVraGk9MjY2MztlLm9uZWhhY2thcmFiaWM9MTYzMztlLm9uZWhhbGY9MTg5O2Uub25laGFuZ3pob3U9MTIzMjE7ZS5vbmVpZGVvZ3JhcGhpY3BhcmVuPTEyODMyO2Uub25laW5mZXJpb3I9ODMyMTtlLm9uZW1vbm9zcGFjZT02NTI5NztlLm9uZW51bWVyYXRvcmJlbmdhbGk9MjU0ODtlLm9uZW9sZHN0eWxlPTYzMjgxO2Uub25lcGFyZW49OTMzMjtlLm9uZXBlcmlvZD05MzUyO2Uub25lcGVyc2lhbj0xNzc3O2Uub25lcXVhcnRlcj0xODg7ZS5vbmVyb21hbj04NTYwO2Uub25lc3VwZXJpb3I9MTg1O2Uub25ldGhhaT0zNjY1O2Uub25ldGhpcmQ9ODUzMTtlLm9vZ29uZWs9NDkxO2Uub29nb25la21hY3Jvbj00OTM7ZS5vb2d1cm11a2hpPTI1Nzk7ZS5vb21hdHJhZ3VybXVraGk9MjYzNTtlLm9vcGVuPTU5NjtlLm9wYXJlbj05Mzg2O2Uub3BlbmJ1bGxldD05NzAyO2Uub3B0aW9uPTg5OTc7ZS5vcmRmZW1pbmluZT0xNzA7ZS5vcmRtYXNjdWxpbmU9MTg2O2Uub3J0aG9nb25hbD04NzM1O2Uub3Nob3J0ZGV2YT0yMzIyO2Uub3Nob3J0dm93ZWxzaWduZGV2YT0yMzc4O2Uub3NsYXNoPTI0ODtlLm9zbGFzaGFjdXRlPTUxMTtlLm9zbWFsbGhpcmFnYW5hPTEyMzYxO2Uub3NtYWxsa2F0YWthbmE9MTI0NTc7ZS5vc21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM4NztlLm9zdHJva2VhY3V0ZT01MTE7ZS5vc3VwZXJpb3I9NjMyMTY7ZS5vdGN5cmlsbGljPTExNTE7ZS5vdGlsZGU9MjQ1O2Uub3RpbGRlYWN1dGU9Nzc1NztlLm90aWxkZWRpZXJlc2lzPTc3NTk7ZS5vdWJvcG9tb2ZvPTEyNTc3O2Uub3ZlcmxpbmU9ODI1NDtlLm92ZXJsaW5lY2VudGVybGluZT02NTA5ODtlLm92ZXJsaW5lY21iPTc3MztlLm92ZXJsaW5lZGFzaGVkPTY1MDk3O2Uub3ZlcmxpbmVkYmx3YXZ5PTY1MTAwO2Uub3ZlcmxpbmV3YXZ5PTY1MDk5O2Uub3ZlcnNjb3JlPTE3NTtlLm92b3dlbHNpZ25iZW5nYWxpPTI1MDc7ZS5vdm93ZWxzaWduZGV2YT0yMzc5O2Uub3Zvd2Vsc2lnbmd1amFyYXRpPTI3NjM7ZS5wPTExMjtlLnBhYW1wc3NxdWFyZT0xMzE4NDtlLnBhYXNlbnRvc3F1YXJlPTEzMDk5O2UucGFiZW5nYWxpPTI0NzQ7ZS5wYWN1dGU9Nzc2NTtlLnBhZGV2YT0yMzQ2O2UucGFnZWRvd249ODY3MTtlLnBhZ2V1cD04NjcwO2UucGFndWphcmF0aT0yNzMwO2UucGFndXJtdWtoaT0yNjAyO2UucGFoaXJhZ2FuYT0xMjQwMTtlLnBhaXlhbm5vaXRoYWk9MzYzMTtlLnBha2F0YWthbmE9MTI0OTc7ZS5wYWxhdGFsaXphdGlvbmN5cmlsbGljY21iPTExNTY7ZS5wYWxvY2hrYWN5cmlsbGljPTEyMTY7ZS5wYW5zaW9za29yZWFuPTEyNjcxO2UucGFyYWdyYXBoPTE4MjtlLnBhcmFsbGVsPTg3NDE7ZS5wYXJlbmxlZnQ9NDA7ZS5wYXJlbmxlZnRhbHRvbmVhcmFiaWM9NjQ4MzA7ZS5wYXJlbmxlZnRidD02MzcyNTtlLnBhcmVubGVmdGV4PTYzNzI0O2UucGFyZW5sZWZ0aW5mZXJpb3I9ODMzMztlLnBhcmVubGVmdG1vbm9zcGFjZT02NTI4ODtlLnBhcmVubGVmdHNtYWxsPTY1MTEzO2UucGFyZW5sZWZ0c3VwZXJpb3I9ODMxNztlLnBhcmVubGVmdHRwPTYzNzIzO2UucGFyZW5sZWZ0dmVydGljYWw9NjUwNzc7ZS5wYXJlbnJpZ2h0PTQxO2UucGFyZW5yaWdodGFsdG9uZWFyYWJpYz02NDgzMTtlLnBhcmVucmlnaHRidD02MzczNjtlLnBhcmVucmlnaHRleD02MzczNTtlLnBhcmVucmlnaHRpbmZlcmlvcj04MzM0O2UucGFyZW5yaWdodG1vbm9zcGFjZT02NTI4OTtlLnBhcmVucmlnaHRzbWFsbD02NTExNDtlLnBhcmVucmlnaHRzdXBlcmlvcj04MzE4O2UucGFyZW5yaWdodHRwPTYzNzM0O2UucGFyZW5yaWdodHZlcnRpY2FsPTY1MDc4O2UucGFydGlhbGRpZmY9ODcwNjtlLnBhc2VxaGVicmV3PTE0NzI7ZS5wYXNodGFoZWJyZXc9MTQzMztlLnBhc3F1YXJlPTEzMjI1O2UucGF0YWg9MTQ2MztlLnBhdGFoMTE9MTQ2MztlLnBhdGFoMWQ9MTQ2MztlLnBhdGFoMmE9MTQ2MztlLnBhdGFoaGVicmV3PTE0NjM7ZS5wYXRhaG5hcnJvd2hlYnJldz0xNDYzO2UucGF0YWhxdWFydGVyaGVicmV3PTE0NjM7ZS5wYXRhaHdpZGVoZWJyZXc9MTQ2MztlLnBhemVyaGVicmV3PTE0NDE7ZS5wYm9wb21vZm89MTI1NTA7ZS5wY2lyY2xlPTk0Mzk7ZS5wZG90YWNjZW50PTc3Njc7ZS5wZT0xNTA4O2UucGVjeXJpbGxpYz0xMDg3O2UucGVkYWdlc2g9NjQzMjQ7ZS5wZWRhZ2VzaGhlYnJldz02NDMyNDtlLnBlZXppc3F1YXJlPTEzMTE1O2UucGVmaW5hbGRhZ2VzaGhlYnJldz02NDMyMztlLnBlaGFyYWJpYz0xNjYyO2UucGVoYXJtZW5pYW49MTQwMjtlLnBlaGVicmV3PTE1MDg7ZS5wZWhmaW5hbGFyYWJpYz02NDM0MztlLnBlaGluaXRpYWxhcmFiaWM9NjQzNDQ7ZS5wZWhpcmFnYW5hPTEyNDEwO2UucGVobWVkaWFsYXJhYmljPTY0MzQ1O2UucGVrYXRha2FuYT0xMjUwNjtlLnBlbWlkZGxlaG9va2N5cmlsbGljPTExOTE7ZS5wZXJhZmVoZWJyZXc9NjQzMzQ7ZS5wZXJjZW50PTM3O2UucGVyY2VudGFyYWJpYz0xNjQyO2UucGVyY2VudG1vbm9zcGFjZT02NTI4NTtlLnBlcmNlbnRzbWFsbD02NTEzMDtlLnBlcmlvZD00NjtlLnBlcmlvZGFybWVuaWFuPTE0MTc7ZS5wZXJpb2RjZW50ZXJlZD0xODM7ZS5wZXJpb2RoYWxmd2lkdGg9NjUzNzc7ZS5wZXJpb2RpbmZlcmlvcj02MzIwNztlLnBlcmlvZG1vbm9zcGFjZT02NTI5NDtlLnBlcmlvZHNtYWxsPTY1MTA2O2UucGVyaW9kc3VwZXJpb3I9NjMyMDg7ZS5wZXJpc3BvbWVuaWdyZWVrY21iPTgzNDtlLnBlcnBlbmRpY3VsYXI9ODg2OTtlLnBlcnRob3VzYW5kPTgyNDA7ZS5wZXNldGE9ODM1OTtlLnBmc3F1YXJlPTEzMTk0O2UucGhhYmVuZ2FsaT0yNDc1O2UucGhhZGV2YT0yMzQ3O2UucGhhZ3VqYXJhdGk9MjczMTtlLnBoYWd1cm11a2hpPTI2MDM7ZS5waGk9OTY2O2UucGhpMT05ODE7ZS5waGlldXBoYWNpcmNsZWtvcmVhbj0xMjkyMjtlLnBoaWV1cGhhcGFyZW5rb3JlYW49MTI4MjY7ZS5waGlldXBoY2lyY2xla29yZWFuPTEyOTA4O2UucGhpZXVwaGtvcmVhbj0xMjYyMTtlLnBoaWV1cGhwYXJlbmtvcmVhbj0xMjgxMjtlLnBoaWxhdGluPTYzMjtlLnBoaW50aHV0aGFpPTM2NDI7ZS5waGlzeW1ib2xncmVlaz05ODE7ZS5waG9vaz00MjE7ZS5waG9waGFudGhhaT0zNjE0O2UucGhvcGh1bmd0aGFpPTM2MTI7ZS5waG9zYW1waGFvdGhhaT0zNjE2O2UucGk9OTYwO2UucGlldXBhY2lyY2xla29yZWFuPTEyOTE1O2UucGlldXBhcGFyZW5rb3JlYW49MTI4MTk7ZS5waWV1cGNpZXVja29yZWFuPTEyNjYyO2UucGlldXBjaXJjbGVrb3JlYW49MTI5MDE7ZS5waWV1cGtpeWVva2tvcmVhbj0xMjY1ODtlLnBpZXVwa29yZWFuPTEyNjEwO2UucGlldXBwYXJlbmtvcmVhbj0xMjgwNTtlLnBpZXVwc2lvc2tpeWVva2tvcmVhbj0xMjY2MDtlLnBpZXVwc2lvc2tvcmVhbj0xMjYxMjtlLnBpZXVwc2lvc3Rpa2V1dGtvcmVhbj0xMjY2MTtlLnBpZXVwdGhpZXV0aGtvcmVhbj0xMjY2MztlLnBpZXVwdGlrZXV0a29yZWFuPTEyNjU5O2UucGloaXJhZ2FuYT0xMjQwNDtlLnBpa2F0YWthbmE9MTI1MDA7ZS5waXN5bWJvbGdyZWVrPTk4MjtlLnBpd3Jhcm1lbmlhbj0xNDExO2UucGxhbmNrb3ZlcjJwaT04NDYzO2UucGxhbmNrb3ZlcjJwaTE9ODQ2MztlLnBsdXM9NDM7ZS5wbHVzYmVsb3djbWI9Nzk5O2UucGx1c2NpcmNsZT04ODUzO2UucGx1c21pbnVzPTE3NztlLnBsdXNtb2Q9NzI2O2UucGx1c21vbm9zcGFjZT02NTI5MTtlLnBsdXNzbWFsbD02NTEyMjtlLnBsdXNzdXBlcmlvcj04MzE0O2UucG1vbm9zcGFjZT02NTM2MDtlLnBtc3F1YXJlPTEzMjcyO2UucG9oaXJhZ2FuYT0xMjQxMztlLnBvaW50aW5naW5kZXhkb3dud2hpdGU9OTc1OTtlLnBvaW50aW5naW5kZXhsZWZ0d2hpdGU9OTc1NjtlLnBvaW50aW5naW5kZXhyaWdodHdoaXRlPTk3NTg7ZS5wb2ludGluZ2luZGV4dXB3aGl0ZT05NzU3O2UucG9rYXRha2FuYT0xMjUwOTtlLnBvcGxhdGhhaT0zNjExO2UucG9zdGFsbWFyaz0xMjMwNjtlLnBvc3RhbG1hcmtmYWNlPTEyMzIwO2UucHBhcmVuPTkzODc7ZS5wcmVjZWRlcz04ODI2O2UucHJlc2NyaXB0aW9uPTg0Nzg7ZS5wcmltZW1vZD02OTc7ZS5wcmltZXJldmVyc2VkPTgyNDU7ZS5wcm9kdWN0PTg3MTk7ZS5wcm9qZWN0aXZlPTg5NjU7ZS5wcm9sb25nZWRrYW5hPTEyNTQwO2UucHJvcGVsbG9yPTg5ODQ7ZS5wcm9wZXJzdWJzZXQ9ODgzNDtlLnByb3BlcnN1cGVyc2V0PTg4MzU7ZS5wcm9wb3J0aW9uPTg3NTk7ZS5wcm9wb3J0aW9uYWw9ODczMztlLnBzaT05Njg7ZS5wc2ljeXJpbGxpYz0xMTM3O2UucHNpbGlwbmV1bWF0YWN5cmlsbGljY21iPTExNTg7ZS5wc3NxdWFyZT0xMzIzMjtlLnB1aGlyYWdhbmE9MTI0MDc7ZS5wdWthdGFrYW5hPTEyNTAzO2UucHZzcXVhcmU9MTMyMzY7ZS5wd3NxdWFyZT0xMzI0MjtlLnE9MTEzO2UucWFkZXZhPTIzOTI7ZS5xYWRtYWhlYnJldz0xNDQ4O2UucWFmYXJhYmljPTE2MDI7ZS5xYWZmaW5hbGFyYWJpYz02NTIzODtlLnFhZmluaXRpYWxhcmFiaWM9NjUyMzk7ZS5xYWZtZWRpYWxhcmFiaWM9NjUyNDA7ZS5xYW1hdHM9MTQ2NDtlLnFhbWF0czEwPTE0NjQ7ZS5xYW1hdHMxYT0xNDY0O2UucWFtYXRzMWM9MTQ2NDtlLnFhbWF0czI3PTE0NjQ7ZS5xYW1hdHMyOT0xNDY0O2UucWFtYXRzMzM9MTQ2NDtlLnFhbWF0c2RlPTE0NjQ7ZS5xYW1hdHNoZWJyZXc9MTQ2NDtlLnFhbWF0c25hcnJvd2hlYnJldz0xNDY0O2UucWFtYXRzcWF0YW5oZWJyZXc9MTQ2NDtlLnFhbWF0c3FhdGFubmFycm93aGVicmV3PTE0NjQ7ZS5xYW1hdHNxYXRhbnF1YXJ0ZXJoZWJyZXc9MTQ2NDtlLnFhbWF0c3FhdGFud2lkZWhlYnJldz0xNDY0O2UucWFtYXRzcXVhcnRlcmhlYnJldz0xNDY0O2UucWFtYXRzd2lkZWhlYnJldz0xNDY0O2UucWFybmV5cGFyYWhlYnJldz0xNDM5O2UucWJvcG9tb2ZvPTEyNTYxO2UucWNpcmNsZT05NDQwO2UucWhvb2s9NjcyO2UucW1vbm9zcGFjZT02NTM2MTtlLnFvZj0xNTExO2UucW9mZGFnZXNoPTY0MzI3O2UucW9mZGFnZXNoaGVicmV3PTY0MzI3O2UucW9maGVicmV3PTE1MTE7ZS5xcGFyZW49OTM4ODtlLnF1YXJ0ZXJub3RlPTk4MzM7ZS5xdWJ1dHM9MTQ2NztlLnF1YnV0czE4PTE0Njc7ZS5xdWJ1dHMyNT0xNDY3O2UucXVidXRzMzE9MTQ2NztlLnF1YnV0c2hlYnJldz0xNDY3O2UucXVidXRzbmFycm93aGVicmV3PTE0Njc7ZS5xdWJ1dHNxdWFydGVyaGVicmV3PTE0Njc7ZS5xdWJ1dHN3aWRlaGVicmV3PTE0Njc7ZS5xdWVzdGlvbj02MztlLnF1ZXN0aW9uYXJhYmljPTE1Njc7ZS5xdWVzdGlvbmFybWVuaWFuPTEzNzQ7ZS5xdWVzdGlvbmRvd249MTkxO2UucXVlc3Rpb25kb3duc21hbGw9NjM0MjM7ZS5xdWVzdGlvbmdyZWVrPTg5NDtlLnF1ZXN0aW9ubW9ub3NwYWNlPTY1MzExO2UucXVlc3Rpb25zbWFsbD02MzI5NTtlLnF1b3RlZGJsPTM0O2UucXVvdGVkYmxiYXNlPTgyMjI7ZS5xdW90ZWRibGxlZnQ9ODIyMDtlLnF1b3RlZGJsbW9ub3NwYWNlPTY1MjgyO2UucXVvdGVkYmxwcmltZT0xMjMxODtlLnF1b3RlZGJscHJpbWVyZXZlcnNlZD0xMjMxNztlLnF1b3RlZGJscmlnaHQ9ODIyMTtlLnF1b3RlbGVmdD04MjE2O2UucXVvdGVsZWZ0cmV2ZXJzZWQ9ODIxOTtlLnF1b3RlcmV2ZXJzZWQ9ODIxOTtlLnF1b3RlcmlnaHQ9ODIxNztlLnF1b3RlcmlnaHRuPTMyOTtlLnF1b3Rlc2luZ2xiYXNlPTgyMTg7ZS5xdW90ZXNpbmdsZT0zOTtlLnF1b3Rlc2luZ2xlbW9ub3NwYWNlPTY1Mjg3O2Uucj0xMTQ7ZS5yYWFybWVuaWFuPTE0MDQ7ZS5yYWJlbmdhbGk9MjQ4MDtlLnJhY3V0ZT0zNDE7ZS5yYWRldmE9MjM1MjtlLnJhZGljYWw9ODczMDtlLnJhZGljYWxleD02MzcxNztlLnJhZG92ZXJzc3F1YXJlPTEzMjMwO2UucmFkb3ZlcnNzcXVhcmVkc3F1YXJlPTEzMjMxO2UucmFkc3F1YXJlPTEzMjI5O2UucmFmZT0xNDcxO2UucmFmZWhlYnJldz0xNDcxO2UucmFndWphcmF0aT0yNzM2O2UucmFndXJtdWtoaT0yNjA4O2UucmFoaXJhZ2FuYT0xMjQyNTtlLnJha2F0YWthbmE9MTI1MjE7ZS5yYWthdGFrYW5haGFsZndpZHRoPTY1NDMxO2UucmFsb3dlcmRpYWdvbmFsYmVuZ2FsaT0yNTQ1O2UucmFtaWRkbGVkaWFnb25hbGJlbmdhbGk9MjU0NDtlLnJhbXNob3JuPTYxMjtlLnJhdGlvPTg3NTg7ZS5yYm9wb21vZm89MTI1NjY7ZS5yY2Fyb249MzQ1O2UucmNlZGlsbGE9MzQzO2UucmNpcmNsZT05NDQxO2UucmNvbW1hYWNjZW50PTM0MztlLnJkYmxncmF2ZT01Mjk7ZS5yZG90YWNjZW50PTc3Njk7ZS5yZG90YmVsb3c9Nzc3MTtlLnJkb3RiZWxvd21hY3Jvbj03NzczO2UucmVmZXJlbmNlbWFyaz04MjUxO2UucmVmbGV4c3Vic2V0PTg4Mzg7ZS5yZWZsZXhzdXBlcnNldD04ODM5O2UucmVnaXN0ZXJlZD0xNzQ7ZS5yZWdpc3RlcnNhbnM9NjM3MjA7ZS5yZWdpc3RlcnNlcmlmPTYzMTk0O2UucmVoYXJhYmljPTE1ODU7ZS5yZWhhcm1lbmlhbj0xNDA4O2UucmVoZmluYWxhcmFiaWM9NjUxOTg7ZS5yZWhpcmFnYW5hPTEyNDI4O2UucmVrYXRha2FuYT0xMjUyNDtlLnJla2F0YWthbmFoYWxmd2lkdGg9NjU0MzQ7ZS5yZXNoPTE1MTI7ZS5yZXNoZGFnZXNoaGVicmV3PTY0MzI4O2UucmVzaGhlYnJldz0xNTEyO2UucmV2ZXJzZWR0aWxkZT04NzY1O2UucmV2aWFoZWJyZXc9MTQzMTtlLnJldmlhbXVncmFzaGhlYnJldz0xNDMxO2UucmV2bG9naWNhbG5vdD04OTc2O2UucmZpc2hob29rPTYzODtlLnJmaXNoaG9va3JldmVyc2VkPTYzOTtlLnJoYWJlbmdhbGk9MjUyNTtlLnJoYWRldmE9MjM5NztlLnJobz05NjE7ZS5yaG9vaz02Mzc7ZS5yaG9va3R1cm5lZD02MzU7ZS5yaG9va3R1cm5lZHN1cGVyaW9yPTY5MztlLnJob3N5bWJvbGdyZWVrPTEwMDk7ZS5yaG90aWNob29rbW9kPTczNDtlLnJpZXVsYWNpcmNsZWtvcmVhbj0xMjkxMztlLnJpZXVsYXBhcmVua29yZWFuPTEyODE3O2UucmlldWxjaXJjbGVrb3JlYW49MTI4OTk7ZS5yaWV1bGhpZXVoa29yZWFuPTEyNjA4O2UucmlldWxraXllb2trb3JlYW49MTI2MDI7ZS5yaWV1bGtpeWVva3Npb3Nrb3JlYW49MTI2NDk7ZS5yaWV1bGtvcmVhbj0xMjYwMTtlLnJpZXVsbWlldW1rb3JlYW49MTI2MDM7ZS5yaWV1bHBhbnNpb3Nrb3JlYW49MTI2NTI7ZS5yaWV1bHBhcmVua29yZWFuPTEyODAzO2UucmlldWxwaGlldXBoa29yZWFuPTEyNjA3O2UucmlldWxwaWV1cGtvcmVhbj0xMjYwNDtlLnJpZXVscGlldXBzaW9za29yZWFuPTEyNjUxO2UucmlldWxzaW9za29yZWFuPTEyNjA1O2UucmlldWx0aGlldXRoa29yZWFuPTEyNjA2O2UucmlldWx0aWtldXRrb3JlYW49MTI2NTA7ZS5yaWV1bHllb3JpbmhpZXVoa29yZWFuPTEyNjUzO2UucmlnaHRhbmdsZT04NzM1O2UucmlnaHR0YWNrYmVsb3djbWI9NzkzO2UucmlnaHR0cmlhbmdsZT04ODk1O2UucmloaXJhZ2FuYT0xMjQyNjtlLnJpa2F0YWthbmE9MTI1MjI7ZS5yaWthdGFrYW5haGFsZndpZHRoPTY1NDMyO2UucmluZz03MzA7ZS5yaW5nYmVsb3djbWI9ODA1O2UucmluZ2NtYj03Nzg7ZS5yaW5naGFsZmxlZnQ9NzAzO2UucmluZ2hhbGZsZWZ0YXJtZW5pYW49MTM2OTtlLnJpbmdoYWxmbGVmdGJlbG93Y21iPTc5NjtlLnJpbmdoYWxmbGVmdGNlbnRlcmVkPTcyMztlLnJpbmdoYWxmcmlnaHQ9NzAyO2UucmluZ2hhbGZyaWdodGJlbG93Y21iPTgyNTtlLnJpbmdoYWxmcmlnaHRjZW50ZXJlZD03MjI7ZS5yaW52ZXJ0ZWRicmV2ZT01MzE7ZS5yaXR0b3J1c3F1YXJlPTEzMTM3O2UucmxpbmViZWxvdz03Nzc1O2UucmxvbmdsZWc9NjM2O2UucmxvbmdsZWd0dXJuZWQ9NjM0O2Uucm1vbm9zcGFjZT02NTM2MjtlLnJvaGlyYWdhbmE9MTI0Mjk7ZS5yb2thdGFrYW5hPTEyNTI1O2Uucm9rYXRha2FuYWhhbGZ3aWR0aD02NTQzNTtlLnJvcnVhdGhhaT0zNjE5O2UucnBhcmVuPTkzODk7ZS5ycmFiZW5nYWxpPTI1MjQ7ZS5ycmFkZXZhPTIzNTM7ZS5ycmFndXJtdWtoaT0yNjUyO2UucnJlaGFyYWJpYz0xNjgxO2UucnJlaGZpbmFsYXJhYmljPTY0Mzk3O2UucnJ2b2NhbGljYmVuZ2FsaT0yNTI4O2UucnJ2b2NhbGljZGV2YT0yNDAwO2UucnJ2b2NhbGljZ3VqYXJhdGk9Mjc4NDtlLnJydm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGk9MjUwMDtlLnJydm9jYWxpY3Zvd2Vsc2lnbmRldmE9MjM3MjtlLnJydm9jYWxpY3Zvd2Vsc2lnbmd1amFyYXRpPTI3NTY7ZS5yc3VwZXJpb3I9NjMyMTc7ZS5ydGJsb2NrPTk2MTY7ZS5ydHVybmVkPTYzMztlLnJ0dXJuZWRzdXBlcmlvcj02OTI7ZS5ydWhpcmFnYW5hPTEyNDI3O2UucnVrYXRha2FuYT0xMjUyMztlLnJ1a2F0YWthbmFoYWxmd2lkdGg9NjU0MzM7ZS5ydXBlZW1hcmtiZW5nYWxpPTI1NDY7ZS5ydXBlZXNpZ25iZW5nYWxpPTI1NDc7ZS5ydXBpYWg9NjMxOTc7ZS5ydXRoYWk9MzYyMDtlLnJ2b2NhbGljYmVuZ2FsaT0yNDQzO2UucnZvY2FsaWNkZXZhPTIzMTU7ZS5ydm9jYWxpY2d1amFyYXRpPTI2OTk7ZS5ydm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGk9MjQ5OTtlLnJ2b2NhbGljdm93ZWxzaWduZGV2YT0yMzcxO2UucnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aT0yNzU1O2Uucz0xMTU7ZS5zYWJlbmdhbGk9MjQ4ODtlLnNhY3V0ZT0zNDc7ZS5zYWN1dGVkb3RhY2NlbnQ9Nzc4MTtlLnNhZGFyYWJpYz0xNTg5O2Uuc2FkZXZhPTIzNjA7ZS5zYWRmaW5hbGFyYWJpYz02NTIxMDtlLnNhZGluaXRpYWxhcmFiaWM9NjUyMTE7ZS5zYWRtZWRpYWxhcmFiaWM9NjUyMTI7ZS5zYWd1amFyYXRpPTI3NDQ7ZS5zYWd1cm11a2hpPTI2MTY7ZS5zYWhpcmFnYW5hPTEyMzczO2Uuc2FrYXRha2FuYT0xMjQ2OTtlLnNha2F0YWthbmFoYWxmd2lkdGg9NjU0MDM7ZS5zYWxsYWxsYWhvdWFsYXloZXdhc2FsbGFtYXJhYmljPTY1MDE4O2Uuc2FtZWtoPTE1MDU7ZS5zYW1la2hkYWdlc2g9NjQzMjE7ZS5zYW1la2hkYWdlc2hoZWJyZXc9NjQzMjE7ZS5zYW1la2hoZWJyZXc9MTUwNTtlLnNhcmFhYXRoYWk9MzYzNDtlLnNhcmFhZXRoYWk9MzY0OTtlLnNhcmFhaW1haW1hbGFpdGhhaT0zNjUyO2Uuc2FyYWFpbWFpbXVhbnRoYWk9MzY1MTtlLnNhcmFhbXRoYWk9MzYzNTtlLnNhcmFhdGhhaT0zNjMyO2Uuc2FyYWV0aGFpPTM2NDg7ZS5zYXJhaWlsZWZ0dGhhaT02MzYyMjtlLnNhcmFpaXRoYWk9MzYzNztlLnNhcmFpbGVmdHRoYWk9NjM2MjE7ZS5zYXJhaXRoYWk9MzYzNjtlLnNhcmFvdGhhaT0zNjUwO2Uuc2FyYXVlZWxlZnR0aGFpPTYzNjI0O2Uuc2FyYXVlZXRoYWk9MzYzOTtlLnNhcmF1ZWxlZnR0aGFpPTYzNjIzO2Uuc2FyYXVldGhhaT0zNjM4O2Uuc2FyYXV0aGFpPTM2NDA7ZS5zYXJhdXV0aGFpPTM2NDE7ZS5zYm9wb21vZm89MTI1Njk7ZS5zY2Fyb249MzUzO2Uuc2Nhcm9uZG90YWNjZW50PTc3ODM7ZS5zY2VkaWxsYT0zNTE7ZS5zY2h3YT02MDE7ZS5zY2h3YWN5cmlsbGljPTEyNDE7ZS5zY2h3YWRpZXJlc2lzY3lyaWxsaWM9MTI0MztlLnNjaHdhaG9vaz02MDI7ZS5zY2lyY2xlPTk0NDI7ZS5zY2lyY3VtZmxleD0zNDk7ZS5zY29tbWFhY2NlbnQ9NTM3O2Uuc2RvdGFjY2VudD03Nzc3O2Uuc2RvdGJlbG93PTc3Nzk7ZS5zZG90YmVsb3dkb3RhY2NlbnQ9Nzc4NTtlLnNlYWd1bGxiZWxvd2NtYj04Mjg7ZS5zZWNvbmQ9ODI0MztlLnNlY29uZHRvbmVjaGluZXNlPTcxNDtlLnNlY3Rpb249MTY3O2Uuc2VlbmFyYWJpYz0xNTg3O2Uuc2VlbmZpbmFsYXJhYmljPTY1MjAyO2Uuc2VlbmluaXRpYWxhcmFiaWM9NjUyMDM7ZS5zZWVubWVkaWFsYXJhYmljPTY1MjA0O2Uuc2Vnb2w9MTQ2MjtlLnNlZ29sMTM9MTQ2MjtlLnNlZ29sMWY9MTQ2MjtlLnNlZ29sMmM9MTQ2MjtlLnNlZ29saGVicmV3PTE0NjI7ZS5zZWdvbG5hcnJvd2hlYnJldz0xNDYyO2Uuc2Vnb2xxdWFydGVyaGVicmV3PTE0NjI7ZS5zZWdvbHRhaGVicmV3PTE0MjY7ZS5zZWdvbHdpZGVoZWJyZXc9MTQ2MjtlLnNlaGFybWVuaWFuPTE0MDU7ZS5zZWhpcmFnYW5hPTEyMzc5O2Uuc2VrYXRha2FuYT0xMjQ3NTtlLnNla2F0YWthbmFoYWxmd2lkdGg9NjU0MDY7ZS5zZW1pY29sb249NTk7ZS5zZW1pY29sb25hcmFiaWM9MTU2MztlLnNlbWljb2xvbm1vbm9zcGFjZT02NTMwNztlLnNlbWljb2xvbnNtYWxsPTY1MTA4O2Uuc2VtaXZvaWNlZG1hcmtrYW5hPTEyNDQ0O2Uuc2VtaXZvaWNlZG1hcmtrYW5haGFsZndpZHRoPTY1NDM5O2Uuc2VudGlzcXVhcmU9MTMwOTA7ZS5zZW50b3NxdWFyZT0xMzA5MTtlLnNldmVuPTU1O2Uuc2V2ZW5hcmFiaWM9MTYzOTtlLnNldmVuYmVuZ2FsaT0yNTQxO2Uuc2V2ZW5jaXJjbGU9OTMxODtlLnNldmVuY2lyY2xlaW52ZXJzZXNhbnNzZXJpZj0xMDEyODtlLnNldmVuZGV2YT0yNDEzO2Uuc2V2ZW5laWdodGhzPTg1NDI7ZS5zZXZlbmd1amFyYXRpPTI3OTc7ZS5zZXZlbmd1cm11a2hpPTI2Njk7ZS5zZXZlbmhhY2thcmFiaWM9MTYzOTtlLnNldmVuaGFuZ3pob3U9MTIzMjc7ZS5zZXZlbmlkZW9ncmFwaGljcGFyZW49MTI4Mzg7ZS5zZXZlbmluZmVyaW9yPTgzMjc7ZS5zZXZlbm1vbm9zcGFjZT02NTMwMztlLnNldmVub2xkc3R5bGU9NjMyODc7ZS5zZXZlbnBhcmVuPTkzMzg7ZS5zZXZlbnBlcmlvZD05MzU4O2Uuc2V2ZW5wZXJzaWFuPTE3ODM7ZS5zZXZlbnJvbWFuPTg1NjY7ZS5zZXZlbnN1cGVyaW9yPTgzMTE7ZS5zZXZlbnRlZW5jaXJjbGU9OTMyODtlLnNldmVudGVlbnBhcmVuPTkzNDg7ZS5zZXZlbnRlZW5wZXJpb2Q9OTM2ODtlLnNldmVudGhhaT0zNjcxO2Uuc2Z0aHlwaGVuPTE3MztlLnNoYWFybWVuaWFuPTEzOTk7ZS5zaGFiZW5nYWxpPTI0ODY7ZS5zaGFjeXJpbGxpYz0xMDk2O2Uuc2hhZGRhYXJhYmljPTE2MTc7ZS5zaGFkZGFkYW1tYWFyYWJpYz02NDYwOTtlLnNoYWRkYWRhbW1hdGFuYXJhYmljPTY0NjA2O2Uuc2hhZGRhZmF0aGFhcmFiaWM9NjQ2MDg7ZS5zaGFkZGFrYXNyYWFyYWJpYz02NDYxMDtlLnNoYWRkYWthc3JhdGFuYXJhYmljPTY0NjA3O2Uuc2hhZGU9OTYxODtlLnNoYWRlZGFyaz05NjE5O2Uuc2hhZGVsaWdodD05NjE3O2Uuc2hhZGVtZWRpdW09OTYxODtlLnNoYWRldmE9MjM1ODtlLnNoYWd1amFyYXRpPTI3NDI7ZS5zaGFndXJtdWtoaT0yNjE0O2Uuc2hhbHNoZWxldGhlYnJldz0xNDI3O2Uuc2hib3BvbW9mbz0xMjU2NTtlLnNoY2hhY3lyaWxsaWM9MTA5NztlLnNoZWVuYXJhYmljPTE1ODg7ZS5zaGVlbmZpbmFsYXJhYmljPTY1MjA2O2Uuc2hlZW5pbml0aWFsYXJhYmljPTY1MjA3O2Uuc2hlZW5tZWRpYWxhcmFiaWM9NjUyMDg7ZS5zaGVpY29wdGljPTk5NTtlLnNoZXFlbD04MzYyO2Uuc2hlcWVsaGVicmV3PTgzNjI7ZS5zaGV2YT0xNDU2O2Uuc2hldmExMTU9MTQ1NjtlLnNoZXZhMTU9MTQ1NjtlLnNoZXZhMjI9MTQ1NjtlLnNoZXZhMmU9MTQ1NjtlLnNoZXZhaGVicmV3PTE0NTY7ZS5zaGV2YW5hcnJvd2hlYnJldz0xNDU2O2Uuc2hldmFxdWFydGVyaGVicmV3PTE0NTY7ZS5zaGV2YXdpZGVoZWJyZXc9MTQ1NjtlLnNoaGFjeXJpbGxpYz0xMjExO2Uuc2hpbWFjb3B0aWM9MTAwNTtlLnNoaW49MTUxMztlLnNoaW5kYWdlc2g9NjQzMjk7ZS5zaGluZGFnZXNoaGVicmV3PTY0MzI5O2Uuc2hpbmRhZ2VzaHNoaW5kb3Q9NjQzMDA7ZS5zaGluZGFnZXNoc2hpbmRvdGhlYnJldz02NDMwMDtlLnNoaW5kYWdlc2hzaW5kb3Q9NjQzMDE7ZS5zaGluZGFnZXNoc2luZG90aGVicmV3PTY0MzAxO2Uuc2hpbmRvdGhlYnJldz0xNDczO2Uuc2hpbmhlYnJldz0xNTEzO2Uuc2hpbnNoaW5kb3Q9NjQyOTg7ZS5zaGluc2hpbmRvdGhlYnJldz02NDI5ODtlLnNoaW5zaW5kb3Q9NjQyOTk7ZS5zaGluc2luZG90aGVicmV3PTY0Mjk5O2Uuc2hvb2s9NjQyO2Uuc2lnbWE9OTYzO2Uuc2lnbWExPTk2MjtlLnNpZ21hZmluYWw9OTYyO2Uuc2lnbWFsdW5hdGVzeW1ib2xncmVlaz0xMDEwO2Uuc2loaXJhZ2FuYT0xMjM3NTtlLnNpa2F0YWthbmE9MTI0NzE7ZS5zaWthdGFrYW5haGFsZndpZHRoPTY1NDA0O2Uuc2lsdXFoZWJyZXc9MTQ2OTtlLnNpbHVxbGVmdGhlYnJldz0xNDY5O2Uuc2ltaWxhcj04NzY0O2Uuc2luZG90aGVicmV3PTE0NzQ7ZS5zaW9zYWNpcmNsZWtvcmVhbj0xMjkxNjtlLnNpb3NhcGFyZW5rb3JlYW49MTI4MjA7ZS5zaW9zY2lldWNrb3JlYW49MTI2NzA7ZS5zaW9zY2lyY2xla29yZWFuPTEyOTAyO2Uuc2lvc2tpeWVva2tvcmVhbj0xMjY2NjtlLnNpb3Nrb3JlYW49MTI2MTM7ZS5zaW9zbmlldW5rb3JlYW49MTI2Njc7ZS5zaW9zcGFyZW5rb3JlYW49MTI4MDY7ZS5zaW9zcGlldXBrb3JlYW49MTI2Njk7ZS5zaW9zdGlrZXV0a29yZWFuPTEyNjY4O2Uuc2l4PTU0O2Uuc2l4YXJhYmljPTE2Mzg7ZS5zaXhiZW5nYWxpPTI1NDA7ZS5zaXhjaXJjbGU9OTMxNztlLnNpeGNpcmNsZWludmVyc2VzYW5zc2VyaWY9MTAxMjc7ZS5zaXhkZXZhPTI0MTI7ZS5zaXhndWphcmF0aT0yNzk2O2Uuc2l4Z3VybXVraGk9MjY2ODtlLnNpeGhhY2thcmFiaWM9MTYzODtlLnNpeGhhbmd6aG91PTEyMzI2O2Uuc2l4aWRlb2dyYXBoaWNwYXJlbj0xMjgzNztlLnNpeGluZmVyaW9yPTgzMjY7ZS5zaXhtb25vc3BhY2U9NjUzMDI7ZS5zaXhvbGRzdHlsZT02MzI4NjtlLnNpeHBhcmVuPTkzMzc7ZS5zaXhwZXJpb2Q9OTM1NztlLnNpeHBlcnNpYW49MTc4MjtlLnNpeHJvbWFuPTg1NjU7ZS5zaXhzdXBlcmlvcj04MzEwO2Uuc2l4dGVlbmNpcmNsZT05MzI3O2Uuc2l4dGVlbmN1cnJlbmN5ZGVub21pbmF0b3JiZW5nYWxpPTI1NTM7ZS5zaXh0ZWVucGFyZW49OTM0NztlLnNpeHRlZW5wZXJpb2Q9OTM2NztlLnNpeHRoYWk9MzY3MDtlLnNsYXNoPTQ3O2Uuc2xhc2htb25vc3BhY2U9NjUyOTU7ZS5zbG9uZz0zODM7ZS5zbG9uZ2RvdGFjY2VudD03ODM1O2Uuc21pbGVmYWNlPTk3ODY7ZS5zbW9ub3NwYWNlPTY1MzYzO2Uuc29mcGFzdXFoZWJyZXc9MTQ3NTtlLnNvZnRoeXBoZW49MTczO2Uuc29mdHNpZ25jeXJpbGxpYz0xMTAwO2Uuc29oaXJhZ2FuYT0xMjM4MTtlLnNva2F0YWthbmE9MTI0Nzc7ZS5zb2thdGFrYW5haGFsZndpZHRoPTY1NDA3O2Uuc29saWR1c2xvbmdvdmVybGF5Y21iPTgyNDtlLnNvbGlkdXNzaG9ydG92ZXJsYXljbWI9ODIzO2Uuc29ydXNpdGhhaT0zNjI1O2Uuc29zYWxhdGhhaT0zNjI0O2Uuc29zb3RoYWk9MzU5NTtlLnNvc3VhdGhhaT0zNjI2O2Uuc3BhY2U9MzI7ZS5zcGFjZWhhY2thcmFiaWM9MzI7ZS5zcGFkZT05ODI0O2Uuc3BhZGVzdWl0YmxhY2s9OTgyNDtlLnNwYWRlc3VpdHdoaXRlPTk4Mjg7ZS5zcGFyZW49OTM5MDtlLnNxdWFyZWJlbG93Y21iPTgyNztlLnNxdWFyZWNjPTEzMjUyO2Uuc3F1YXJlY209MTMyMTM7ZS5zcXVhcmVkaWFnb25hbGNyb3NzaGF0Y2hmaWxsPTk2NDE7ZS5zcXVhcmVob3Jpem9udGFsZmlsbD05NjM2O2Uuc3F1YXJla2c9MTMxOTk7ZS5zcXVhcmVrbT0xMzIxNDtlLnNxdWFyZWttY2FwaXRhbD0xMzI2MjtlLnNxdWFyZWxuPTEzMjY1O2Uuc3F1YXJlbG9nPTEzMjY2O2Uuc3F1YXJlbWc9MTMxOTg7ZS5zcXVhcmVtaWw9MTMyNjk7ZS5zcXVhcmVtbT0xMzIxMjtlLnNxdWFyZW1zcXVhcmVkPTEzMjE3O2Uuc3F1YXJlb3J0aG9nb25hbGNyb3NzaGF0Y2hmaWxsPTk2Mzg7ZS5zcXVhcmV1cHBlcmxlZnR0b2xvd2VycmlnaHRmaWxsPTk2Mzk7ZS5zcXVhcmV1cHBlcnJpZ2h0dG9sb3dlcmxlZnRmaWxsPTk2NDA7ZS5zcXVhcmV2ZXJ0aWNhbGZpbGw9OTYzNztlLnNxdWFyZXdoaXRld2l0aHNtYWxsYmxhY2s9OTYzNTtlLnNyc3F1YXJlPTEzMjc1O2Uuc3NhYmVuZ2FsaT0yNDg3O2Uuc3NhZGV2YT0yMzU5O2Uuc3NhZ3VqYXJhdGk9Mjc0MztlLnNzYW5nY2lldWNrb3JlYW49MTI2MTc7ZS5zc2FuZ2hpZXVoa29yZWFuPTEyNjc3O2Uuc3NhbmdpZXVuZ2tvcmVhbj0xMjY3MjtlLnNzYW5na2l5ZW9ra29yZWFuPTEyNTk0O2Uuc3NhbmduaWV1bmtvcmVhbj0xMjY0NTtlLnNzYW5ncGlldXBrb3JlYW49MTI2MTE7ZS5zc2FuZ3Npb3Nrb3JlYW49MTI2MTQ7ZS5zc2FuZ3Rpa2V1dGtvcmVhbj0xMjYwMDtlLnNzdXBlcmlvcj02MzIxODtlLnN0ZXJsaW5nPTE2MztlLnN0ZXJsaW5nbW9ub3NwYWNlPTY1NTA1O2Uuc3Ryb2tlbG9uZ292ZXJsYXljbWI9ODIyO2Uuc3Ryb2tlc2hvcnRvdmVybGF5Y21iPTgyMTtlLnN1YnNldD04ODM0O2Uuc3Vic2V0bm90ZXF1YWw9ODg0MjtlLnN1YnNldG9yZXF1YWw9ODgzODtlLnN1Y2NlZWRzPTg4Mjc7ZS5zdWNodGhhdD04NzE1O2Uuc3VoaXJhZ2FuYT0xMjM3NztlLnN1a2F0YWthbmE9MTI0NzM7ZS5zdWthdGFrYW5haGFsZndpZHRoPTY1NDA1O2Uuc3VrdW5hcmFiaWM9MTYxODtlLnN1bW1hdGlvbj04NzIxO2Uuc3VuPTk3ODg7ZS5zdXBlcnNldD04ODM1O2Uuc3VwZXJzZXRub3RlcXVhbD04ODQzO2Uuc3VwZXJzZXRvcmVxdWFsPTg4Mzk7ZS5zdnNxdWFyZT0xMzI3NjtlLnN5b3V3YWVyYXNxdWFyZT0xMzE4MDtlLnQ9MTE2O2UudGFiZW5nYWxpPTI0Njg7ZS50YWNrZG93bj04ODY4O2UudGFja2xlZnQ9ODg2NztlLnRhZGV2YT0yMzQwO2UudGFndWphcmF0aT0yNzI0O2UudGFndXJtdWtoaT0yNTk2O2UudGFoYXJhYmljPTE1OTE7ZS50YWhmaW5hbGFyYWJpYz02NTIxODtlLnRhaGluaXRpYWxhcmFiaWM9NjUyMTk7ZS50YWhpcmFnYW5hPTEyMzgzO2UudGFobWVkaWFsYXJhYmljPTY1MjIwO2UudGFpc3lvdWVyYXNxdWFyZT0xMzE4MTtlLnRha2F0YWthbmE9MTI0Nzk7ZS50YWthdGFrYW5haGFsZndpZHRoPTY1NDA4O2UudGF0d2VlbGFyYWJpYz0xNjAwO2UudGF1PTk2NDtlLnRhdj0xNTE0O2UudGF2ZGFnZXM9NjQzMzA7ZS50YXZkYWdlc2g9NjQzMzA7ZS50YXZkYWdlc2hoZWJyZXc9NjQzMzA7ZS50YXZoZWJyZXc9MTUxNDtlLnRiYXI9MzU5O2UudGJvcG9tb2ZvPTEyNTU0O2UudGNhcm9uPTM1NztlLnRjY3VybD02ODA7ZS50Y2VkaWxsYT0zNTU7ZS50Y2hlaGFyYWJpYz0xNjcwO2UudGNoZWhmaW5hbGFyYWJpYz02NDM3OTtlLnRjaGVoaW5pdGlhbGFyYWJpYz02NDM4MDtlLnRjaGVobWVkaWFsYXJhYmljPTY0MzgxO2UudGNpcmNsZT05NDQzO2UudGNpcmN1bWZsZXhiZWxvdz03NzkzO2UudGNvbW1hYWNjZW50PTM1NTtlLnRkaWVyZXNpcz03ODMxO2UudGRvdGFjY2VudD03Nzg3O2UudGRvdGJlbG93PTc3ODk7ZS50ZWN5cmlsbGljPTEwOTA7ZS50ZWRlc2NlbmRlcmN5cmlsbGljPTExOTc7ZS50ZWhhcmFiaWM9MTU3ODtlLnRlaGZpbmFsYXJhYmljPTY1MTc0O2UudGVoaGFoaW5pdGlhbGFyYWJpYz02NDY3NDtlLnRlaGhhaGlzb2xhdGVkYXJhYmljPTY0NTI0O2UudGVoaW5pdGlhbGFyYWJpYz02NTE3NTtlLnRlaGlyYWdhbmE9MTIzOTA7ZS50ZWhqZWVtaW5pdGlhbGFyYWJpYz02NDY3MztlLnRlaGplZW1pc29sYXRlZGFyYWJpYz02NDUyMztlLnRlaG1hcmJ1dGFhcmFiaWM9MTU3NztlLnRlaG1hcmJ1dGFmaW5hbGFyYWJpYz02NTE3MjtlLnRlaG1lZGlhbGFyYWJpYz02NTE3NjtlLnRlaG1lZW1pbml0aWFsYXJhYmljPTY0Njc2O2UudGVobWVlbWlzb2xhdGVkYXJhYmljPTY0NTI2O2UudGVobm9vbmZpbmFsYXJhYmljPTY0NjI3O2UudGVrYXRha2FuYT0xMjQ4NjtlLnRla2F0YWthbmFoYWxmd2lkdGg9NjU0MTE7ZS50ZWxlcGhvbmU9ODQ4MTtlLnRlbGVwaG9uZWJsYWNrPTk3NDI7ZS50ZWxpc2hhZ2Vkb2xhaGVicmV3PTE0NDA7ZS50ZWxpc2hhcWV0YW5haGVicmV3PTE0NDk7ZS50ZW5jaXJjbGU9OTMyMTtlLnRlbmlkZW9ncmFwaGljcGFyZW49MTI4NDE7ZS50ZW5wYXJlbj05MzQxO2UudGVucGVyaW9kPTkzNjE7ZS50ZW5yb21hbj04NTY5O2UudGVzaD02Nzk7ZS50ZXQ9MTQ5NjtlLnRldGRhZ2VzaD02NDMxMjtlLnRldGRhZ2VzaGhlYnJldz02NDMxMjtlLnRldGhlYnJldz0xNDk2O2UudGV0c2VjeXJpbGxpYz0xMjA1O2UudGV2aXJoZWJyZXc9MTQzNTtlLnRldmlybGVmdGhlYnJldz0xNDM1O2UudGhhYmVuZ2FsaT0yNDY5O2UudGhhZGV2YT0yMzQxO2UudGhhZ3VqYXJhdGk9MjcyNTtlLnRoYWd1cm11a2hpPTI1OTc7ZS50aGFsYXJhYmljPTE1ODQ7ZS50aGFsZmluYWxhcmFiaWM9NjUxOTY7ZS50aGFudGhha2hhdGxvd2xlZnR0aGFpPTYzNjQwO2UudGhhbnRoYWtoYXRsb3dyaWdodHRoYWk9NjM2Mzk7ZS50aGFudGhha2hhdHRoYWk9MzY2MDtlLnRoYW50aGFraGF0dXBwZXJsZWZ0dGhhaT02MzYzODtlLnRoZWhhcmFiaWM9MTU3OTtlLnRoZWhmaW5hbGFyYWJpYz02NTE3ODtlLnRoZWhpbml0aWFsYXJhYmljPTY1MTc5O2UudGhlaG1lZGlhbGFyYWJpYz02NTE4MDtlLnRoZXJlZXhpc3RzPTg3MDc7ZS50aGVyZWZvcmU9ODc1NjtlLnRoZXRhPTk1MjtlLnRoZXRhMT05Nzc7ZS50aGV0YXN5bWJvbGdyZWVrPTk3NztlLnRoaWV1dGhhY2lyY2xla29yZWFuPTEyOTIxO2UudGhpZXV0aGFwYXJlbmtvcmVhbj0xMjgyNTtlLnRoaWV1dGhjaXJjbGVrb3JlYW49MTI5MDc7ZS50aGlldXRoa29yZWFuPTEyNjIwO2UudGhpZXV0aHBhcmVua29yZWFuPTEyODExO2UudGhpcnRlZW5jaXJjbGU9OTMyNDtlLnRoaXJ0ZWVucGFyZW49OTM0NDtlLnRoaXJ0ZWVucGVyaW9kPTkzNjQ7ZS50aG9uYW5nbW9udGhvdGhhaT0zNjAxO2UudGhvb2s9NDI5O2UudGhvcGh1dGhhb3RoYWk9MzYwMjtlLnRob3JuPTI1NDtlLnRob3RoYWhhbnRoYWk9MzYwNztlLnRob3RoYW50aGFpPTM2MDA7ZS50aG90aG9uZ3RoYWk9MzYwODtlLnRob3RodW5ndGhhaT0zNjA2O2UudGhvdXNhbmRjeXJpbGxpYz0xMTU0O2UudGhvdXNhbmRzc2VwYXJhdG9yYXJhYmljPTE2NDQ7ZS50aG91c2FuZHNzZXBhcmF0b3JwZXJzaWFuPTE2NDQ7ZS50aHJlZT01MTtlLnRocmVlYXJhYmljPTE2MzU7ZS50aHJlZWJlbmdhbGk9MjUzNztlLnRocmVlY2lyY2xlPTkzMTQ7ZS50aHJlZWNpcmNsZWludmVyc2VzYW5zc2VyaWY9MTAxMjQ7ZS50aHJlZWRldmE9MjQwOTtlLnRocmVlZWlnaHRocz04NTQwO2UudGhyZWVndWphcmF0aT0yNzkzO2UudGhyZWVndXJtdWtoaT0yNjY1O2UudGhyZWVoYWNrYXJhYmljPTE2MzU7ZS50aHJlZWhhbmd6aG91PTEyMzIzO2UudGhyZWVpZGVvZ3JhcGhpY3BhcmVuPTEyODM0O2UudGhyZWVpbmZlcmlvcj04MzIzO2UudGhyZWVtb25vc3BhY2U9NjUyOTk7ZS50aHJlZW51bWVyYXRvcmJlbmdhbGk9MjU1MDtlLnRocmVlb2xkc3R5bGU9NjMyODM7ZS50aHJlZXBhcmVuPTkzMzQ7ZS50aHJlZXBlcmlvZD05MzU0O2UudGhyZWVwZXJzaWFuPTE3Nzk7ZS50aHJlZXF1YXJ0ZXJzPTE5MDtlLnRocmVlcXVhcnRlcnNlbWRhc2g9NjMxOTg7ZS50aHJlZXJvbWFuPTg1NjI7ZS50aHJlZXN1cGVyaW9yPTE3OTtlLnRocmVldGhhaT0zNjY3O2UudGh6c3F1YXJlPTEzMjA0O2UudGloaXJhZ2FuYT0xMjM4NTtlLnRpa2F0YWthbmE9MTI0ODE7ZS50aWthdGFrYW5haGFsZndpZHRoPTY1NDA5O2UudGlrZXV0YWNpcmNsZWtvcmVhbj0xMjkxMjtlLnRpa2V1dGFwYXJlbmtvcmVhbj0xMjgxNjtlLnRpa2V1dGNpcmNsZWtvcmVhbj0xMjg5ODtlLnRpa2V1dGtvcmVhbj0xMjU5OTtlLnRpa2V1dHBhcmVua29yZWFuPTEyODAyO2UudGlsZGU9NzMyO2UudGlsZGViZWxvd2NtYj04MTY7ZS50aWxkZWNtYj03NzE7ZS50aWxkZWNvbWI9NzcxO2UudGlsZGVkb3VibGVjbWI9ODY0O2UudGlsZGVvcGVyYXRvcj04NzY0O2UudGlsZGVvdmVybGF5Y21iPTgyMDtlLnRpbGRldmVydGljYWxjbWI9ODMwO2UudGltZXNjaXJjbGU9ODg1NTtlLnRpcGVoYWhlYnJldz0xNDMwO2UudGlwZWhhbGVmdGhlYnJldz0xNDMwO2UudGlwcGlndXJtdWtoaT0yNjcyO2UudGl0bG9jeXJpbGxpY2NtYj0xMTU1O2UudGl3bmFybWVuaWFuPTE0MDc7ZS50bGluZWJlbG93PTc3OTE7ZS50bW9ub3NwYWNlPTY1MzY0O2UudG9hcm1lbmlhbj0xMzg1O2UudG9oaXJhZ2FuYT0xMjM5MjtlLnRva2F0YWthbmE9MTI0ODg7ZS50b2thdGFrYW5haGFsZndpZHRoPTY1NDEyO2UudG9uZWJhcmV4dHJhaGlnaG1vZD03NDE7ZS50b25lYmFyZXh0cmFsb3dtb2Q9NzQ1O2UudG9uZWJhcmhpZ2htb2Q9NzQyO2UudG9uZWJhcmxvd21vZD03NDQ7ZS50b25lYmFybWlkbW9kPTc0MztlLnRvbmVmaXZlPTQ0NTtlLnRvbmVzaXg9Mzg5O2UudG9uZXR3bz00MjQ7ZS50b25vcz05MDA7ZS50b25zcXVhcmU9MTMwOTU7ZS50b3BhdGFrdGhhaT0zNTk5O2UudG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0PTEyMzA4O2UudG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0c21hbGw9NjUxMTc7ZS50b3J0b2lzZXNoZWxsYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA4MTtlLnRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHQ9MTIzMDk7ZS50b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0c21hbGw9NjUxMTg7ZS50b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0dmVydGljYWw9NjUwODI7ZS50b3Rhb3RoYWk9MzYwNTtlLnRwYWxhdGFsaG9vaz00Mjc7ZS50cGFyZW49OTM5MTtlLnRyYWRlbWFyaz04NDgyO2UudHJhZGVtYXJrc2Fucz02MzcyMjtlLnRyYWRlbWFya3NlcmlmPTYzMTk1O2UudHJldHJvZmxleGhvb2s9NjQ4O2UudHJpYWdkbj05NjYwO2UudHJpYWdsZj05NjY4O2UudHJpYWdydD05NjU4O2UudHJpYWd1cD05NjUwO2UudHM9Njc4O2UudHNhZGk9MTUxMDtlLnRzYWRpZGFnZXNoPTY0MzI2O2UudHNhZGlkYWdlc2hoZWJyZXc9NjQzMjY7ZS50c2FkaWhlYnJldz0xNTEwO2UudHNlY3lyaWxsaWM9MTA5NDtlLnRzZXJlPTE0NjE7ZS50c2VyZTEyPTE0NjE7ZS50c2VyZTFlPTE0NjE7ZS50c2VyZTJiPTE0NjE7ZS50c2VyZWhlYnJldz0xNDYxO2UudHNlcmVuYXJyb3doZWJyZXc9MTQ2MTtlLnRzZXJlcXVhcnRlcmhlYnJldz0xNDYxO2UudHNlcmV3aWRlaGVicmV3PTE0NjE7ZS50c2hlY3lyaWxsaWM9MTExNTtlLnRzdXBlcmlvcj02MzIxOTtlLnR0YWJlbmdhbGk9MjQ2MztlLnR0YWRldmE9MjMzNTtlLnR0YWd1amFyYXRpPTI3MTk7ZS50dGFndXJtdWtoaT0yNTkxO2UudHRlaGFyYWJpYz0xNjU3O2UudHRlaGZpbmFsYXJhYmljPTY0MzU5O2UudHRlaGluaXRpYWxhcmFiaWM9NjQzNjA7ZS50dGVobWVkaWFsYXJhYmljPTY0MzYxO2UudHRoYWJlbmdhbGk9MjQ2NDtlLnR0aGFkZXZhPTIzMzY7ZS50dGhhZ3VqYXJhdGk9MjcyMDtlLnR0aGFndXJtdWtoaT0yNTkyO2UudHR1cm5lZD02NDc7ZS50dWhpcmFnYW5hPTEyMzg4O2UudHVrYXRha2FuYT0xMjQ4NDtlLnR1a2F0YWthbmFoYWxmd2lkdGg9NjU0MTA7ZS50dXNtYWxsaGlyYWdhbmE9MTIzODc7ZS50dXNtYWxsa2F0YWthbmE9MTI0ODM7ZS50dXNtYWxsa2F0YWthbmFoYWxmd2lkdGg9NjUzOTE7ZS50d2VsdmVjaXJjbGU9OTMyMztlLnR3ZWx2ZXBhcmVuPTkzNDM7ZS50d2VsdmVwZXJpb2Q9OTM2MztlLnR3ZWx2ZXJvbWFuPTg1NzE7ZS50d2VudHljaXJjbGU9OTMzMTtlLnR3ZW50eWhhbmd6aG91PTIxMzE2O2UudHdlbnR5cGFyZW49OTM1MTtlLnR3ZW50eXBlcmlvZD05MzcxO2UudHdvPTUwO2UudHdvYXJhYmljPTE2MzQ7ZS50d29iZW5nYWxpPTI1MzY7ZS50d29jaXJjbGU9OTMxMztlLnR3b2NpcmNsZWludmVyc2VzYW5zc2VyaWY9MTAxMjM7ZS50d29kZXZhPTI0MDg7ZS50d29kb3RlbmxlYWRlcj04MjI5O2UudHdvZG90bGVhZGVyPTgyMjk7ZS50d29kb3RsZWFkZXJ2ZXJ0aWNhbD02NTA3MjtlLnR3b2d1amFyYXRpPTI3OTI7ZS50d29ndXJtdWtoaT0yNjY0O2UudHdvaGFja2FyYWJpYz0xNjM0O2UudHdvaGFuZ3pob3U9MTIzMjI7ZS50d29pZGVvZ3JhcGhpY3BhcmVuPTEyODMzO2UudHdvaW5mZXJpb3I9ODMyMjtlLnR3b21vbm9zcGFjZT02NTI5ODtlLnR3b251bWVyYXRvcmJlbmdhbGk9MjU0OTtlLnR3b29sZHN0eWxlPTYzMjgyO2UudHdvcGFyZW49OTMzMztlLnR3b3BlcmlvZD05MzUzO2UudHdvcGVyc2lhbj0xNzc4O2UudHdvcm9tYW49ODU2MTtlLnR3b3N0cm9rZT00NDM7ZS50d29zdXBlcmlvcj0xNzg7ZS50d290aGFpPTM2NjY7ZS50d290aGlyZHM9ODUzMjtlLnU9MTE3O2UudWFjdXRlPTI1MDtlLnViYXI9NjQ5O2UudWJlbmdhbGk9MjQ0MTtlLnVib3BvbW9mbz0xMjU4NDtlLnVicmV2ZT0zNjU7ZS51Y2Fyb249NDY4O2UudWNpcmNsZT05NDQ0O2UudWNpcmN1bWZsZXg9MjUxO2UudWNpcmN1bWZsZXhiZWxvdz03Nzk5O2UudWN5cmlsbGljPTEwOTE7ZS51ZGF0dGFkZXZhPTIzODU7ZS51ZGJsYWN1dGU9MzY5O2UudWRibGdyYXZlPTUzMztlLnVkZXZhPTIzMTM7ZS51ZGllcmVzaXM9MjUyO2UudWRpZXJlc2lzYWN1dGU9NDcyO2UudWRpZXJlc2lzYmVsb3c9Nzc5NTtlLnVkaWVyZXNpc2Nhcm9uPTQ3NDtlLnVkaWVyZXNpc2N5cmlsbGljPTEyNjU7ZS51ZGllcmVzaXNncmF2ZT00NzY7ZS51ZGllcmVzaXNtYWNyb249NDcwO2UudWRvdGJlbG93PTc5MDk7ZS51Z3JhdmU9MjQ5O2UudWd1amFyYXRpPTI2OTc7ZS51Z3VybXVraGk9MjU2OTtlLnVoaXJhZ2FuYT0xMjM1ODtlLnVob29rYWJvdmU9NzkxMTtlLnVob3JuPTQzMjtlLnVob3JuYWN1dGU9NzkxMztlLnVob3JuZG90YmVsb3c9NzkyMTtlLnVob3JuZ3JhdmU9NzkxNTtlLnVob3JuaG9va2Fib3ZlPTc5MTc7ZS51aG9ybnRpbGRlPTc5MTk7ZS51aHVuZ2FydW1sYXV0PTM2OTtlLnVodW5nYXJ1bWxhdXRjeXJpbGxpYz0xMjY3O2UudWludmVydGVkYnJldmU9NTM1O2UudWthdGFrYW5hPTEyNDU0O2UudWthdGFrYW5haGFsZndpZHRoPTY1Mzk1O2UudWtjeXJpbGxpYz0xMTQ1O2UudWtvcmVhbj0xMjYzNjtlLnVtYWNyb249MzYzO2UudW1hY3JvbmN5cmlsbGljPTEyNjM7ZS51bWFjcm9uZGllcmVzaXM9NzgwMztlLnVtYXRyYWd1cm11a2hpPTI2MjU7ZS51bW9ub3NwYWNlPTY1MzY1O2UudW5kZXJzY29yZT05NTtlLnVuZGVyc2NvcmVkYmw9ODIxNTtlLnVuZGVyc2NvcmVtb25vc3BhY2U9NjUzNDM7ZS51bmRlcnNjb3JldmVydGljYWw9NjUwNzU7ZS51bmRlcnNjb3Jld2F2eT02NTEwMztlLnVuaW9uPTg3NDY7ZS51bml2ZXJzYWw9ODcwNDtlLnVvZ29uZWs9MzcxO2UudXBhcmVuPTkzOTI7ZS51cGJsb2NrPTk2MDA7ZS51cHBlcmRvdGhlYnJldz0xNDc2O2UudXBzaWxvbj05NjU7ZS51cHNpbG9uZGllcmVzaXM9OTcxO2UudXBzaWxvbmRpZXJlc2lzdG9ub3M9OTQ0O2UudXBzaWxvbmxhdGluPTY1MDtlLnVwc2lsb250b25vcz05NzM7ZS51cHRhY2tiZWxvd2NtYj03OTc7ZS51cHRhY2ttb2Q9NzI0O2UudXJhZ3VybXVraGk9MjY3NTtlLnVyaW5nPTM2NztlLnVzaG9ydGN5cmlsbGljPTExMTg7ZS51c21hbGxoaXJhZ2FuYT0xMjM1NztlLnVzbWFsbGthdGFrYW5hPTEyNDUzO2UudXNtYWxsa2F0YWthbmFoYWxmd2lkdGg9NjUzODU7ZS51c3RyYWlnaHRjeXJpbGxpYz0xMTk5O2UudXN0cmFpZ2h0c3Ryb2tlY3lyaWxsaWM9MTIwMTtlLnV0aWxkZT0zNjE7ZS51dGlsZGVhY3V0ZT03ODAxO2UudXRpbGRlYmVsb3c9Nzc5NztlLnV1YmVuZ2FsaT0yNDQyO2UudXVkZXZhPTIzMTQ7ZS51dWd1amFyYXRpPTI2OTg7ZS51dWd1cm11a2hpPTI1NzA7ZS51dW1hdHJhZ3VybXVraGk9MjYyNjtlLnV1dm93ZWxzaWduYmVuZ2FsaT0yNDk4O2UudXV2b3dlbHNpZ25kZXZhPTIzNzA7ZS51dXZvd2Vsc2lnbmd1amFyYXRpPTI3NTQ7ZS51dm93ZWxzaWduYmVuZ2FsaT0yNDk3O2UudXZvd2Vsc2lnbmRldmE9MjM2OTtlLnV2b3dlbHNpZ25ndWphcmF0aT0yNzUzO2Uudj0xMTg7ZS52YWRldmE9MjM1NztlLnZhZ3VqYXJhdGk9Mjc0MTtlLnZhZ3VybXVraGk9MjYxMztlLnZha2F0YWthbmE9MTI1MzU7ZS52YXY9MTQ5MztlLnZhdmRhZ2VzaD02NDMwOTtlLnZhdmRhZ2VzaDY1PTY0MzA5O2UudmF2ZGFnZXNoaGVicmV3PTY0MzA5O2UudmF2aGVicmV3PTE0OTM7ZS52YXZob2xhbT02NDMzMTtlLnZhdmhvbGFtaGVicmV3PTY0MzMxO2UudmF2dmF2aGVicmV3PTE1MjA7ZS52YXZ5b2RoZWJyZXc9MTUyMTtlLnZjaXJjbGU9OTQ0NTtlLnZkb3RiZWxvdz03ODA3O2UudmVjeXJpbGxpYz0xMDc0O2UudmVoYXJhYmljPTE3MDA7ZS52ZWhmaW5hbGFyYWJpYz02NDM2MztlLnZlaGluaXRpYWxhcmFiaWM9NjQzNjQ7ZS52ZWhtZWRpYWxhcmFiaWM9NjQzNjU7ZS52ZWthdGFrYW5hPTEyNTM3O2UudmVudXM9OTc5MjtlLnZlcnRpY2FsYmFyPTEyNDtlLnZlcnRpY2FsbGluZWFib3ZlY21iPTc4MTtlLnZlcnRpY2FsbGluZWJlbG93Y21iPTgwOTtlLnZlcnRpY2FsbGluZWxvd21vZD03MTY7ZS52ZXJ0aWNhbGxpbmVtb2Q9NzEyO2UudmV3YXJtZW5pYW49MTQwNjtlLnZob29rPTY1MTtlLnZpa2F0YWthbmE9MTI1MzY7ZS52aXJhbWFiZW5nYWxpPTI1MDk7ZS52aXJhbWFkZXZhPTIzODE7ZS52aXJhbWFndWphcmF0aT0yNzY1O2UudmlzYXJnYWJlbmdhbGk9MjQzNTtlLnZpc2FyZ2FkZXZhPTIzMDc7ZS52aXNhcmdhZ3VqYXJhdGk9MjY5MTtlLnZtb25vc3BhY2U9NjUzNjY7ZS52b2FybWVuaWFuPTE0MDA7ZS52b2ljZWRpdGVyYXRpb25oaXJhZ2FuYT0xMjQ0NjtlLnZvaWNlZGl0ZXJhdGlvbmthdGFrYW5hPTEyNTQyO2Uudm9pY2VkbWFya2thbmE9MTI0NDM7ZS52b2ljZWRtYXJra2FuYWhhbGZ3aWR0aD02NTQzODtlLnZva2F0YWthbmE9MTI1Mzg7ZS52cGFyZW49OTM5MztlLnZ0aWxkZT03ODA1O2UudnR1cm5lZD02NTI7ZS52dWhpcmFnYW5hPTEyNDM2O2UudnVrYXRha2FuYT0xMjUzMjtlLnc9MTE5O2Uud2FjdXRlPTc4MTE7ZS53YWVrb3JlYW49MTI2MzM7ZS53YWhpcmFnYW5hPTEyNDMxO2Uud2FrYXRha2FuYT0xMjUyNztlLndha2F0YWthbmFoYWxmd2lkdGg9NjU0MzY7ZS53YWtvcmVhbj0xMjYzMjtlLndhc21hbGxoaXJhZ2FuYT0xMjQzMDtlLndhc21hbGxrYXRha2FuYT0xMjUyNjtlLndhdHRvc3F1YXJlPTEzMTQzO2Uud2F2ZWRhc2g9MTIzMTY7ZS53YXZ5dW5kZXJzY29yZXZlcnRpY2FsPTY1MDc2O2Uud2F3YXJhYmljPTE2MDg7ZS53YXdmaW5hbGFyYWJpYz02NTI2MjtlLndhd2hhbXphYWJvdmVhcmFiaWM9MTU3MjtlLndhd2hhbXphYWJvdmVmaW5hbGFyYWJpYz02NTE1ODtlLndic3F1YXJlPTEzMjc3O2Uud2NpcmNsZT05NDQ2O2Uud2NpcmN1bWZsZXg9MzczO2Uud2RpZXJlc2lzPTc4MTM7ZS53ZG90YWNjZW50PTc4MTU7ZS53ZG90YmVsb3c9NzgxNztlLndlaGlyYWdhbmE9MTI0MzM7ZS53ZWllcnN0cmFzcz04NDcyO2Uud2VrYXRha2FuYT0xMjUyOTtlLndla29yZWFuPTEyNjM4O2Uud2Vva29yZWFuPTEyNjM3O2Uud2dyYXZlPTc4MDk7ZS53aGl0ZWJ1bGxldD05NzAyO2Uud2hpdGVjaXJjbGU9OTY3NTtlLndoaXRlY2lyY2xlaW52ZXJzZT05Njg5O2Uud2hpdGVjb3JuZXJicmFja2V0bGVmdD0xMjMwMjtlLndoaXRlY29ybmVyYnJhY2tldGxlZnR2ZXJ0aWNhbD02NTA5MTtlLndoaXRlY29ybmVyYnJhY2tldHJpZ2h0PTEyMzAzO2Uud2hpdGVjb3JuZXJicmFja2V0cmlnaHR2ZXJ0aWNhbD02NTA5MjtlLndoaXRlZGlhbW9uZD05NjcxO2Uud2hpdGVkaWFtb25kY29udGFpbmluZ2JsYWNrc21hbGxkaWFtb25kPTk2NzI7ZS53aGl0ZWRvd25wb2ludGluZ3NtYWxsdHJpYW5nbGU9OTY2MztlLndoaXRlZG93bnBvaW50aW5ndHJpYW5nbGU9OTY2MTtlLndoaXRlbGVmdHBvaW50aW5nc21hbGx0cmlhbmdsZT05NjY3O2Uud2hpdGVsZWZ0cG9pbnRpbmd0cmlhbmdsZT05NjY1O2Uud2hpdGVsZW50aWN1bGFyYnJhY2tldGxlZnQ9MTIzMTA7ZS53aGl0ZWxlbnRpY3VsYXJicmFja2V0cmlnaHQ9MTIzMTE7ZS53aGl0ZXJpZ2h0cG9pbnRpbmdzbWFsbHRyaWFuZ2xlPTk2NTc7ZS53aGl0ZXJpZ2h0cG9pbnRpbmd0cmlhbmdsZT05NjU1O2Uud2hpdGVzbWFsbHNxdWFyZT05NjQzO2Uud2hpdGVzbWlsaW5nZmFjZT05Nzg2O2Uud2hpdGVzcXVhcmU9OTYzMztlLndoaXRlc3Rhcj05NzM0O2Uud2hpdGV0ZWxlcGhvbmU9OTc0MztlLndoaXRldG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0PTEyMzEyO2Uud2hpdGV0b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0PTEyMzEzO2Uud2hpdGV1cHBvaW50aW5nc21hbGx0cmlhbmdsZT05NjUzO2Uud2hpdGV1cHBvaW50aW5ndHJpYW5nbGU9OTY1MTtlLndpaGlyYWdhbmE9MTI0MzI7ZS53aWthdGFrYW5hPTEyNTI4O2Uud2lrb3JlYW49MTI2Mzk7ZS53bW9ub3NwYWNlPTY1MzY3O2Uud29oaXJhZ2FuYT0xMjQzNDtlLndva2F0YWthbmE9MTI1MzA7ZS53b2thdGFrYW5haGFsZndpZHRoPTY1MzgyO2Uud29uPTgzNjE7ZS53b25tb25vc3BhY2U9NjU1MTA7ZS53b3dhZW50aGFpPTM2MjM7ZS53cGFyZW49OTM5NDtlLndyaW5nPTc4MzI7ZS53c3VwZXJpb3I9Njk1O2Uud3R1cm5lZD02NTM7ZS53eW5uPTQ0NztlLng9MTIwO2UueGFib3ZlY21iPTgyOTtlLnhib3BvbW9mbz0xMjU2MjtlLnhjaXJjbGU9OTQ0NztlLnhkaWVyZXNpcz03ODIxO2UueGRvdGFjY2VudD03ODE5O2UueGVoYXJtZW5pYW49MTM4OTtlLnhpPTk1ODtlLnhtb25vc3BhY2U9NjUzNjg7ZS54cGFyZW49OTM5NTtlLnhzdXBlcmlvcj03Mzk7ZS55PTEyMTtlLnlhYWRvc3F1YXJlPTEzMTM0O2UueWFiZW5nYWxpPTI0Nzk7ZS55YWN1dGU9MjUzO2UueWFkZXZhPTIzNTE7ZS55YWVrb3JlYW49MTI2MjY7ZS55YWd1amFyYXRpPTI3MzU7ZS55YWd1cm11a2hpPTI2MDc7ZS55YWhpcmFnYW5hPTEyNDIwO2UueWFrYXRha2FuYT0xMjUxNjtlLnlha2F0YWthbmFoYWxmd2lkdGg9NjU0Mjg7ZS55YWtvcmVhbj0xMjYyNTtlLnlhbWFra2FudGhhaT0zNjYyO2UueWFzbWFsbGhpcmFnYW5hPTEyNDE5O2UueWFzbWFsbGthdGFrYW5hPTEyNTE1O2UueWFzbWFsbGthdGFrYW5haGFsZndpZHRoPTY1Mzg4O2UueWF0Y3lyaWxsaWM9MTEyMztlLnljaXJjbGU9OTQ0ODtlLnljaXJjdW1mbGV4PTM3NTtlLnlkaWVyZXNpcz0yNTU7ZS55ZG90YWNjZW50PTc4MjM7ZS55ZG90YmVsb3c9NzkyNTtlLnllaGFyYWJpYz0xNjEwO2UueWVoYmFycmVlYXJhYmljPTE3NDY7ZS55ZWhiYXJyZWVmaW5hbGFyYWJpYz02NDQzMTtlLnllaGZpbmFsYXJhYmljPTY1MjY2O2UueWVoaGFtemFhYm92ZWFyYWJpYz0xNTc0O2UueWVoaGFtemFhYm92ZWZpbmFsYXJhYmljPTY1MTYyO2UueWVoaGFtemFhYm92ZWluaXRpYWxhcmFiaWM9NjUxNjM7ZS55ZWhoYW16YWFib3ZlbWVkaWFsYXJhYmljPTY1MTY0O2UueWVoaW5pdGlhbGFyYWJpYz02NTI2NztlLnllaG1lZGlhbGFyYWJpYz02NTI2ODtlLnllaG1lZW1pbml0aWFsYXJhYmljPTY0NzMzO2UueWVobWVlbWlzb2xhdGVkYXJhYmljPTY0NjAwO2UueWVobm9vbmZpbmFsYXJhYmljPTY0NjYwO2UueWVodGhyZWVkb3RzYmVsb3dhcmFiaWM9MTc0NTtlLnlla29yZWFuPTEyNjMwO2UueWVuPTE2NTtlLnllbm1vbm9zcGFjZT02NTUwOTtlLnllb2tvcmVhbj0xMjYyOTtlLnllb3JpbmhpZXVoa29yZWFuPTEyNjc4O2UueWVyYWhiZW55b21vaGVicmV3PTE0NTA7ZS55ZXJhaGJlbnlvbW9sZWZ0aGVicmV3PTE0NTA7ZS55ZXJpY3lyaWxsaWM9MTA5OTtlLnllcnVkaWVyZXNpc2N5cmlsbGljPTEyNzM7ZS55ZXNpZXVuZ2tvcmVhbj0xMjY3MztlLnllc2lldW5ncGFuc2lvc2tvcmVhbj0xMjY3NTtlLnllc2lldW5nc2lvc2tvcmVhbj0xMjY3NDtlLnlldGl2aGVicmV3PTE0MzQ7ZS55Z3JhdmU9NzkyMztlLnlob29rPTQzNjtlLnlob29rYWJvdmU9NzkyNztlLnlpYXJtZW5pYW49MTM5NztlLnlpY3lyaWxsaWM9MTExMTtlLnlpa29yZWFuPTEyNjQyO2UueWlueWFuZz05Nzc1O2UueWl3bmFybWVuaWFuPTE0MTA7ZS55bW9ub3NwYWNlPTY1MzY5O2UueW9kPTE0OTc7ZS55b2RkYWdlc2g9NjQzMTM7ZS55b2RkYWdlc2hoZWJyZXc9NjQzMTM7ZS55b2RoZWJyZXc9MTQ5NztlLnlvZHlvZGhlYnJldz0xNTIyO2UueW9keW9kcGF0YWhoZWJyZXc9NjQyODc7ZS55b2hpcmFnYW5hPTEyNDI0O2UueW9pa29yZWFuPTEyNjgxO2UueW9rYXRha2FuYT0xMjUyMDtlLnlva2F0YWthbmFoYWxmd2lkdGg9NjU0MzA7ZS55b2tvcmVhbj0xMjYzNTtlLnlvc21hbGxoaXJhZ2FuYT0xMjQyMztlLnlvc21hbGxrYXRha2FuYT0xMjUxOTtlLnlvc21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM5MDtlLnlvdGdyZWVrPTEwMTE7ZS55b3lhZWtvcmVhbj0xMjY4MDtlLnlveWFrb3JlYW49MTI2Nzk7ZS55b3lha3RoYWk9MzYxODtlLnlveWluZ3RoYWk9MzU5NztlLnlwYXJlbj05Mzk2O2UueXBvZ2VncmFtbWVuaT04OTA7ZS55cG9nZWdyYW1tZW5pZ3JlZWtjbWI9ODM3O2UueXI9NDIyO2UueXJpbmc9NzgzMztlLnlzdXBlcmlvcj02OTY7ZS55dGlsZGU9NzkyOTtlLnl0dXJuZWQ9NjU0O2UueXVoaXJhZ2FuYT0xMjQyMjtlLnl1aWtvcmVhbj0xMjY4NDtlLnl1a2F0YWthbmE9MTI1MTg7ZS55dWthdGFrYW5haGFsZndpZHRoPTY1NDI5O2UueXVrb3JlYW49MTI2NDA7ZS55dXNiaWdjeXJpbGxpYz0xMTMxO2UueXVzYmlnaW90aWZpZWRjeXJpbGxpYz0xMTMzO2UueXVzbGl0dGxlY3lyaWxsaWM9MTEyNztlLnl1c2xpdHRsZWlvdGlmaWVkY3lyaWxsaWM9MTEyOTtlLnl1c21hbGxoaXJhZ2FuYT0xMjQyMTtlLnl1c21hbGxrYXRha2FuYT0xMjUxNztlLnl1c21hbGxrYXRha2FuYWhhbGZ3aWR0aD02NTM4OTtlLnl1eWVrb3JlYW49MTI2ODM7ZS55dXllb2tvcmVhbj0xMjY4MjtlLnl5YWJlbmdhbGk9MjUyNztlLnl5YWRldmE9MjM5OTtlLno9MTIyO2UuemFhcm1lbmlhbj0xMzgyO2UuemFjdXRlPTM3ODtlLnphZGV2YT0yMzk1O2UuemFndXJtdWtoaT0yNjUxO2UuemFoYXJhYmljPTE1OTI7ZS56YWhmaW5hbGFyYWJpYz02NTIyMjtlLnphaGluaXRpYWxhcmFiaWM9NjUyMjM7ZS56YWhpcmFnYW5hPTEyMzc0O2UuemFobWVkaWFsYXJhYmljPTY1MjI0O2UuemFpbmFyYWJpYz0xNTg2O2UuemFpbmZpbmFsYXJhYmljPTY1MjAwO2UuemFrYXRha2FuYT0xMjQ3MDtlLnphcWVmZ2Fkb2xoZWJyZXc9MTQyOTtlLnphcWVmcWF0YW5oZWJyZXc9MTQyODtlLnphcnFhaGVicmV3PTE0MzI7ZS56YXlpbj0xNDk0O2UuemF5aW5kYWdlc2g9NjQzMTA7ZS56YXlpbmRhZ2VzaGhlYnJldz02NDMxMDtlLnpheWluaGVicmV3PTE0OTQ7ZS56Ym9wb21vZm89MTI1Njc7ZS56Y2Fyb249MzgyO2UuemNpcmNsZT05NDQ5O2UuemNpcmN1bWZsZXg9NzgyNTtlLnpjdXJsPTY1NztlLnpkb3Q9MzgwO2UuemRvdGFjY2VudD0zODA7ZS56ZG90YmVsb3c9NzgyNztlLnplY3lyaWxsaWM9MTA3OTtlLnplZGVzY2VuZGVyY3lyaWxsaWM9MTE3NztlLnplZGllcmVzaXNjeXJpbGxpYz0xMjQ3O2UuemVoaXJhZ2FuYT0xMjM4MDtlLnpla2F0YWthbmE9MTI0NzY7ZS56ZXJvPTQ4O2UuemVyb2FyYWJpYz0xNjMyO2UuemVyb2JlbmdhbGk9MjUzNDtlLnplcm9kZXZhPTI0MDY7ZS56ZXJvZ3VqYXJhdGk9Mjc5MDtlLnplcm9ndXJtdWtoaT0yNjYyO2UuemVyb2hhY2thcmFiaWM9MTYzMjtlLnplcm9pbmZlcmlvcj04MzIwO2UuemVyb21vbm9zcGFjZT02NTI5NjtlLnplcm9vbGRzdHlsZT02MzI4MDtlLnplcm9wZXJzaWFuPTE3NzY7ZS56ZXJvc3VwZXJpb3I9ODMwNDtlLnplcm90aGFpPTM2NjQ7ZS56ZXJvd2lkdGhqb2luZXI9NjUyNzk7ZS56ZXJvd2lkdGhub25qb2luZXI9ODIwNDtlLnplcm93aWR0aHNwYWNlPTgyMDM7ZS56ZXRhPTk1MDtlLnpoYm9wb21vZm89MTI1NjM7ZS56aGVhcm1lbmlhbj0xMzg2O2UuemhlYnJldmVjeXJpbGxpYz0xMjE4O2UuemhlY3lyaWxsaWM9MTA3ODtlLnpoZWRlc2NlbmRlcmN5cmlsbGljPTExNzU7ZS56aGVkaWVyZXNpc2N5cmlsbGljPTEyNDU7ZS56aWhpcmFnYW5hPTEyMzc2O2UuemlrYXRha2FuYT0xMjQ3MjtlLnppbm9yaGVicmV3PTE0NTQ7ZS56bGluZWJlbG93PTc4Mjk7ZS56bW9ub3NwYWNlPTY1MzcwO2Uuem9oaXJhZ2FuYT0xMjM4MjtlLnpva2F0YWthbmE9MTI0Nzg7ZS56cGFyZW49OTM5NztlLnpyZXRyb2ZsZXhob29rPTY1NjtlLnpzdHJva2U9NDM4O2UuenVoaXJhZ2FuYT0xMjM3ODtlLnp1a2F0YWthbmE9MTI0NzQ7ZVsiLm5vdGRlZiJdPTA7ZS5hbmdicmFja2V0bGVmdGJpZz05MDAxO2UuYW5nYnJhY2tldGxlZnRCaWc9OTAwMTtlLmFuZ2JyYWNrZXRsZWZ0YmlnZz05MDAxO2UuYW5nYnJhY2tldGxlZnRCaWdnPTkwMDE7ZS5hbmdicmFja2V0cmlnaHRCaWc9OTAwMjtlLmFuZ2JyYWNrZXRyaWdodGJpZz05MDAyO2UuYW5nYnJhY2tldHJpZ2h0QmlnZz05MDAyO2UuYW5nYnJhY2tldHJpZ2h0YmlnZz05MDAyO2UuYXJyb3dob29rbGVmdD04NjE4O2UuYXJyb3dob29rcmlnaHQ9ODYxNztlLmFycm93bGVmdHRvcGhhbGY9ODYzNjtlLmFycm93bGVmdGJvdGhhbGY9ODYzNztlLmFycm93bm9ydGhlYXN0PTg1OTk7ZS5hcnJvd25vcnRod2VzdD04NTk4O2UuYXJyb3dyaWdodHRvcGhhbGY9ODY0MDtlLmFycm93cmlnaHRib3RoYWxmPTg2NDE7ZS5hcnJvd3NvdXRoZWFzdD04NjAwO2UuYXJyb3dzb3V0aHdlc3Q9ODYwMTtlLmJhY2tzbGFzaGJpZz04NzI2O2UuYmFja3NsYXNoQmlnPTg3MjY7ZS5iYWNrc2xhc2hCaWdnPTg3MjY7ZS5iYWNrc2xhc2hiaWdnPTg3MjY7ZS5iYXJkYmw9ODIxNDtlLmJyYWNlaHRpcGRvd25sZWZ0PTY1MDc5O2UuYnJhY2VodGlwZG93bnJpZ2h0PTY1MDc5O2UuYnJhY2VodGlwdXBsZWZ0PTY1MDgwO2UuYnJhY2VodGlwdXByaWdodD02NTA4MDtlLmJyYWNlbGVmdEJpZz0xMjM7ZS5icmFjZWxlZnRiaWc9MTIzO2UuYnJhY2VsZWZ0YmlnZz0xMjM7ZS5icmFjZWxlZnRCaWdnPTEyMztlLmJyYWNlcmlnaHRCaWc9MTI1O2UuYnJhY2VyaWdodGJpZz0xMjU7ZS5icmFjZXJpZ2h0YmlnZz0xMjU7ZS5icmFjZXJpZ2h0QmlnZz0xMjU7ZS5icmFja2V0bGVmdGJpZz05MTtlLmJyYWNrZXRsZWZ0QmlnPTkxO2UuYnJhY2tldGxlZnRiaWdnPTkxO2UuYnJhY2tldGxlZnRCaWdnPTkxO2UuYnJhY2tldHJpZ2h0QmlnPTkzO2UuYnJhY2tldHJpZ2h0YmlnPTkzO2UuYnJhY2tldHJpZ2h0YmlnZz05MztlLmJyYWNrZXRyaWdodEJpZ2c9OTM7ZS5jZWlsaW5nbGVmdGJpZz04OTY4O2UuY2VpbGluZ2xlZnRCaWc9ODk2ODtlLmNlaWxpbmdsZWZ0QmlnZz04OTY4O2UuY2VpbGluZ2xlZnRiaWdnPTg5Njg7ZS5jZWlsaW5ncmlnaHRiaWc9ODk2OTtlLmNlaWxpbmdyaWdodEJpZz04OTY5O2UuY2VpbGluZ3JpZ2h0YmlnZz04OTY5O2UuY2VpbGluZ3JpZ2h0QmlnZz04OTY5O2UuY2lyY2xlZG90ZGlzcGxheT04ODU3O2UuY2lyY2xlZG90dGV4dD04ODU3O2UuY2lyY2xlbXVsdGlwbHlkaXNwbGF5PTg4NTU7ZS5jaXJjbGVtdWx0aXBseXRleHQ9ODg1NTtlLmNpcmNsZXBsdXNkaXNwbGF5PTg4NTM7ZS5jaXJjbGVwbHVzdGV4dD04ODUzO2UuY29udGludGVncmFsZGlzcGxheT04NzUwO2UuY29udGludGVncmFsdGV4dD04NzUwO2UuY29wcm9kdWN0ZGlzcGxheT04NzIwO2UuY29wcm9kdWN0dGV4dD04NzIwO2UuZmxvb3JsZWZ0QmlnPTg5NzA7ZS5mbG9vcmxlZnRiaWc9ODk3MDtlLmZsb29ybGVmdGJpZ2c9ODk3MDtlLmZsb29ybGVmdEJpZ2c9ODk3MDtlLmZsb29ycmlnaHRiaWc9ODk3MTtlLmZsb29ycmlnaHRCaWc9ODk3MTtlLmZsb29ycmlnaHRCaWdnPTg5NzE7ZS5mbG9vcnJpZ2h0YmlnZz04OTcxO2UuaGF0d2lkZT03NzA7ZS5oYXR3aWRlcj03NzA7ZS5oYXR3aWRlc3Q9NzcwO2UuaW50ZXJjYWw9NzQ4ODtlLmludGVncmFsZGlzcGxheT04NzQ3O2UuaW50ZWdyYWx0ZXh0PTg3NDc7ZS5pbnRlcnNlY3Rpb25kaXNwbGF5PTg4OTg7ZS5pbnRlcnNlY3Rpb250ZXh0PTg4OTg7ZS5sb2dpY2FsYW5kZGlzcGxheT04NzQzO2UubG9naWNhbGFuZHRleHQ9ODc0MztlLmxvZ2ljYWxvcmRpc3BsYXk9ODc0NDtlLmxvZ2ljYWxvcnRleHQ9ODc0NDtlLnBhcmVubGVmdEJpZz00MDtlLnBhcmVubGVmdGJpZz00MDtlLnBhcmVubGVmdEJpZ2c9NDA7ZS5wYXJlbmxlZnRiaWdnPTQwO2UucGFyZW5yaWdodEJpZz00MTtlLnBhcmVucmlnaHRiaWc9NDE7ZS5wYXJlbnJpZ2h0QmlnZz00MTtlLnBhcmVucmlnaHRiaWdnPTQxO2UucHJpbWU9ODI0MjtlLnByb2R1Y3RkaXNwbGF5PTg3MTk7ZS5wcm9kdWN0dGV4dD04NzE5O2UucmFkaWNhbGJpZz04NzMwO2UucmFkaWNhbEJpZz04NzMwO2UucmFkaWNhbEJpZ2c9ODczMDtlLnJhZGljYWxiaWdnPTg3MzA7ZS5yYWRpY2FsYnQ9ODczMDtlLnJhZGljYWx0cD04NzMwO2UucmFkaWNhbHZlcnRleD04NzMwO2Uuc2xhc2hiaWc9NDc7ZS5zbGFzaEJpZz00NztlLnNsYXNoQmlnZz00NztlLnNsYXNoYmlnZz00NztlLnN1bW1hdGlvbmRpc3BsYXk9ODcyMTtlLnN1bW1hdGlvbnRleHQ9ODcyMTtlLnRpbGRld2lkZT03MzI7ZS50aWxkZXdpZGVyPTczMjtlLnRpbGRld2lkZXN0PTczMjtlLnVuaW9uZGlzcGxheT04ODk5O2UudW5pb25tdWx0aWRpc3BsYXk9ODg0NjtlLnVuaW9ubXVsdGl0ZXh0PTg4NDY7ZS51bmlvbnNxZGlzcGxheT04ODUyO2UudW5pb25zcXRleHQ9ODg1MjtlLnVuaW9udGV4dD04ODk5O2UudmV4dGVuZGRvdWJsZT04NzQxO2UudmV4dGVuZHNpbmdsZT04NzM5fSkscGE9Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2Uuc3BhY2U9MzI7ZS5hMT05OTg1O2UuYTI9OTk4NjtlLmEyMDI9OTk4NztlLmEzPTk5ODg7ZS5hND05NzQyO2UuYTU9OTk5MDtlLmExMTk9OTk5MTtlLmExMTg9OTk5MjtlLmExMTc9OTk5MztlLmExMT05NzU1O2UuYTEyPTk3NTg7ZS5hMTM9OTk5NjtlLmExND05OTk3O2UuYTE1PTk5OTg7ZS5hMTY9OTk5OTtlLmExMDU9MWU0O2UuYTE3PTEwMDAxO2UuYTE4PTEwMDAyO2UuYTE5PTEwMDAzO2UuYTIwPTEwMDA0O2UuYTIxPTEwMDA1O2UuYTIyPTEwMDA2O2UuYTIzPTEwMDA3O2UuYTI0PTEwMDA4O2UuYTI1PTEwMDA5O2UuYTI2PTEwMDEwO2UuYTI3PTEwMDExO2UuYTI4PTEwMDEyO2UuYTY9MTAwMTM7ZS5hNz0xMDAxNDtlLmE4PTEwMDE1O2UuYTk9MTAwMTY7ZS5hMTA9MTAwMTc7ZS5hMjk9MTAwMTg7ZS5hMzA9MTAwMTk7ZS5hMzE9MTAwMjA7ZS5hMzI9MTAwMjE7ZS5hMzM9MTAwMjI7ZS5hMzQ9MTAwMjM7ZS5hMzU9OTczMztlLmEzNj0xMDAyNTtlLmEzNz0xMDAyNjtlLmEzOD0xMDAyNztlLmEzOT0xMDAyODtlLmE0MD0xMDAyOTtlLmE0MT0xMDAzMDtlLmE0Mj0xMDAzMTtlLmE0Mz0xMDAzMjtlLmE0ND0xMDAzMztlLmE0NT0xMDAzNDtlLmE0Nj0xMDAzNTtlLmE0Nz0xMDAzNjtlLmE0OD0xMDAzNztlLmE0OT0xMDAzODtlLmE1MD0xMDAzOTtlLmE1MT0xMDA0MDtlLmE1Mj0xMDA0MTtlLmE1Mz0xMDA0MjtlLmE1ND0xMDA0MztlLmE1NT0xMDA0NDtlLmE1Nj0xMDA0NTtlLmE1Nz0xMDA0NjtlLmE1OD0xMDA0NztlLmE1OT0xMDA0ODtlLmE2MD0xMDA0OTtlLmE2MT0xMDA1MDtlLmE2Mj0xMDA1MTtlLmE2Mz0xMDA1MjtlLmE2ND0xMDA1MztlLmE2NT0xMDA1NDtlLmE2Nj0xMDA1NTtlLmE2Nz0xMDA1NjtlLmE2OD0xMDA1NztlLmE2OT0xMDA1ODtlLmE3MD0xMDA1OTtlLmE3MT05Njc5O2UuYTcyPTEwMDYxO2UuYTczPTk2MzI7ZS5hNzQ9MTAwNjM7ZS5hMjAzPTEwMDY0O2UuYTc1PTEwMDY1O2UuYTIwND0xMDA2NjtlLmE3Nj05NjUwO2UuYTc3PTk2NjA7ZS5hNzg9OTY3MDtlLmE3OT0xMDA3MDtlLmE4MT05Njg3O2UuYTgyPTEwMDcyO2UuYTgzPTEwMDczO2UuYTg0PTEwMDc0O2UuYTk3PTEwMDc1O2UuYTk4PTEwMDc2O2UuYTk5PTEwMDc3O2UuYTEwMD0xMDA3ODtlLmExMDE9MTAwODE7ZS5hMTAyPTEwMDgyO2UuYTEwMz0xMDA4MztlLmExMDQ9MTAwODQ7ZS5hMTA2PTEwMDg1O2UuYTEwNz0xMDA4NjtlLmExMDg9MTAwODc7ZS5hMTEyPTk4Mjc7ZS5hMTExPTk4MzA7ZS5hMTEwPTk4Mjk7ZS5hMTA5PTk4MjQ7ZS5hMTIwPTkzMTI7ZS5hMTIxPTkzMTM7ZS5hMTIyPTkzMTQ7ZS5hMTIzPTkzMTU7ZS5hMTI0PTkzMTY7ZS5hMTI1PTkzMTc7ZS5hMTI2PTkzMTg7ZS5hMTI3PTkzMTk7ZS5hMTI4PTkzMjA7ZS5hMTI5PTkzMjE7ZS5hMTMwPTEwMTAyO2UuYTEzMT0xMDEwMztlLmExMzI9MTAxMDQ7ZS5hMTMzPTEwMTA1O2UuYTEzND0xMDEwNjtlLmExMzU9MTAxMDc7ZS5hMTM2PTEwMTA4O2UuYTEzNz0xMDEwOTtlLmExMzg9MTAxMTA7ZS5hMTM5PTEwMTExO2UuYTE0MD0xMDExMjtlLmExNDE9MTAxMTM7ZS5hMTQyPTEwMTE0O2UuYTE0Mz0xMDExNTtlLmExNDQ9MTAxMTY7ZS5hMTQ1PTEwMTE3O2UuYTE0Nj0xMDExODtlLmExNDc9MTAxMTk7ZS5hMTQ4PTEwMTIwO2UuYTE0OT0xMDEyMTtlLmExNTA9MTAxMjI7ZS5hMTUxPTEwMTIzO2UuYTE1Mj0xMDEyNDtlLmExNTM9MTAxMjU7ZS5hMTU0PTEwMTI2O2UuYTE1NT0xMDEyNztlLmExNTY9MTAxMjg7ZS5hMTU3PTEwMTI5O2UuYTE1OD0xMDEzMDtlLmExNTk9MTAxMzE7ZS5hMTYwPTEwMTMyO2UuYTE2MT04NTk0O2UuYTE2Mz04NTk2O2UuYTE2ND04NTk3O2UuYTE5Nj0xMDEzNjtlLmExNjU9MTAxMzc7ZS5hMTkyPTEwMTM4O2UuYTE2Nj0xMDEzOTtlLmExNjc9MTAxNDA7ZS5hMTY4PTEwMTQxO2UuYTE2OT0xMDE0MjtlLmExNzA9MTAxNDM7ZS5hMTcxPTEwMTQ0O2UuYTE3Mj0xMDE0NTtlLmExNzM9MTAxNDY7ZS5hMTYyPTEwMTQ3O2UuYTE3ND0xMDE0ODtlLmExNzU9MTAxNDk7ZS5hMTc2PTEwMTUwO2UuYTE3Nz0xMDE1MTtlLmExNzg9MTAxNTI7ZS5hMTc5PTEwMTUzO2UuYTE5Mz0xMDE1NDtlLmExODA9MTAxNTU7ZS5hMTk5PTEwMTU2O2UuYTE4MT0xMDE1NztlLmEyMDA9MTAxNTg7ZS5hMTgyPTEwMTU5O2UuYTIwMT0xMDE2MTtlLmExODM9MTAxNjI7ZS5hMTg0PTEwMTYzO2UuYTE5Nz0xMDE2NDtlLmExODU9MTAxNjU7ZS5hMTk0PTEwMTY2O2UuYTE5OD0xMDE2NztlLmExODY9MTAxNjg7ZS5hMTk1PTEwMTY5O2UuYTE4Nz0xMDE3MDtlLmExODg9MTAxNzE7ZS5hMTg5PTEwMTcyO2UuYTE5MD0xMDE3MztlLmExOTE9MTAxNzQ7ZS5hODk9MTAwODg7ZS5hOTA9MTAwODk7ZS5hOTM9MTAwOTA7ZS5hOTQ9MTAwOTE7ZS5hOTE9MTAwOTI7ZS5hOTI9MTAwOTM7ZS5hMjA1PTEwMDk0O2UuYTg1PTEwMDk1O2UuYTIwNj0xMDA5NjtlLmE4Nj0xMDA5NztlLmE4Nz0xMDA5ODtlLmE4OD0xMDA5OTtlLmE5NT0xMDEwMDtlLmE5Nj0xMDEwMTtlWyIubm90ZGVmIl09MH0pLG1hPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlWzYzNzIxXT0xNjk7ZVs2MzE5M109MTY5O2VbNjM3MjBdPTE3NDtlWzYzMTk0XT0xNzQ7ZVs2MzcyMl09ODQ4MjtlWzYzMTk1XT04NDgyO2VbNjM3MjldPTkxMjc7ZVs2MzczMF09OTEyODtlWzYzNzMxXT05MTI5O2VbNjM3NDBdPTkxMzE7ZVs2Mzc0MV09OTEzMjtlWzYzNzQyXT05MTMzO2VbNjM3MjZdPTkxMjE7ZVs2MzcyN109OTEyMjtlWzYzNzI4XT05MTIzO2VbNjM3MzddPTkxMjQ7ZVs2MzczOF09OTEyNTtlWzYzNzM5XT05MTI2O2VbNjM3MjNdPTkxMTU7ZVs2MzcyNF09OTExNjtlWzYzNzI1XT05MTE3O2VbNjM3MzRdPTkxMTg7ZVs2MzczNV09OTExOTtlWzYzNzM2XT05MTIwfSk7ZnVuY3Rpb24gZ2V0VW5pY29kZUZvckdseXBoKGUsdCl7bGV0IHI9dFtlXTtpZih2b2lkIDAhPT1yKXJldHVybiByO2lmKCFlKXJldHVybi0xO2lmKCJ1Ij09PWVbMF0pe2NvbnN0IHQ9ZS5sZW5ndGg7bGV0IGE7aWYoNz09PXQmJiJuIj09PWVbMV0mJiJpIj09PWVbMl0pYT1lLnN1YnN0cmluZygzKTtlbHNle2lmKCEodD49NSYmdDw9NykpcmV0dXJuLTE7YT1lLnN1YnN0cmluZygxKX1pZihhPT09YS50b1VwcGVyQ2FzZSgpKXtyPXBhcnNlSW50KGEsMTYpO2lmKHI+PTApcmV0dXJuIHJ9fXJldHVybi0xfWNvbnN0IGJhPVtbMCwxMjddLFsxMjgsMjU1XSxbMjU2LDM4M10sWzM4NCw1OTFdLFs1OTIsNjg3LDc0MjQsNzU1MSw3NTUyLDc2MTVdLFs2ODgsNzY3LDQyNzUyLDQyNzgzXSxbNzY4LDg3OSw3NjE2LDc2NzldLFs4ODAsMTAyM10sWzExMzkyLDExNTE5XSxbMTAyNCwxMjc5LDEyODAsMTMyNywxMTc0NCwxMTc3NSw0MjU2MCw0MjY1NV0sWzEzMjgsMTQyM10sWzE0MjQsMTUzNV0sWzQyMjQwLDQyNTU5XSxbMTUzNiwxNzkxLDE4NzIsMTkxOV0sWzE5ODQsMjA0N10sWzIzMDQsMjQzMV0sWzI0MzIsMjU1OV0sWzI1NjAsMjY4N10sWzI2ODgsMjgxNV0sWzI4MTYsMjk0M10sWzI5NDQsMzA3MV0sWzMwNzIsMzE5OV0sWzMyMDAsMzMyN10sWzMzMjgsMzQ1NV0sWzM1ODQsMzcxMV0sWzM3MTIsMzgzOV0sWzQyNTYsNDM1MSwxMTUyMCwxMTU2N10sWzY5MTIsNzAzOV0sWzQzNTIsNDYwN10sWzc2ODAsNzkzNSwxMTM2MCwxMTM5MSw0Mjc4NCw0MzAwN10sWzc5MzYsODE5MV0sWzgxOTIsODMwMywxMTc3NiwxMTkwM10sWzgzMDQsODM1MV0sWzgzNTIsODM5OV0sWzg0MDAsODQ0N10sWzg0NDgsODUyN10sWzg1MjgsODU5MV0sWzg1OTIsODcwMywxMDIyNCwxMDIzOSwxMDQ5NiwxMDYyMywxMTAwOCwxMTI2M10sWzg3MDQsODk1OSwxMDc1MiwxMTAwNywxMDE3NiwxMDIyMywxMDYyNCwxMDc1MV0sWzg5NjAsOTIxNV0sWzkyMTYsOTI3OV0sWzkyODAsOTMxMV0sWzkzMTIsOTQ3MV0sWzk0NzIsOTU5OV0sWzk2MDAsOTYzMV0sWzk2MzIsOTcyN10sWzk3MjgsOTk4M10sWzk5ODQsMTAxNzVdLFsxMjI4OCwxMjM1MV0sWzEyMzUyLDEyNDQ3XSxbMTI0NDgsMTI1NDMsMTI3ODQsMTI3OTldLFsxMjU0NCwxMjU5MSwxMjcwNCwxMjczNV0sWzEyNTkyLDEyNjg3XSxbNDMwNzIsNDMxMzVdLFsxMjgwMCwxMzA1NV0sWzEzMDU2LDEzMzExXSxbNDQwMzIsNTUyMTVdLFs1NTI5Niw1NzM0M10sWzY3ODQwLDY3ODcxXSxbMTk5NjgsNDA5NTksMTE5MDQsMTIwMzEsMTIwMzIsMTIyNTUsMTIyNzIsMTIyODcsMTMzMTIsMTk5MDMsMTMxMDcyLDE3Mzc5MSwxMjY4OCwxMjcwM10sWzU3MzQ0LDYzNzQzXSxbMTI3MzYsMTI3ODMsNjM3NDQsNjQyNTUsMTk0NTYwLDE5NTEwM10sWzY0MjU2LDY0MzM1XSxbNjQzMzYsNjUwMjNdLFs2NTA1Niw2NTA3MV0sWzY1MDQwLDY1MDU1XSxbNjUxMDQsNjUxMzVdLFs2NTEzNiw2NTI3OV0sWzY1MjgwLDY1NTE5XSxbNjU1MjAsNjU1MzVdLFszODQwLDQwOTVdLFsxNzkyLDE4NzFdLFsxOTIwLDE5ODNdLFszNDU2LDM1ODNdLFs0MDk2LDQyNTVdLFs0NjA4LDQ5OTEsNDk5Miw1MDIzLDExNjQ4LDExNzQzXSxbNTAyNCw1MTE5XSxbNTEyMCw1NzU5XSxbNTc2MCw1NzkxXSxbNTc5Miw1ODg3XSxbNjAxNiw2MTQzXSxbNjE0NCw2MzE5XSxbMTAyNDAsMTA0OTVdLFs0MDk2MCw0MjEyN10sWzU4ODgsNTkxOSw1OTIwLDU5NTEsNTk1Miw1OTgzLDU5ODQsNjAxNV0sWzY2MzA0LDY2MzUxXSxbNjYzNTIsNjYzODNdLFs2NjU2MCw2NjYzOV0sWzExODc4NCwxMTkwMzksMTE5MDQwLDExOTI5NSwxMTkyOTYsMTE5Mzc1XSxbMTE5ODA4LDEyMDgzMV0sWzEwNDQ0ODAsMTA0ODU3M10sWzY1MDI0LDY1MDM5LDkxNzc2MCw5MTc5OTldLFs5MTc1MDQsOTE3NjMxXSxbNjQwMCw2NDc5XSxbNjQ4MCw2NTI3XSxbNjUyOCw2NjIzXSxbNjY1Niw2Njg3XSxbMTEyNjQsMTEzNTldLFsxMTU2OCwxMTY0N10sWzE5OTA0LDE5OTY3XSxbNDMwMDgsNDMwNTVdLFs2NTUzNiw2NTY2Myw2NTY2NCw2NTc5MSw2NTc5Miw2NTg1NV0sWzY1ODU2LDY1OTM1XSxbNjY0MzIsNjY0NjNdLFs2NjQ2NCw2NjUyN10sWzY2NjQwLDY2Njg3XSxbNjY2ODgsNjY3MzVdLFs2NzU4NCw2NzY0N10sWzY4MDk2LDY4MTkxXSxbMTE5NTUyLDExOTY0N10sWzczNzI4LDc0NzUxLDc0NzUyLDc0ODc5XSxbMTE5NjQ4LDExOTY3OV0sWzcwNDAsNzEwM10sWzcxNjgsNzI0N10sWzcyNDgsNzI5NV0sWzQzMTM2LDQzMjMxXSxbNDMyNjQsNDMzMTFdLFs0MzMxMiw0MzM1OV0sWzQzNTIwLDQzNjE1XSxbNjU5MzYsNjU5OTldLFs2NmUzLDY2MDQ3XSxbNjYyMDgsNjYyNzEsNjYxNzYsNjYyMDcsNjc4NzIsNjc5MDNdLFsxMjcwMjQsMTI3MTM1LDEyNjk3NiwxMjcwMjNdXTtmdW5jdGlvbiBnZXRVbmljb2RlUmFuZ2VGb3IoZSx0PS0xKXtpZigtMSE9PXQpe2NvbnN0IHI9YmFbdF07Zm9yKGxldCBhPTAsbj1yLmxlbmd0aDthPG47YSs9MilpZihlPj1yW2FdJiZlPD1yW2ErMV0pcmV0dXJuIHR9Zm9yKGxldCB0PTAscj1iYS5sZW5ndGg7dDxyO3QrKyl7Y29uc3Qgcj1iYVt0XTtmb3IobGV0IGE9MCxuPXIubGVuZ3RoO2E8bjthKz0yKWlmKGU+PXJbYV0mJmU8PXJbYSsxXSlyZXR1cm4gdH1yZXR1cm4tMX1jb25zdCB5YT1uZXcgUmVnRXhwKCJeKFxccyl8KFxccHtNbn0pfChcXHB7Q2Z9KSQiLCJ1Iiksd2E9bmV3IE1hcDtjb25zdCB4YT0hMCxTYT0xLEFhPTIsa2E9NCxDYT0zMix2YT1bIi5ub3RkZWYiLCIubnVsbCIsIm5vbm1hcmtpbmdyZXR1cm4iLCJzcGFjZSIsImV4Y2xhbSIsInF1b3RlZGJsIiwibnVtYmVyc2lnbiIsImRvbGxhciIsInBlcmNlbnQiLCJhbXBlcnNhbmQiLCJxdW90ZXNpbmdsZSIsInBhcmVubGVmdCIsInBhcmVucmlnaHQiLCJhc3RlcmlzayIsInBsdXMiLCJjb21tYSIsImh5cGhlbiIsInBlcmlvZCIsInNsYXNoIiwiemVybyIsIm9uZSIsInR3byIsInRocmVlIiwiZm91ciIsImZpdmUiLCJzaXgiLCJzZXZlbiIsImVpZ2h0IiwibmluZSIsImNvbG9uIiwic2VtaWNvbG9uIiwibGVzcyIsImVxdWFsIiwiZ3JlYXRlciIsInF1ZXN0aW9uIiwiYXQiLCJBIiwiQiIsIkMiLCJEIiwiRSIsIkYiLCJHIiwiSCIsIkkiLCJKIiwiSyIsIkwiLCJNIiwiTiIsIk8iLCJQIiwiUSIsIlIiLCJTIiwiVCIsIlUiLCJWIiwiVyIsIlgiLCJZIiwiWiIsImJyYWNrZXRsZWZ0IiwiYmFja3NsYXNoIiwiYnJhY2tldHJpZ2h0IiwiYXNjaWljaXJjdW0iLCJ1bmRlcnNjb3JlIiwiZ3JhdmUiLCJhIiwiYiIsImMiLCJkIiwiZSIsImYiLCJnIiwiaCIsImkiLCJqIiwiayIsImwiLCJtIiwibiIsIm8iLCJwIiwicSIsInIiLCJzIiwidCIsInUiLCJ2IiwidyIsIngiLCJ5IiwieiIsImJyYWNlbGVmdCIsImJhciIsImJyYWNlcmlnaHQiLCJhc2NpaXRpbGRlIiwiQWRpZXJlc2lzIiwiQXJpbmciLCJDY2VkaWxsYSIsIkVhY3V0ZSIsIk50aWxkZSIsIk9kaWVyZXNpcyIsIlVkaWVyZXNpcyIsImFhY3V0ZSIsImFncmF2ZSIsImFjaXJjdW1mbGV4IiwiYWRpZXJlc2lzIiwiYXRpbGRlIiwiYXJpbmciLCJjY2VkaWxsYSIsImVhY3V0ZSIsImVncmF2ZSIsImVjaXJjdW1mbGV4IiwiZWRpZXJlc2lzIiwiaWFjdXRlIiwiaWdyYXZlIiwiaWNpcmN1bWZsZXgiLCJpZGllcmVzaXMiLCJudGlsZGUiLCJvYWN1dGUiLCJvZ3JhdmUiLCJvY2lyY3VtZmxleCIsIm9kaWVyZXNpcyIsIm90aWxkZSIsInVhY3V0ZSIsInVncmF2ZSIsInVjaXJjdW1mbGV4IiwidWRpZXJlc2lzIiwiZGFnZ2VyIiwiZGVncmVlIiwiY2VudCIsInN0ZXJsaW5nIiwic2VjdGlvbiIsImJ1bGxldCIsInBhcmFncmFwaCIsImdlcm1hbmRibHMiLCJyZWdpc3RlcmVkIiwiY29weXJpZ2h0IiwidHJhZGVtYXJrIiwiYWN1dGUiLCJkaWVyZXNpcyIsIm5vdGVxdWFsIiwiQUUiLCJPc2xhc2giLCJpbmZpbml0eSIsInBsdXNtaW51cyIsImxlc3NlcXVhbCIsImdyZWF0ZXJlcXVhbCIsInllbiIsIm11IiwicGFydGlhbGRpZmYiLCJzdW1tYXRpb24iLCJwcm9kdWN0IiwicGkiLCJpbnRlZ3JhbCIsIm9yZGZlbWluaW5lIiwib3JkbWFzY3VsaW5lIiwiT21lZ2EiLCJhZSIsIm9zbGFzaCIsInF1ZXN0aW9uZG93biIsImV4Y2xhbWRvd24iLCJsb2dpY2Fsbm90IiwicmFkaWNhbCIsImZsb3JpbiIsImFwcHJveGVxdWFsIiwiRGVsdGEiLCJndWlsbGVtb3RsZWZ0IiwiZ3VpbGxlbW90cmlnaHQiLCJlbGxpcHNpcyIsIm5vbmJyZWFraW5nc3BhY2UiLCJBZ3JhdmUiLCJBdGlsZGUiLCJPdGlsZGUiLCJPRSIsIm9lIiwiZW5kYXNoIiwiZW1kYXNoIiwicXVvdGVkYmxsZWZ0IiwicXVvdGVkYmxyaWdodCIsInF1b3RlbGVmdCIsInF1b3RlcmlnaHQiLCJkaXZpZGUiLCJsb3plbmdlIiwieWRpZXJlc2lzIiwiWWRpZXJlc2lzIiwiZnJhY3Rpb24iLCJjdXJyZW5jeSIsImd1aWxzaW5nbGxlZnQiLCJndWlsc2luZ2xyaWdodCIsImZpIiwiZmwiLCJkYWdnZXJkYmwiLCJwZXJpb2RjZW50ZXJlZCIsInF1b3Rlc2luZ2xiYXNlIiwicXVvdGVkYmxiYXNlIiwicGVydGhvdXNhbmQiLCJBY2lyY3VtZmxleCIsIkVjaXJjdW1mbGV4IiwiQWFjdXRlIiwiRWRpZXJlc2lzIiwiRWdyYXZlIiwiSWFjdXRlIiwiSWNpcmN1bWZsZXgiLCJJZGllcmVzaXMiLCJJZ3JhdmUiLCJPYWN1dGUiLCJPY2lyY3VtZmxleCIsImFwcGxlIiwiT2dyYXZlIiwiVWFjdXRlIiwiVWNpcmN1bWZsZXgiLCJVZ3JhdmUiLCJkb3RsZXNzaSIsImNpcmN1bWZsZXgiLCJ0aWxkZSIsIm1hY3JvbiIsImJyZXZlIiwiZG90YWNjZW50IiwicmluZyIsImNlZGlsbGEiLCJodW5nYXJ1bWxhdXQiLCJvZ29uZWsiLCJjYXJvbiIsIkxzbGFzaCIsImxzbGFzaCIsIlNjYXJvbiIsInNjYXJvbiIsIlpjYXJvbiIsInpjYXJvbiIsImJyb2tlbmJhciIsIkV0aCIsImV0aCIsIllhY3V0ZSIsInlhY3V0ZSIsIlRob3JuIiwidGhvcm4iLCJtaW51cyIsIm11bHRpcGx5Iiwib25lc3VwZXJpb3IiLCJ0d29zdXBlcmlvciIsInRocmVlc3VwZXJpb3IiLCJvbmVoYWxmIiwib25lcXVhcnRlciIsInRocmVlcXVhcnRlcnMiLCJmcmFuYyIsIkdicmV2ZSIsImdicmV2ZSIsIklkb3RhY2NlbnQiLCJTY2VkaWxsYSIsInNjZWRpbGxhIiwiQ2FjdXRlIiwiY2FjdXRlIiwiQ2Nhcm9uIiwiY2Nhcm9uIiwiZGNyb2F0Il07ZnVuY3Rpb24gcmVjb3ZlckdseXBoTmFtZShlLHQpe2lmKHZvaWQgMCE9PXRbZV0pcmV0dXJuIGU7Y29uc3Qgcj1nZXRVbmljb2RlRm9yR2x5cGgoZSx0KTtpZigtMSE9PXIpZm9yKGNvbnN0IGUgaW4gdClpZih0W2VdPT09cilyZXR1cm4gZTtpbmZvKCJVbmFibGUgdG8gcmVjb3ZlciBhIHN0YW5kYXJkIGdseXBoIG5hbWUgZm9yOiAiK2UpO3JldHVybiBlfWZ1bmN0aW9uIHR5cGUxRm9udEdseXBoTWFwcGluZyhlLHQscil7Y29uc3QgYT1PYmplY3QuY3JlYXRlKG51bGwpO2xldCBuLGkscztjb25zdCBvPSEhKGUuZmxhZ3Mma2EpO2lmKGUuaXNJbnRlcm5hbEZvbnQpe3M9dDtmb3IoaT0wO2k8cy5sZW5ndGg7aSsrKXtuPXIuaW5kZXhPZihzW2ldKTthW2ldPW4+PTA/bjowfX1lbHNlIGlmKGUuYmFzZUVuY29kaW5nTmFtZSl7cz1nZXRFbmNvZGluZyhlLmJhc2VFbmNvZGluZ05hbWUpO2ZvcihpPTA7aTxzLmxlbmd0aDtpKyspe249ci5pbmRleE9mKHNbaV0pO2FbaV09bj49MD9uOjB9fWVsc2UgaWYobylmb3IoaSBpbiB0KWFbaV09dFtpXTtlbHNle3M9aGE7Zm9yKGk9MDtpPHMubGVuZ3RoO2krKyl7bj1yLmluZGV4T2Yoc1tpXSk7YVtpXT1uPj0wP246MH19Y29uc3QgYz1lLmRpZmZlcmVuY2VzO2xldCBsO2lmKGMpZm9yKGkgaW4gYyl7Y29uc3QgZT1jW2ldO249ci5pbmRleE9mKGUpO2lmKC0xPT09bil7bHx8KGw9Z2EoKSk7Y29uc3QgdD1yZWNvdmVyR2x5cGhOYW1lKGUsbCk7dCE9PWUmJihuPXIuaW5kZXhPZih0KSl9YVtpXT1uPj0wP246MH1yZXR1cm4gYX1mdW5jdGlvbiBub3JtYWxpemVGb250TmFtZShlKXtyZXR1cm4gZS5yZXBsYWNlQWxsKC9bLF9dL2csIi0iKS5yZXBsYWNlQWxsKC9ccy9nLCIiKX1jb25zdCBGYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZT0+e2VbODIxMV09NjUwNzQ7ZVs4MjEyXT02NTA3MztlWzgyMjldPTY1MDcyO2VbODIzMF09NjUwNDk7ZVsxMjI4OV09NjUwNDE7ZVsxMjI5MF09NjUwNDI7ZVsxMjI5Nl09NjUwODc7ZVsxMjI5N109NjUwODg7ZVsxMjI5OF09NjUwODU7ZVsxMjI5OV09NjUwODY7ZVsxMjMwMF09NjUwODk7ZVsxMjMwMV09NjUwOTA7ZVsxMjMwMl09NjUwOTE7ZVsxMjMwM109NjUwOTI7ZVsxMjMwNF09NjUwODM7ZVsxMjMwNV09NjUwODQ7ZVsxMjMwOF09NjUwODE7ZVsxMjMwOV09NjUwODI7ZVsxMjMxMF09NjUwNDc7ZVsxMjMxMV09NjUwNDg7ZVs2NTEwM109NjUwNzY7ZVs2NTI4MV09NjUwNDU7ZVs2NTI4OF09NjUwNzc7ZVs2NTI4OV09NjUwNzg7ZVs2NTI5Ml09NjUwNDA7ZVs2NTMwNl09NjUwNDM7ZVs2NTMwN109NjUwNDQ7ZVs2NTMxMV09NjUwNDY7ZVs2NTMzOV09NjUwOTU7ZVs2NTM0MV09NjUwOTY7ZVs2NTM0M109NjUwNzU7ZVs2NTM3MV09NjUwNzk7ZVs2NTM3M109NjUwODB9KTtfX3dlYnBhY2tfcmVxdWlyZV9fKDE4MDYpO2NvbnN0IElhPVsiLm5vdGRlZiIsInNwYWNlIiwiZXhjbGFtIiwicXVvdGVkYmwiLCJudW1iZXJzaWduIiwiZG9sbGFyIiwicGVyY2VudCIsImFtcGVyc2FuZCIsInF1b3RlcmlnaHQiLCJwYXJlbmxlZnQiLCJwYXJlbnJpZ2h0IiwiYXN0ZXJpc2siLCJwbHVzIiwiY29tbWEiLCJoeXBoZW4iLCJwZXJpb2QiLCJzbGFzaCIsInplcm8iLCJvbmUiLCJ0d28iLCJ0aHJlZSIsImZvdXIiLCJmaXZlIiwic2l4Iiwic2V2ZW4iLCJlaWdodCIsIm5pbmUiLCJjb2xvbiIsInNlbWljb2xvbiIsImxlc3MiLCJlcXVhbCIsImdyZWF0ZXIiLCJxdWVzdGlvbiIsImF0IiwiQSIsIkIiLCJDIiwiRCIsIkUiLCJGIiwiRyIsIkgiLCJJIiwiSiIsIksiLCJMIiwiTSIsIk4iLCJPIiwiUCIsIlEiLCJSIiwiUyIsIlQiLCJVIiwiViIsIlciLCJYIiwiWSIsIloiLCJicmFja2V0bGVmdCIsImJhY2tzbGFzaCIsImJyYWNrZXRyaWdodCIsImFzY2lpY2lyY3VtIiwidW5kZXJzY29yZSIsInF1b3RlbGVmdCIsImEiLCJiIiwiYyIsImQiLCJlIiwiZiIsImciLCJoIiwiaSIsImoiLCJrIiwibCIsIm0iLCJuIiwibyIsInAiLCJxIiwiciIsInMiLCJ0IiwidSIsInYiLCJ3IiwieCIsInkiLCJ6IiwiYnJhY2VsZWZ0IiwiYmFyIiwiYnJhY2VyaWdodCIsImFzY2lpdGlsZGUiLCJleGNsYW1kb3duIiwiY2VudCIsInN0ZXJsaW5nIiwiZnJhY3Rpb24iLCJ5ZW4iLCJmbG9yaW4iLCJzZWN0aW9uIiwiY3VycmVuY3kiLCJxdW90ZXNpbmdsZSIsInF1b3RlZGJsbGVmdCIsImd1aWxsZW1vdGxlZnQiLCJndWlsc2luZ2xsZWZ0IiwiZ3VpbHNpbmdscmlnaHQiLCJmaSIsImZsIiwiZW5kYXNoIiwiZGFnZ2VyIiwiZGFnZ2VyZGJsIiwicGVyaW9kY2VudGVyZWQiLCJwYXJhZ3JhcGgiLCJidWxsZXQiLCJxdW90ZXNpbmdsYmFzZSIsInF1b3RlZGJsYmFzZSIsInF1b3RlZGJscmlnaHQiLCJndWlsbGVtb3RyaWdodCIsImVsbGlwc2lzIiwicGVydGhvdXNhbmQiLCJxdWVzdGlvbmRvd24iLCJncmF2ZSIsImFjdXRlIiwiY2lyY3VtZmxleCIsInRpbGRlIiwibWFjcm9uIiwiYnJldmUiLCJkb3RhY2NlbnQiLCJkaWVyZXNpcyIsInJpbmciLCJjZWRpbGxhIiwiaHVuZ2FydW1sYXV0Iiwib2dvbmVrIiwiY2Fyb24iLCJlbWRhc2giLCJBRSIsIm9yZGZlbWluaW5lIiwiTHNsYXNoIiwiT3NsYXNoIiwiT0UiLCJvcmRtYXNjdWxpbmUiLCJhZSIsImRvdGxlc3NpIiwibHNsYXNoIiwib3NsYXNoIiwib2UiLCJnZXJtYW5kYmxzIiwib25lc3VwZXJpb3IiLCJsb2dpY2Fsbm90IiwibXUiLCJ0cmFkZW1hcmsiLCJFdGgiLCJvbmVoYWxmIiwicGx1c21pbnVzIiwiVGhvcm4iLCJvbmVxdWFydGVyIiwiZGl2aWRlIiwiYnJva2VuYmFyIiwiZGVncmVlIiwidGhvcm4iLCJ0aHJlZXF1YXJ0ZXJzIiwidHdvc3VwZXJpb3IiLCJyZWdpc3RlcmVkIiwibWludXMiLCJldGgiLCJtdWx0aXBseSIsInRocmVlc3VwZXJpb3IiLCJjb3B5cmlnaHQiLCJBYWN1dGUiLCJBY2lyY3VtZmxleCIsIkFkaWVyZXNpcyIsIkFncmF2ZSIsIkFyaW5nIiwiQXRpbGRlIiwiQ2NlZGlsbGEiLCJFYWN1dGUiLCJFY2lyY3VtZmxleCIsIkVkaWVyZXNpcyIsIkVncmF2ZSIsIklhY3V0ZSIsIkljaXJjdW1mbGV4IiwiSWRpZXJlc2lzIiwiSWdyYXZlIiwiTnRpbGRlIiwiT2FjdXRlIiwiT2NpcmN1bWZsZXgiLCJPZGllcmVzaXMiLCJPZ3JhdmUiLCJPdGlsZGUiLCJTY2Fyb24iLCJVYWN1dGUiLCJVY2lyY3VtZmxleCIsIlVkaWVyZXNpcyIsIlVncmF2ZSIsIllhY3V0ZSIsIllkaWVyZXNpcyIsIlpjYXJvbiIsImFhY3V0ZSIsImFjaXJjdW1mbGV4IiwiYWRpZXJlc2lzIiwiYWdyYXZlIiwiYXJpbmciLCJhdGlsZGUiLCJjY2VkaWxsYSIsImVhY3V0ZSIsImVjaXJjdW1mbGV4IiwiZWRpZXJlc2lzIiwiZWdyYXZlIiwiaWFjdXRlIiwiaWNpcmN1bWZsZXgiLCJpZGllcmVzaXMiLCJpZ3JhdmUiLCJudGlsZGUiLCJvYWN1dGUiLCJvY2lyY3VtZmxleCIsIm9kaWVyZXNpcyIsIm9ncmF2ZSIsIm90aWxkZSIsInNjYXJvbiIsInVhY3V0ZSIsInVjaXJjdW1mbGV4IiwidWRpZXJlc2lzIiwidWdyYXZlIiwieWFjdXRlIiwieWRpZXJlc2lzIiwiemNhcm9uIl0sVGE9WyIubm90ZGVmIiwic3BhY2UiLCJleGNsYW1zbWFsbCIsIkh1bmdhcnVtbGF1dHNtYWxsIiwiZG9sbGFyb2xkc3R5bGUiLCJkb2xsYXJzdXBlcmlvciIsImFtcGVyc2FuZHNtYWxsIiwiQWN1dGVzbWFsbCIsInBhcmVubGVmdHN1cGVyaW9yIiwicGFyZW5yaWdodHN1cGVyaW9yIiwidHdvZG90ZW5sZWFkZXIiLCJvbmVkb3RlbmxlYWRlciIsImNvbW1hIiwiaHlwaGVuIiwicGVyaW9kIiwiZnJhY3Rpb24iLCJ6ZXJvb2xkc3R5bGUiLCJvbmVvbGRzdHlsZSIsInR3b29sZHN0eWxlIiwidGhyZWVvbGRzdHlsZSIsImZvdXJvbGRzdHlsZSIsImZpdmVvbGRzdHlsZSIsInNpeG9sZHN0eWxlIiwic2V2ZW5vbGRzdHlsZSIsImVpZ2h0b2xkc3R5bGUiLCJuaW5lb2xkc3R5bGUiLCJjb2xvbiIsInNlbWljb2xvbiIsImNvbW1hc3VwZXJpb3IiLCJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwicGVyaW9kc3VwZXJpb3IiLCJxdWVzdGlvbnNtYWxsIiwiYXN1cGVyaW9yIiwiYnN1cGVyaW9yIiwiY2VudHN1cGVyaW9yIiwiZHN1cGVyaW9yIiwiZXN1cGVyaW9yIiwiaXN1cGVyaW9yIiwibHN1cGVyaW9yIiwibXN1cGVyaW9yIiwibnN1cGVyaW9yIiwib3N1cGVyaW9yIiwicnN1cGVyaW9yIiwic3N1cGVyaW9yIiwidHN1cGVyaW9yIiwiZmYiLCJmaSIsImZsIiwiZmZpIiwiZmZsIiwicGFyZW5sZWZ0aW5mZXJpb3IiLCJwYXJlbnJpZ2h0aW5mZXJpb3IiLCJDaXJjdW1mbGV4c21hbGwiLCJoeXBoZW5zdXBlcmlvciIsIkdyYXZlc21hbGwiLCJBc21hbGwiLCJCc21hbGwiLCJDc21hbGwiLCJEc21hbGwiLCJFc21hbGwiLCJGc21hbGwiLCJHc21hbGwiLCJIc21hbGwiLCJJc21hbGwiLCJKc21hbGwiLCJLc21hbGwiLCJMc21hbGwiLCJNc21hbGwiLCJOc21hbGwiLCJPc21hbGwiLCJQc21hbGwiLCJRc21hbGwiLCJSc21hbGwiLCJTc21hbGwiLCJUc21hbGwiLCJVc21hbGwiLCJWc21hbGwiLCJXc21hbGwiLCJYc21hbGwiLCJZc21hbGwiLCJac21hbGwiLCJjb2xvbm1vbmV0YXJ5Iiwib25lZml0dGVkIiwicnVwaWFoIiwiVGlsZGVzbWFsbCIsImV4Y2xhbWRvd25zbWFsbCIsImNlbnRvbGRzdHlsZSIsIkxzbGFzaHNtYWxsIiwiU2Nhcm9uc21hbGwiLCJaY2Fyb25zbWFsbCIsIkRpZXJlc2lzc21hbGwiLCJCcmV2ZXNtYWxsIiwiQ2Fyb25zbWFsbCIsIkRvdGFjY2VudHNtYWxsIiwiTWFjcm9uc21hbGwiLCJmaWd1cmVkYXNoIiwiaHlwaGVuaW5mZXJpb3IiLCJPZ29uZWtzbWFsbCIsIlJpbmdzbWFsbCIsIkNlZGlsbGFzbWFsbCIsIm9uZXF1YXJ0ZXIiLCJvbmVoYWxmIiwidGhyZWVxdWFydGVycyIsInF1ZXN0aW9uZG93bnNtYWxsIiwib25lZWlnaHRoIiwidGhyZWVlaWdodGhzIiwiZml2ZWVpZ2h0aHMiLCJzZXZlbmVpZ2h0aHMiLCJvbmV0aGlyZCIsInR3b3RoaXJkcyIsInplcm9zdXBlcmlvciIsIm9uZXN1cGVyaW9yIiwidHdvc3VwZXJpb3IiLCJ0aHJlZXN1cGVyaW9yIiwiZm91cnN1cGVyaW9yIiwiZml2ZXN1cGVyaW9yIiwic2l4c3VwZXJpb3IiLCJzZXZlbnN1cGVyaW9yIiwiZWlnaHRzdXBlcmlvciIsIm5pbmVzdXBlcmlvciIsInplcm9pbmZlcmlvciIsIm9uZWluZmVyaW9yIiwidHdvaW5mZXJpb3IiLCJ0aHJlZWluZmVyaW9yIiwiZm91cmluZmVyaW9yIiwiZml2ZWluZmVyaW9yIiwic2l4aW5mZXJpb3IiLCJzZXZlbmluZmVyaW9yIiwiZWlnaHRpbmZlcmlvciIsIm5pbmVpbmZlcmlvciIsImNlbnRpbmZlcmlvciIsImRvbGxhcmluZmVyaW9yIiwicGVyaW9kaW5mZXJpb3IiLCJjb21tYWluZmVyaW9yIiwiQWdyYXZlc21hbGwiLCJBYWN1dGVzbWFsbCIsIkFjaXJjdW1mbGV4c21hbGwiLCJBdGlsZGVzbWFsbCIsIkFkaWVyZXNpc3NtYWxsIiwiQXJpbmdzbWFsbCIsIkFFc21hbGwiLCJDY2VkaWxsYXNtYWxsIiwiRWdyYXZlc21hbGwiLCJFYWN1dGVzbWFsbCIsIkVjaXJjdW1mbGV4c21hbGwiLCJFZGllcmVzaXNzbWFsbCIsIklncmF2ZXNtYWxsIiwiSWFjdXRlc21hbGwiLCJJY2lyY3VtZmxleHNtYWxsIiwiSWRpZXJlc2lzc21hbGwiLCJFdGhzbWFsbCIsIk50aWxkZXNtYWxsIiwiT2dyYXZlc21hbGwiLCJPYWN1dGVzbWFsbCIsIk9jaXJjdW1mbGV4c21hbGwiLCJPdGlsZGVzbWFsbCIsIk9kaWVyZXNpc3NtYWxsIiwiT0VzbWFsbCIsIk9zbGFzaHNtYWxsIiwiVWdyYXZlc21hbGwiLCJVYWN1dGVzbWFsbCIsIlVjaXJjdW1mbGV4c21hbGwiLCJVZGllcmVzaXNzbWFsbCIsIllhY3V0ZXNtYWxsIiwiVGhvcm5zbWFsbCIsIllkaWVyZXNpc3NtYWxsIl0sT2E9WyIubm90ZGVmIiwic3BhY2UiLCJkb2xsYXJvbGRzdHlsZSIsImRvbGxhcnN1cGVyaW9yIiwicGFyZW5sZWZ0c3VwZXJpb3IiLCJwYXJlbnJpZ2h0c3VwZXJpb3IiLCJ0d29kb3RlbmxlYWRlciIsIm9uZWRvdGVubGVhZGVyIiwiY29tbWEiLCJoeXBoZW4iLCJwZXJpb2QiLCJmcmFjdGlvbiIsInplcm9vbGRzdHlsZSIsIm9uZW9sZHN0eWxlIiwidHdvb2xkc3R5bGUiLCJ0aHJlZW9sZHN0eWxlIiwiZm91cm9sZHN0eWxlIiwiZml2ZW9sZHN0eWxlIiwic2l4b2xkc3R5bGUiLCJzZXZlbm9sZHN0eWxlIiwiZWlnaHRvbGRzdHlsZSIsIm5pbmVvbGRzdHlsZSIsImNvbG9uIiwic2VtaWNvbG9uIiwiY29tbWFzdXBlcmlvciIsInRocmVlcXVhcnRlcnNlbWRhc2giLCJwZXJpb2RzdXBlcmlvciIsImFzdXBlcmlvciIsImJzdXBlcmlvciIsImNlbnRzdXBlcmlvciIsImRzdXBlcmlvciIsImVzdXBlcmlvciIsImlzdXBlcmlvciIsImxzdXBlcmlvciIsIm1zdXBlcmlvciIsIm5zdXBlcmlvciIsIm9zdXBlcmlvciIsInJzdXBlcmlvciIsInNzdXBlcmlvciIsInRzdXBlcmlvciIsImZmIiwiZmkiLCJmbCIsImZmaSIsImZmbCIsInBhcmVubGVmdGluZmVyaW9yIiwicGFyZW5yaWdodGluZmVyaW9yIiwiaHlwaGVuc3VwZXJpb3IiLCJjb2xvbm1vbmV0YXJ5Iiwib25lZml0dGVkIiwicnVwaWFoIiwiY2VudG9sZHN0eWxlIiwiZmlndXJlZGFzaCIsImh5cGhlbmluZmVyaW9yIiwib25lcXVhcnRlciIsIm9uZWhhbGYiLCJ0aHJlZXF1YXJ0ZXJzIiwib25lZWlnaHRoIiwidGhyZWVlaWdodGhzIiwiZml2ZWVpZ2h0aHMiLCJzZXZlbmVpZ2h0aHMiLCJvbmV0aGlyZCIsInR3b3RoaXJkcyIsInplcm9zdXBlcmlvciIsIm9uZXN1cGVyaW9yIiwidHdvc3VwZXJpb3IiLCJ0aHJlZXN1cGVyaW9yIiwiZm91cnN1cGVyaW9yIiwiZml2ZXN1cGVyaW9yIiwic2l4c3VwZXJpb3IiLCJzZXZlbnN1cGVyaW9yIiwiZWlnaHRzdXBlcmlvciIsIm5pbmVzdXBlcmlvciIsInplcm9pbmZlcmlvciIsIm9uZWluZmVyaW9yIiwidHdvaW5mZXJpb3IiLCJ0aHJlZWluZmVyaW9yIiwiZm91cmluZmVyaW9yIiwiZml2ZWluZmVyaW9yIiwic2l4aW5mZXJpb3IiLCJzZXZlbmluZmVyaW9yIiwiZWlnaHRpbmZlcmlvciIsIm5pbmVpbmZlcmlvciIsImNlbnRpbmZlcmlvciIsImRvbGxhcmluZmVyaW9yIiwicGVyaW9kaW5mZXJpb3IiLCJjb21tYWluZmVyaW9yIl0sTWE9WyIubm90ZGVmIiwic3BhY2UiLCJleGNsYW0iLCJxdW90ZWRibCIsIm51bWJlcnNpZ24iLCJkb2xsYXIiLCJwZXJjZW50IiwiYW1wZXJzYW5kIiwicXVvdGVyaWdodCIsInBhcmVubGVmdCIsInBhcmVucmlnaHQiLCJhc3RlcmlzayIsInBsdXMiLCJjb21tYSIsImh5cGhlbiIsInBlcmlvZCIsInNsYXNoIiwiemVybyIsIm9uZSIsInR3byIsInRocmVlIiwiZm91ciIsImZpdmUiLCJzaXgiLCJzZXZlbiIsImVpZ2h0IiwibmluZSIsImNvbG9uIiwic2VtaWNvbG9uIiwibGVzcyIsImVxdWFsIiwiZ3JlYXRlciIsInF1ZXN0aW9uIiwiYXQiLCJBIiwiQiIsIkMiLCJEIiwiRSIsIkYiLCJHIiwiSCIsIkkiLCJKIiwiSyIsIkwiLCJNIiwiTiIsIk8iLCJQIiwiUSIsIlIiLCJTIiwiVCIsIlUiLCJWIiwiVyIsIlgiLCJZIiwiWiIsImJyYWNrZXRsZWZ0IiwiYmFja3NsYXNoIiwiYnJhY2tldHJpZ2h0IiwiYXNjaWljaXJjdW0iLCJ1bmRlcnNjb3JlIiwicXVvdGVsZWZ0IiwiYSIsImIiLCJjIiwiZCIsImUiLCJmIiwiZyIsImgiLCJpIiwiaiIsImsiLCJsIiwibSIsIm4iLCJvIiwicCIsInEiLCJyIiwicyIsInQiLCJ1IiwidiIsInciLCJ4IiwieSIsInoiLCJicmFjZWxlZnQiLCJiYXIiLCJicmFjZXJpZ2h0IiwiYXNjaWl0aWxkZSIsImV4Y2xhbWRvd24iLCJjZW50Iiwic3RlcmxpbmciLCJmcmFjdGlvbiIsInllbiIsImZsb3JpbiIsInNlY3Rpb24iLCJjdXJyZW5jeSIsInF1b3Rlc2luZ2xlIiwicXVvdGVkYmxsZWZ0IiwiZ3VpbGxlbW90bGVmdCIsImd1aWxzaW5nbGxlZnQiLCJndWlsc2luZ2xyaWdodCIsImZpIiwiZmwiLCJlbmRhc2giLCJkYWdnZXIiLCJkYWdnZXJkYmwiLCJwZXJpb2RjZW50ZXJlZCIsInBhcmFncmFwaCIsImJ1bGxldCIsInF1b3Rlc2luZ2xiYXNlIiwicXVvdGVkYmxiYXNlIiwicXVvdGVkYmxyaWdodCIsImd1aWxsZW1vdHJpZ2h0IiwiZWxsaXBzaXMiLCJwZXJ0aG91c2FuZCIsInF1ZXN0aW9uZG93biIsImdyYXZlIiwiYWN1dGUiLCJjaXJjdW1mbGV4IiwidGlsZGUiLCJtYWNyb24iLCJicmV2ZSIsImRvdGFjY2VudCIsImRpZXJlc2lzIiwicmluZyIsImNlZGlsbGEiLCJodW5nYXJ1bWxhdXQiLCJvZ29uZWsiLCJjYXJvbiIsImVtZGFzaCIsIkFFIiwib3JkZmVtaW5pbmUiLCJMc2xhc2giLCJPc2xhc2giLCJPRSIsIm9yZG1hc2N1bGluZSIsImFlIiwiZG90bGVzc2kiLCJsc2xhc2giLCJvc2xhc2giLCJvZSIsImdlcm1hbmRibHMiLCJvbmVzdXBlcmlvciIsImxvZ2ljYWxub3QiLCJtdSIsInRyYWRlbWFyayIsIkV0aCIsIm9uZWhhbGYiLCJwbHVzbWludXMiLCJUaG9ybiIsIm9uZXF1YXJ0ZXIiLCJkaXZpZGUiLCJicm9rZW5iYXIiLCJkZWdyZWUiLCJ0aG9ybiIsInRocmVlcXVhcnRlcnMiLCJ0d29zdXBlcmlvciIsInJlZ2lzdGVyZWQiLCJtaW51cyIsImV0aCIsIm11bHRpcGx5IiwidGhyZWVzdXBlcmlvciIsImNvcHlyaWdodCIsIkFhY3V0ZSIsIkFjaXJjdW1mbGV4IiwiQWRpZXJlc2lzIiwiQWdyYXZlIiwiQXJpbmciLCJBdGlsZGUiLCJDY2VkaWxsYSIsIkVhY3V0ZSIsIkVjaXJjdW1mbGV4IiwiRWRpZXJlc2lzIiwiRWdyYXZlIiwiSWFjdXRlIiwiSWNpcmN1bWZsZXgiLCJJZGllcmVzaXMiLCJJZ3JhdmUiLCJOdGlsZGUiLCJPYWN1dGUiLCJPY2lyY3VtZmxleCIsIk9kaWVyZXNpcyIsIk9ncmF2ZSIsIk90aWxkZSIsIlNjYXJvbiIsIlVhY3V0ZSIsIlVjaXJjdW1mbGV4IiwiVWRpZXJlc2lzIiwiVWdyYXZlIiwiWWFjdXRlIiwiWWRpZXJlc2lzIiwiWmNhcm9uIiwiYWFjdXRlIiwiYWNpcmN1bWZsZXgiLCJhZGllcmVzaXMiLCJhZ3JhdmUiLCJhcmluZyIsImF0aWxkZSIsImNjZWRpbGxhIiwiZWFjdXRlIiwiZWNpcmN1bWZsZXgiLCJlZGllcmVzaXMiLCJlZ3JhdmUiLCJpYWN1dGUiLCJpY2lyY3VtZmxleCIsImlkaWVyZXNpcyIsImlncmF2ZSIsIm50aWxkZSIsIm9hY3V0ZSIsIm9jaXJjdW1mbGV4Iiwib2RpZXJlc2lzIiwib2dyYXZlIiwib3RpbGRlIiwic2Nhcm9uIiwidWFjdXRlIiwidWNpcmN1bWZsZXgiLCJ1ZGllcmVzaXMiLCJ1Z3JhdmUiLCJ5YWN1dGUiLCJ5ZGllcmVzaXMiLCJ6Y2Fyb24iLCJleGNsYW1zbWFsbCIsIkh1bmdhcnVtbGF1dHNtYWxsIiwiZG9sbGFyb2xkc3R5bGUiLCJkb2xsYXJzdXBlcmlvciIsImFtcGVyc2FuZHNtYWxsIiwiQWN1dGVzbWFsbCIsInBhcmVubGVmdHN1cGVyaW9yIiwicGFyZW5yaWdodHN1cGVyaW9yIiwidHdvZG90ZW5sZWFkZXIiLCJvbmVkb3RlbmxlYWRlciIsInplcm9vbGRzdHlsZSIsIm9uZW9sZHN0eWxlIiwidHdvb2xkc3R5bGUiLCJ0aHJlZW9sZHN0eWxlIiwiZm91cm9sZHN0eWxlIiwiZml2ZW9sZHN0eWxlIiwic2l4b2xkc3R5bGUiLCJzZXZlbm9sZHN0eWxlIiwiZWlnaHRvbGRzdHlsZSIsIm5pbmVvbGRzdHlsZSIsImNvbW1hc3VwZXJpb3IiLCJ0aHJlZXF1YXJ0ZXJzZW1kYXNoIiwicGVyaW9kc3VwZXJpb3IiLCJxdWVzdGlvbnNtYWxsIiwiYXN1cGVyaW9yIiwiYnN1cGVyaW9yIiwiY2VudHN1cGVyaW9yIiwiZHN1cGVyaW9yIiwiZXN1cGVyaW9yIiwiaXN1cGVyaW9yIiwibHN1cGVyaW9yIiwibXN1cGVyaW9yIiwibnN1cGVyaW9yIiwib3N1cGVyaW9yIiwicnN1cGVyaW9yIiwic3N1cGVyaW9yIiwidHN1cGVyaW9yIiwiZmYiLCJmZmkiLCJmZmwiLCJwYXJlbmxlZnRpbmZlcmlvciIsInBhcmVucmlnaHRpbmZlcmlvciIsIkNpcmN1bWZsZXhzbWFsbCIsImh5cGhlbnN1cGVyaW9yIiwiR3JhdmVzbWFsbCIsIkFzbWFsbCIsIkJzbWFsbCIsIkNzbWFsbCIsIkRzbWFsbCIsIkVzbWFsbCIsIkZzbWFsbCIsIkdzbWFsbCIsIkhzbWFsbCIsIklzbWFsbCIsIkpzbWFsbCIsIktzbWFsbCIsIkxzbWFsbCIsIk1zbWFsbCIsIk5zbWFsbCIsIk9zbWFsbCIsIlBzbWFsbCIsIlFzbWFsbCIsIlJzbWFsbCIsIlNzbWFsbCIsIlRzbWFsbCIsIlVzbWFsbCIsIlZzbWFsbCIsIldzbWFsbCIsIlhzbWFsbCIsIllzbWFsbCIsIlpzbWFsbCIsImNvbG9ubW9uZXRhcnkiLCJvbmVmaXR0ZWQiLCJydXBpYWgiLCJUaWxkZXNtYWxsIiwiZXhjbGFtZG93bnNtYWxsIiwiY2VudG9sZHN0eWxlIiwiTHNsYXNoc21hbGwiLCJTY2Fyb25zbWFsbCIsIlpjYXJvbnNtYWxsIiwiRGllcmVzaXNzbWFsbCIsIkJyZXZlc21hbGwiLCJDYXJvbnNtYWxsIiwiRG90YWNjZW50c21hbGwiLCJNYWNyb25zbWFsbCIsImZpZ3VyZWRhc2giLCJoeXBoZW5pbmZlcmlvciIsIk9nb25la3NtYWxsIiwiUmluZ3NtYWxsIiwiQ2VkaWxsYXNtYWxsIiwicXVlc3Rpb25kb3duc21hbGwiLCJvbmVlaWdodGgiLCJ0aHJlZWVpZ2h0aHMiLCJmaXZlZWlnaHRocyIsInNldmVuZWlnaHRocyIsIm9uZXRoaXJkIiwidHdvdGhpcmRzIiwiemVyb3N1cGVyaW9yIiwiZm91cnN1cGVyaW9yIiwiZml2ZXN1cGVyaW9yIiwic2l4c3VwZXJpb3IiLCJzZXZlbnN1cGVyaW9yIiwiZWlnaHRzdXBlcmlvciIsIm5pbmVzdXBlcmlvciIsInplcm9pbmZlcmlvciIsIm9uZWluZmVyaW9yIiwidHdvaW5mZXJpb3IiLCJ0aHJlZWluZmVyaW9yIiwiZm91cmluZmVyaW9yIiwiZml2ZWluZmVyaW9yIiwic2l4aW5mZXJpb3IiLCJzZXZlbmluZmVyaW9yIiwiZWlnaHRpbmZlcmlvciIsIm5pbmVpbmZlcmlvciIsImNlbnRpbmZlcmlvciIsImRvbGxhcmluZmVyaW9yIiwicGVyaW9kaW5mZXJpb3IiLCJjb21tYWluZmVyaW9yIiwiQWdyYXZlc21hbGwiLCJBYWN1dGVzbWFsbCIsIkFjaXJjdW1mbGV4c21hbGwiLCJBdGlsZGVzbWFsbCIsIkFkaWVyZXNpc3NtYWxsIiwiQXJpbmdzbWFsbCIsIkFFc21hbGwiLCJDY2VkaWxsYXNtYWxsIiwiRWdyYXZlc21hbGwiLCJFYWN1dGVzbWFsbCIsIkVjaXJjdW1mbGV4c21hbGwiLCJFZGllcmVzaXNzbWFsbCIsIklncmF2ZXNtYWxsIiwiSWFjdXRlc21hbGwiLCJJY2lyY3VtZmxleHNtYWxsIiwiSWRpZXJlc2lzc21hbGwiLCJFdGhzbWFsbCIsIk50aWxkZXNtYWxsIiwiT2dyYXZlc21hbGwiLCJPYWN1dGVzbWFsbCIsIk9jaXJjdW1mbGV4c21hbGwiLCJPdGlsZGVzbWFsbCIsIk9kaWVyZXNpc3NtYWxsIiwiT0VzbWFsbCIsIk9zbGFzaHNtYWxsIiwiVWdyYXZlc21hbGwiLCJVYWN1dGVzbWFsbCIsIlVjaXJjdW1mbGV4c21hbGwiLCJVZGllcmVzaXNzbWFsbCIsIllhY3V0ZXNtYWxsIiwiVGhvcm5zbWFsbCIsIllkaWVyZXNpc3NtYWxsIiwiMDAxLjAwMCIsIjAwMS4wMDEiLCIwMDEuMDAyIiwiMDAxLjAwMyIsIkJsYWNrIiwiQm9sZCIsIkJvb2siLCJMaWdodCIsIk1lZGl1bSIsIlJlZ3VsYXIiLCJSb21hbiIsIlNlbWlib2xkIl0sRGE9MzkxLEJhPVtudWxsLHtpZDoiaHN0ZW0iLG1pbjoyLHN0YWNrQ2xlYXJpbmc6ITAsc3RlbTohMH0sbnVsbCx7aWQ6InZzdGVtIixtaW46MixzdGFja0NsZWFyaW5nOiEwLHN0ZW06ITB9LHtpZDoidm1vdmV0byIsbWluOjEsc3RhY2tDbGVhcmluZzohMH0se2lkOiJybGluZXRvIixtaW46MixyZXNldFN0YWNrOiEwfSx7aWQ6ImhsaW5ldG8iLG1pbjoxLHJlc2V0U3RhY2s6ITB9LHtpZDoidmxpbmV0byIsbWluOjEscmVzZXRTdGFjazohMH0se2lkOiJycmN1cnZldG8iLG1pbjo2LHJlc2V0U3RhY2s6ITB9LG51bGwse2lkOiJjYWxsc3ViciIsbWluOjEsdW5kZWZTdGFjazohMH0se2lkOiJyZXR1cm4iLG1pbjowLHVuZGVmU3RhY2s6ITB9LG51bGwsbnVsbCx7aWQ6ImVuZGNoYXIiLG1pbjowLHN0YWNrQ2xlYXJpbmc6ITB9LG51bGwsbnVsbCxudWxsLHtpZDoiaHN0ZW1obSIsbWluOjIsc3RhY2tDbGVhcmluZzohMCxzdGVtOiEwfSx7aWQ6ImhpbnRtYXNrIixtaW46MCxzdGFja0NsZWFyaW5nOiEwfSx7aWQ6ImNudHJtYXNrIixtaW46MCxzdGFja0NsZWFyaW5nOiEwfSx7aWQ6InJtb3ZldG8iLG1pbjoyLHN0YWNrQ2xlYXJpbmc6ITB9LHtpZDoiaG1vdmV0byIsbWluOjEsc3RhY2tDbGVhcmluZzohMH0se2lkOiJ2c3RlbWhtIixtaW46MixzdGFja0NsZWFyaW5nOiEwLHN0ZW06ITB9LHtpZDoicmN1cnZlbGluZSIsbWluOjgscmVzZXRTdGFjazohMH0se2lkOiJybGluZWN1cnZlIixtaW46OCxyZXNldFN0YWNrOiEwfSx7aWQ6InZ2Y3VydmV0byIsbWluOjQscmVzZXRTdGFjazohMH0se2lkOiJoaGN1cnZldG8iLG1pbjo0LHJlc2V0U3RhY2s6ITB9LG51bGwse2lkOiJjYWxsZ3N1YnIiLG1pbjoxLHVuZGVmU3RhY2s6ITB9LHtpZDoidmhjdXJ2ZXRvIixtaW46NCxyZXNldFN0YWNrOiEwfSx7aWQ6Imh2Y3VydmV0byIsbWluOjQscmVzZXRTdGFjazohMH1dLFJhPVtudWxsLG51bGwsbnVsbCx7aWQ6ImFuZCIsbWluOjIsc3RhY2tEZWx0YTotMX0se2lkOiJvciIsbWluOjIsc3RhY2tEZWx0YTotMX0se2lkOiJub3QiLG1pbjoxLHN0YWNrRGVsdGE6MH0sbnVsbCxudWxsLG51bGwse2lkOiJhYnMiLG1pbjoxLHN0YWNrRGVsdGE6MH0se2lkOiJhZGQiLG1pbjoyLHN0YWNrRGVsdGE6LTEsc3RhY2tGbihlLHQpe2VbdC0yXT1lW3QtMl0rZVt0LTFdfX0se2lkOiJzdWIiLG1pbjoyLHN0YWNrRGVsdGE6LTEsc3RhY2tGbihlLHQpe2VbdC0yXT1lW3QtMl0tZVt0LTFdfX0se2lkOiJkaXYiLG1pbjoyLHN0YWNrRGVsdGE6LTEsc3RhY2tGbihlLHQpe2VbdC0yXT1lW3QtMl0vZVt0LTFdfX0sbnVsbCx7aWQ6Im5lZyIsbWluOjEsc3RhY2tEZWx0YTowLHN0YWNrRm4oZSx0KXtlW3QtMV09LWVbdC0xXX19LHtpZDoiZXEiLG1pbjoyLHN0YWNrRGVsdGE6LTF9LG51bGwsbnVsbCx7aWQ6ImRyb3AiLG1pbjoxLHN0YWNrRGVsdGE6LTF9LG51bGwse2lkOiJwdXQiLG1pbjoyLHN0YWNrRGVsdGE6LTJ9LHtpZDoiZ2V0IixtaW46MSxzdGFja0RlbHRhOjB9LHtpZDoiaWZlbHNlIixtaW46NCxzdGFja0RlbHRhOi0zfSx7aWQ6InJhbmRvbSIsbWluOjAsc3RhY2tEZWx0YToxfSx7aWQ6Im11bCIsbWluOjIsc3RhY2tEZWx0YTotMSxzdGFja0ZuKGUsdCl7ZVt0LTJdPWVbdC0yXSplW3QtMV19fSxudWxsLHtpZDoic3FydCIsbWluOjEsc3RhY2tEZWx0YTowfSx7aWQ6ImR1cCIsbWluOjEsc3RhY2tEZWx0YToxfSx7aWQ6ImV4Y2giLG1pbjoyLHN0YWNrRGVsdGE6MH0se2lkOiJpbmRleCIsbWluOjIsc3RhY2tEZWx0YTowfSx7aWQ6InJvbGwiLG1pbjozLHN0YWNrRGVsdGE6LTJ9LG51bGwsbnVsbCxudWxsLHtpZDoiaGZsZXgiLG1pbjo3LHJlc2V0U3RhY2s6ITB9LHtpZDoiZmxleCIsbWluOjEzLHJlc2V0U3RhY2s6ITB9LHtpZDoiaGZsZXgxIixtaW46OSxyZXNldFN0YWNrOiEwfSx7aWQ6ImZsZXgxIixtaW46MTEscmVzZXRTdGFjazohMH1dO2NsYXNzIENGRlBhcnNlcntjb25zdHJ1Y3RvcihlLHQscil7dGhpcy5ieXRlcz1lLmdldEJ5dGVzKCk7dGhpcy5wcm9wZXJ0aWVzPXQ7dGhpcy5zZWFjQW5hbHlzaXNFbmFibGVkPSEhcn1wYXJzZSgpe2NvbnN0IGU9dGhpcy5wcm9wZXJ0aWVzLHQ9bmV3IENGRjt0aGlzLmNmZj10O2NvbnN0IHI9dGhpcy5wYXJzZUhlYWRlcigpLGE9dGhpcy5wYXJzZUluZGV4KHIuZW5kUG9zKSxuPXRoaXMucGFyc2VJbmRleChhLmVuZFBvcyksaT10aGlzLnBhcnNlSW5kZXgobi5lbmRQb3MpLHM9dGhpcy5wYXJzZUluZGV4KGkuZW5kUG9zKSxvPXRoaXMucGFyc2VEaWN0KG4ub2JqLmdldCgwKSksYz10aGlzLmNyZWF0ZURpY3QoQ0ZGVG9wRGljdCxvLHQuc3RyaW5ncyk7dC5oZWFkZXI9ci5vYmo7dC5uYW1lcz10aGlzLnBhcnNlTmFtZUluZGV4KGEub2JqKTt0LnN0cmluZ3M9dGhpcy5wYXJzZVN0cmluZ0luZGV4KGkub2JqKTt0LnRvcERpY3Q9Yzt0Lmdsb2JhbFN1YnJJbmRleD1zLm9iajt0aGlzLnBhcnNlUHJpdmF0ZURpY3QodC50b3BEaWN0KTt0LmlzQ0lERm9udD1jLmhhc05hbWUoIlJPUyIpO2NvbnN0IGw9Yy5nZXRCeU5hbWUoIkNoYXJTdHJpbmdzIiksaD10aGlzLnBhcnNlSW5kZXgobCkub2JqLHU9Yy5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKTt1JiYoZS5mb250TWF0cml4PXUpO2NvbnN0IGQ9Yy5nZXRCeU5hbWUoIkZvbnRCQm94Iik7aWYoZCl7ZS5hc2NlbnQ9TWF0aC5tYXgoZFszXSxkWzFdKTtlLmRlc2NlbnQ9TWF0aC5taW4oZFsxXSxkWzNdKTtlLmFzY2VudFNjYWxlZD0hMH1sZXQgZixnO2lmKHQuaXNDSURGb250KXtjb25zdCBlPXRoaXMucGFyc2VJbmRleChjLmdldEJ5TmFtZSgiRkRBcnJheSIpKS5vYmo7Zm9yKGxldCByPTAsYT1lLmNvdW50O3I8YTsrK3Ipe2NvbnN0IGE9ZS5nZXQociksbj10aGlzLmNyZWF0ZURpY3QoQ0ZGVG9wRGljdCx0aGlzLnBhcnNlRGljdChhKSx0LnN0cmluZ3MpO3RoaXMucGFyc2VQcml2YXRlRGljdChuKTt0LmZkQXJyYXkucHVzaChuKX1nPW51bGw7Zj10aGlzLnBhcnNlQ2hhcnNldHMoYy5nZXRCeU5hbWUoImNoYXJzZXQiKSxoLmNvdW50LHQuc3RyaW5ncywhMCk7dC5mZFNlbGVjdD10aGlzLnBhcnNlRkRTZWxlY3QoYy5nZXRCeU5hbWUoIkZEU2VsZWN0IiksaC5jb3VudCl9ZWxzZXtmPXRoaXMucGFyc2VDaGFyc2V0cyhjLmdldEJ5TmFtZSgiY2hhcnNldCIpLGguY291bnQsdC5zdHJpbmdzLCExKTtnPXRoaXMucGFyc2VFbmNvZGluZyhjLmdldEJ5TmFtZSgiRW5jb2RpbmciKSxlLHQuc3RyaW5ncyxmLmNoYXJzZXQpfXQuY2hhcnNldD1mO3QuZW5jb2Rpbmc9Zztjb25zdCBwPXRoaXMucGFyc2VDaGFyU3RyaW5ncyh7Y2hhclN0cmluZ3M6aCxsb2NhbFN1YnJJbmRleDpjLnByaXZhdGVEaWN0LnN1YnJzSW5kZXgsZ2xvYmFsU3VickluZGV4OnMub2JqLGZkU2VsZWN0OnQuZmRTZWxlY3QsZmRBcnJheTp0LmZkQXJyYXkscHJpdmF0ZURpY3Q6Yy5wcml2YXRlRGljdH0pO3QuY2hhclN0cmluZ3M9cC5jaGFyU3RyaW5nczt0LnNlYWNzPXAuc2VhY3M7dC53aWR0aHM9cC53aWR0aHM7cmV0dXJuIHR9cGFyc2VIZWFkZXIoKXtsZXQgZT10aGlzLmJ5dGVzO2NvbnN0IHQ9ZS5sZW5ndGg7bGV0IHI9MDtmb3IoO3I8dCYmMSE9PWVbcl07KSsrcjtpZihyPj10KXRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBDRkYgaGVhZGVyIik7aWYoMCE9PXIpe2luZm8oImNmZiBkYXRhIGlzIHNoaWZ0ZWQiKTtlPWUuc3ViYXJyYXkocik7dGhpcy5ieXRlcz1lfWNvbnN0IGE9ZVswXSxuPWVbMV0saT1lWzJdLHM9ZVszXTtyZXR1cm57b2JqOm5ldyBDRkZIZWFkZXIoYSxuLGkscyksZW5kUG9zOml9fXBhcnNlRGljdChlKXtsZXQgdD0wO2Z1bmN0aW9uIHBhcnNlT3BlcmFuZCgpe2xldCByPWVbdCsrXTtpZigzMD09PXIpcmV0dXJuIGZ1bmN0aW9uIHBhcnNlRmxvYXRPcGVyYW5kKCl7bGV0IHI9IiI7Y29uc3QgYT0xNSxuPVsiMCIsIjEiLCIyIiwiMyIsIjQiLCI1IiwiNiIsIjciLCI4IiwiOSIsIi4iLCJFIiwiRS0iLG51bGwsIi0iXSxpPWUubGVuZ3RoO2Zvcig7dDxpOyl7Y29uc3QgaT1lW3QrK10scz1pPj40LG89MTUmaTtpZihzPT09YSlicmVhaztyKz1uW3NdO2lmKG89PT1hKWJyZWFrO3IrPW5bb119cmV0dXJuIHBhcnNlRmxvYXQocil9KCk7aWYoMjg9PT1yKXtyPXJlYWRJbnQxNihlLHQpO3QrPTI7cmV0dXJuIHJ9aWYoMjk9PT1yKXtyPWVbdCsrXTtyPXI8PDh8ZVt0KytdO3I9cjw8OHxlW3QrK107cj1yPDw4fGVbdCsrXTtyZXR1cm4gcn1pZihyPj0zMiYmcjw9MjQ2KXJldHVybiByLTEzOTtpZihyPj0yNDcmJnI8PTI1MClyZXR1cm4gMjU2KihyLTI0NykrZVt0KytdKzEwODtpZihyPj0yNTEmJnI8PTI1NClyZXR1cm4tMjU2KihyLTI1MSktZVt0KytdLTEwODt3YXJuKCdDRkZQYXJzZXJfcGFyc2VEaWN0OiAiJytyKyciIGlzIGEgcmVzZXJ2ZWQgY29tbWFuZC4nKTtyZXR1cm4gTmFOfWxldCByPVtdO2NvbnN0IGE9W107dD0wO2NvbnN0IG49ZS5sZW5ndGg7Zm9yKDt0PG47KXtsZXQgbj1lW3RdO2lmKG48PTIxKXsxMj09PW4mJihuPW48PDh8ZVsrK3RdKTthLnB1c2goW24scl0pO3I9W107Kyt0fWVsc2Ugci5wdXNoKHBhcnNlT3BlcmFuZCgpKX1yZXR1cm4gYX1wYXJzZUluZGV4KGUpe2NvbnN0IHQ9bmV3IENGRkluZGV4LHI9dGhpcy5ieXRlcyxhPXJbZSsrXTw8OHxyW2UrK10sbj1bXTtsZXQgaSxzLG89ZTtpZigwIT09YSl7Y29uc3QgdD1yW2UrK10sYz1lKyhhKzEpKnQtMTtmb3IoaT0wLHM9YSsxO2k8czsrK2kpe2xldCBhPTA7Zm9yKGxldCBuPTA7bjx0Oysrbil7YTw8PTg7YSs9cltlKytdfW4ucHVzaChjK2EpfW89blthXX1mb3IoaT0wLHM9bi5sZW5ndGgtMTtpPHM7KytpKXtjb25zdCBlPW5baV0sYT1uW2krMV07dC5hZGQoci5zdWJhcnJheShlLGEpKX1yZXR1cm57b2JqOnQsZW5kUG9zOm99fXBhcnNlTmFtZUluZGV4KGUpe2NvbnN0IHQ9W107Zm9yKGxldCByPTAsYT1lLmNvdW50O3I8YTsrK3Ipe2NvbnN0IGE9ZS5nZXQocik7dC5wdXNoKGJ5dGVzVG9TdHJpbmcoYSkpfXJldHVybiB0fXBhcnNlU3RyaW5nSW5kZXgoZSl7Y29uc3QgdD1uZXcgQ0ZGU3RyaW5ncztmb3IobGV0IHI9MCxhPWUuY291bnQ7cjxhOysrcil7Y29uc3QgYT1lLmdldChyKTt0LmFkZChieXRlc1RvU3RyaW5nKGEpKX1yZXR1cm4gdH1jcmVhdGVEaWN0KGUsdCxyKXtjb25zdCBhPW5ldyBlKHIpO2Zvcihjb25zdFtlLHJdb2YgdClhLnNldEJ5S2V5KGUscik7cmV0dXJuIGF9cGFyc2VDaGFyU3RyaW5nKGUsdCxyLGEpe2lmKCF0fHxlLmNhbGxEZXB0aD4xMClyZXR1cm4hMTtsZXQgbj1lLnN0YWNrU2l6ZTtjb25zdCBpPWUuc3RhY2s7bGV0IHM9dC5sZW5ndGg7Zm9yKGxldCBvPTA7bzxzOyl7Y29uc3QgYz10W28rK107bGV0IGw9bnVsbDtpZigxMj09PWMpe2NvbnN0IGU9dFtvKytdO2lmKDA9PT1lKXt0W28tMl09MTM5O3Rbby0xXT0yMjtuPTB9ZWxzZSBsPVJhW2VdfWVsc2UgaWYoMjg9PT1jKXtpW25dPXJlYWRJbnQxNih0LG8pO28rPTI7bisrfWVsc2UgaWYoMTQ9PT1jKXtpZihuPj00KXtuLT00O2lmKHRoaXMuc2VhY0FuYWx5c2lzRW5hYmxlZCl7ZS5zZWFjPWkuc2xpY2UobixuKzQpO3JldHVybiExfX1sPUJhW2NdfWVsc2UgaWYoYz49MzImJmM8PTI0Nil7aVtuXT1jLTEzOTtuKyt9ZWxzZSBpZihjPj0yNDcmJmM8PTI1NCl7aVtuXT1jPDI1MT8oYy0yNDc8PDgpK3Rbb10rMTA4Oi0oYy0yNTE8PDgpLXRbb10tMTA4O28rKztuKyt9ZWxzZSBpZigyNTU9PT1jKXtpW25dPSh0W29dPDwyNHx0W28rMV08PDE2fHRbbysyXTw8OHx0W28rM10pLzY1NTM2O28rPTQ7bisrfWVsc2UgaWYoMTk9PT1jfHwyMD09PWMpe2UuaGludHMrPW4+PjE7aWYoMD09PWUuaGludHMpe3QuY29weVdpdGhpbihvLTEsbywtMSk7by09MTtzLT0xO2NvbnRpbnVlfW8rPWUuaGludHMrNz4+MztuJT0yO2w9QmFbY119ZWxzZXtpZigxMD09PWN8fDI5PT09Yyl7Y29uc3QgdD0xMD09PWM/cjphO2lmKCF0KXtsPUJhW2NdO3dhcm4oIk1pc3Npbmcgc3VicnNJbmRleCBmb3IgIitsLmlkKTtyZXR1cm4hMX1sZXQgcz0zMjc2ODt0LmNvdW50PDEyNDA/cz0xMDc6dC5jb3VudDwzMzkwMCYmKHM9MTEzMSk7Y29uc3Qgbz1pWy0tbl0rcztpZihvPDB8fG8+PXQuY291bnR8fGlzTmFOKG8pKXtsPUJhW2NdO3dhcm4oIk91dCBvZiBib3VuZHMgc3VickluZGV4IGZvciAiK2wuaWQpO3JldHVybiExfWUuc3RhY2tTaXplPW47ZS5jYWxsRGVwdGgrKztpZighdGhpcy5wYXJzZUNoYXJTdHJpbmcoZSx0LmdldChvKSxyLGEpKXJldHVybiExO2UuY2FsbERlcHRoLS07bj1lLnN0YWNrU2l6ZTtjb250aW51ZX1pZigxMT09PWMpe2Uuc3RhY2tTaXplPW47cmV0dXJuITB9aWYoMD09PWMmJm89PT10Lmxlbmd0aCl7dFtvLTFdPTE0O2w9QmFbMTRdfWVsc2V7aWYoOT09PWMpe3QuY29weVdpdGhpbihvLTEsbywtMSk7by09MTtzLT0xO2NvbnRpbnVlfWw9QmFbY119fWlmKGwpe2lmKGwuc3RlbSl7ZS5oaW50cys9bj4+MTtpZigzPT09Y3x8MjM9PT1jKWUuaGFzVlN0ZW1zPSEwO2Vsc2UgaWYoZS5oYXNWU3RlbXMmJigxPT09Y3x8MTg9PT1jKSl7d2FybigiQ0ZGIHN0ZW0gaGludHMgYXJlIGluIHdyb25nIG9yZGVyIik7dFtvLTFdPTE9PT1jPzM6MjN9fWlmKCJtaW4iaW4gbCYmIWUudW5kZWZTdGFjayYmbjxsLm1pbil7d2FybigiTm90IGVub3VnaCBwYXJhbWV0ZXJzIGZvciAiK2wuaWQrIjsgYWN0dWFsOiAiK24rIiwgZXhwZWN0ZWQ6ICIrbC5taW4pO2lmKDA9PT1uKXt0W28tMV09MTQ7cmV0dXJuITB9cmV0dXJuITF9aWYoZS5maXJzdFN0YWNrQ2xlYXJpbmcmJmwuc3RhY2tDbGVhcmluZyl7ZS5maXJzdFN0YWNrQ2xlYXJpbmc9ITE7bi09bC5taW47bj49MiYmbC5zdGVtP24lPTI6bj4xJiZ3YXJuKCJGb3VuZCB0b28gbWFueSBwYXJhbWV0ZXJzIGZvciBzdGFjay1jbGVhcmluZyBjb21tYW5kIik7bj4wJiYoZS53aWR0aD1pW24tMV0pfWlmKCJzdGFja0RlbHRhImluIGwpeyJzdGFja0ZuImluIGwmJmwuc3RhY2tGbihpLG4pO24rPWwuc3RhY2tEZWx0YX1lbHNlIGlmKGwuc3RhY2tDbGVhcmluZyluPTA7ZWxzZSBpZihsLnJlc2V0U3RhY2spe249MDtlLnVuZGVmU3RhY2s9ITF9ZWxzZSBpZihsLnVuZGVmU3RhY2spe249MDtlLnVuZGVmU3RhY2s9ITA7ZS5maXJzdFN0YWNrQ2xlYXJpbmc9ITF9fX1zPHQubGVuZ3RoJiZ0LmZpbGwoMTQscyk7ZS5zdGFja1NpemU9bjtyZXR1cm4hMH1wYXJzZUNoYXJTdHJpbmdzKHtjaGFyU3RyaW5nczplLGxvY2FsU3VickluZGV4OnQsZ2xvYmFsU3VickluZGV4OnIsZmRTZWxlY3Q6YSxmZEFycmF5Om4scHJpdmF0ZURpY3Q6aX0pe2NvbnN0IHM9W10sbz1bXSxjPWUuY291bnQ7Zm9yKGxldCBsPTA7bDxjO2wrKyl7Y29uc3QgYz1lLmdldChsKSxoPXtjYWxsRGVwdGg6MCxzdGFja1NpemU6MCxzdGFjazpbXSx1bmRlZlN0YWNrOiEwLGhpbnRzOjAsZmlyc3RTdGFja0NsZWFyaW5nOiEwLHNlYWM6bnVsbCx3aWR0aDpudWxsLGhhc1ZTdGVtczohMX07bGV0IHU9ITAsZD1udWxsLGY9aTtpZihhJiZuLmxlbmd0aCl7Y29uc3QgZT1hLmdldEZESW5kZXgobCk7aWYoLTE9PT1lKXt3YXJuKCJHbHlwaCBpbmRleCBpcyBub3QgaW4gZmQgc2VsZWN0LiIpO3U9ITF9aWYoZT49bi5sZW5ndGgpe3dhcm4oIkludmFsaWQgZmQgaW5kZXggZm9yIGdseXBoIGluZGV4LiIpO3U9ITF9aWYodSl7Zj1uW2VdLnByaXZhdGVEaWN0O2Q9Zi5zdWJyc0luZGV4fX1lbHNlIHQmJihkPXQpO3UmJih1PXRoaXMucGFyc2VDaGFyU3RyaW5nKGgsYyxkLHIpKTtpZihudWxsIT09aC53aWR0aCl7Y29uc3QgZT1mLmdldEJ5TmFtZSgibm9taW5hbFdpZHRoWCIpO29bbF09ZStoLndpZHRofWVsc2V7Y29uc3QgZT1mLmdldEJ5TmFtZSgiZGVmYXVsdFdpZHRoWCIpO29bbF09ZX1udWxsIT09aC5zZWFjJiYoc1tsXT1oLnNlYWMpO3V8fGUuc2V0KGwsbmV3IFVpbnQ4QXJyYXkoWzE0XSkpfXJldHVybntjaGFyU3RyaW5nczplLHNlYWNzOnMsd2lkdGhzOm99fWVtcHR5UHJpdmF0ZURpY3Rpb25hcnkoZSl7Y29uc3QgdD10aGlzLmNyZWF0ZURpY3QoQ0ZGUHJpdmF0ZURpY3QsW10sZS5zdHJpbmdzKTtlLnNldEJ5S2V5KDE4LFswLDBdKTtlLnByaXZhdGVEaWN0PXR9cGFyc2VQcml2YXRlRGljdChlKXtpZighZS5oYXNOYW1lKCJQcml2YXRlIikpe3RoaXMuZW1wdHlQcml2YXRlRGljdGlvbmFyeShlKTtyZXR1cm59Y29uc3QgdD1lLmdldEJ5TmFtZSgiUHJpdmF0ZSIpO2lmKCFBcnJheS5pc0FycmF5KHQpfHwyIT09dC5sZW5ndGgpe2UucmVtb3ZlQnlOYW1lKCJQcml2YXRlIik7cmV0dXJufWNvbnN0IHI9dFswXSxhPXRbMV07aWYoMD09PXJ8fGE+PXRoaXMuYnl0ZXMubGVuZ3RoKXt0aGlzLmVtcHR5UHJpdmF0ZURpY3Rpb25hcnkoZSk7cmV0dXJufWNvbnN0IG49YStyLGk9dGhpcy5ieXRlcy5zdWJhcnJheShhLG4pLHM9dGhpcy5wYXJzZURpY3QoaSksbz10aGlzLmNyZWF0ZURpY3QoQ0ZGUHJpdmF0ZURpY3QscyxlLnN0cmluZ3MpO2UucHJpdmF0ZURpY3Q9bzswPT09by5nZXRCeU5hbWUoIkV4cGFuc2lvbkZhY3RvciIpJiZvLnNldEJ5TmFtZSgiRXhwYW5zaW9uRmFjdG9yIiwuMDYpO2lmKCFvLmdldEJ5TmFtZSgiU3VicnMiKSlyZXR1cm47Y29uc3QgYz1vLmdldEJ5TmFtZSgiU3VicnMiKSxsPWErYztpZigwPT09Y3x8bD49dGhpcy5ieXRlcy5sZW5ndGgpe3RoaXMuZW1wdHlQcml2YXRlRGljdGlvbmFyeShlKTtyZXR1cm59Y29uc3QgaD10aGlzLnBhcnNlSW5kZXgobCk7by5zdWJyc0luZGV4PWgub2JqfXBhcnNlQ2hhcnNldHMoZSx0LHIsYSl7aWYoMD09PWUpcmV0dXJuIG5ldyBDRkZDaGFyc2V0KCEwLFBhLklTT19BRE9CRSxJYSk7aWYoMT09PWUpcmV0dXJuIG5ldyBDRkZDaGFyc2V0KCEwLFBhLkVYUEVSVCxUYSk7aWYoMj09PWUpcmV0dXJuIG5ldyBDRkZDaGFyc2V0KCEwLFBhLkVYUEVSVF9TVUJTRVQsT2EpO2NvbnN0IG49dGhpcy5ieXRlcyxpPWUscz1uW2UrK10sbz1bYT8wOiIubm90ZGVmIl07bGV0IGMsbCxoO3QtPTE7c3dpdGNoKHMpe2Nhc2UgMDpmb3IoaD0wO2g8dDtoKyspe2M9bltlKytdPDw4fG5bZSsrXTtvLnB1c2goYT9jOnIuZ2V0KGMpKX1icmVhaztjYXNlIDE6Zm9yKDtvLmxlbmd0aDw9dDspe2M9bltlKytdPDw4fG5bZSsrXTtsPW5bZSsrXTtmb3IoaD0wO2g8PWw7aCsrKW8ucHVzaChhP2MrKzpyLmdldChjKyspKX1icmVhaztjYXNlIDI6Zm9yKDtvLmxlbmd0aDw9dDspe2M9bltlKytdPDw4fG5bZSsrXTtsPW5bZSsrXTw8OHxuW2UrK107Zm9yKGg9MDtoPD1sO2grKylvLnB1c2goYT9jKys6ci5nZXQoYysrKSl9YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gY2hhcnNldCBmb3JtYXQiKX1jb25zdCB1PWUsZD1uLnN1YmFycmF5KGksdSk7cmV0dXJuIG5ldyBDRkZDaGFyc2V0KCExLHMsbyxkKX1wYXJzZUVuY29kaW5nKGUsdCxyLGEpe2NvbnN0IG49T2JqZWN0LmNyZWF0ZShudWxsKSxpPXRoaXMuYnl0ZXM7bGV0IHMsbyxjLGw9ITEsaD1udWxsO2lmKDA9PT1lfHwxPT09ZSl7bD0hMDtzPWU7Y29uc3QgdD1lP29hOmhhO2ZvcihvPTAsYz1hLmxlbmd0aDtvPGM7bysrKXtjb25zdCBlPXQuaW5kZXhPZihhW29dKTstMSE9PWUmJihuW2VdPW8pfX1lbHNle2NvbnN0IHQ9ZTtzPWlbZSsrXTtzd2l0Y2goMTI3JnMpe2Nhc2UgMDpjb25zdCB0PWlbZSsrXTtmb3Iobz0xO288PXQ7bysrKW5baVtlKytdXT1vO2JyZWFrO2Nhc2UgMTpjb25zdCByPWlbZSsrXTtsZXQgYT0xO2ZvcihvPTA7bzxyO28rKyl7Y29uc3QgdD1pW2UrK10scj1pW2UrK107Zm9yKGxldCBlPXQ7ZTw9dCtyO2UrKyluW2VdPWErK31icmVhaztkZWZhdWx0OnRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBlbmNvZGluZyBmb3JtYXQ6ICR7c30gaW4gQ0ZGYCl9Y29uc3QgYz1lO2lmKDEyOCZzKXtpW3RdJj0xMjc7IWZ1bmN0aW9uIHJlYWRTdXBwbGVtZW50KCl7Y29uc3QgdD1pW2UrK107Zm9yKG89MDtvPHQ7bysrKXtjb25zdCB0PWlbZSsrXSxzPShpW2UrK108PDgpKygyNTUmaVtlKytdKTtuW3RdPWEuaW5kZXhPZihyLmdldChzKSl9fSgpfWg9aS5zdWJhcnJheSh0LGMpfXMmPTEyNztyZXR1cm4gbmV3IENGRkVuY29kaW5nKGwscyxuLGgpfXBhcnNlRkRTZWxlY3QoZSx0KXtjb25zdCByPXRoaXMuYnl0ZXMsYT1yW2UrK10sbj1bXTtsZXQgaTtzd2l0Y2goYSl7Y2FzZSAwOmZvcihpPTA7aTx0OysraSl7Y29uc3QgdD1yW2UrK107bi5wdXNoKHQpfWJyZWFrO2Nhc2UgMzpjb25zdCBzPXJbZSsrXTw8OHxyW2UrK107Zm9yKGk9MDtpPHM7KytpKXtsZXQgdD1yW2UrK108PDh8cltlKytdO2lmKDA9PT1pJiYwIT09dCl7d2FybigicGFyc2VGRFNlbGVjdDogVGhlIGZpcnN0IHJhbmdlIG11c3QgaGF2ZSBhIGZpcnN0IEdJRCBvZiAwIC0tIHRyeWluZyB0byByZWNvdmVyLiIpO3Q9MH1jb25zdCBhPXJbZSsrXSxzPXJbZV08PDh8cltlKzFdO2ZvcihsZXQgZT10O2U8czsrK2Upbi5wdXNoKGEpfWUrPTI7YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHBhcnNlRkRTZWxlY3Q6IFVua25vd24gZm9ybWF0ICIke2F9Ii5gKX1pZihuLmxlbmd0aCE9PXQpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJwYXJzZUZEU2VsZWN0OiBJbnZhbGlkIGZvbnQgZGF0YS4iKTtyZXR1cm4gbmV3IENGRkZEU2VsZWN0KGEsbil9fWNsYXNzIENGRntjb25zdHJ1Y3Rvcigpe3RoaXMuaGVhZGVyPW51bGw7dGhpcy5uYW1lcz1bXTt0aGlzLnRvcERpY3Q9bnVsbDt0aGlzLnN0cmluZ3M9bmV3IENGRlN0cmluZ3M7dGhpcy5nbG9iYWxTdWJySW5kZXg9bnVsbDt0aGlzLmVuY29kaW5nPW51bGw7dGhpcy5jaGFyc2V0PW51bGw7dGhpcy5jaGFyU3RyaW5ncz1udWxsO3RoaXMuZmRBcnJheT1bXTt0aGlzLmZkU2VsZWN0PW51bGw7dGhpcy5pc0NJREZvbnQ9ITF9ZHVwbGljYXRlRmlyc3RHbHlwaCgpe2lmKHRoaXMuY2hhclN0cmluZ3MuY291bnQ+PTY1NTM1KXt3YXJuKCJOb3QgZW5vdWdoIHNwYWNlIGluIGNoYXJzdHJpbmdzIHRvIGR1cGxpY2F0ZSBmaXJzdCBnbHlwaC4iKTtyZXR1cm59Y29uc3QgZT10aGlzLmNoYXJTdHJpbmdzLmdldCgwKTt0aGlzLmNoYXJTdHJpbmdzLmFkZChlKTt0aGlzLmlzQ0lERm9udCYmdGhpcy5mZFNlbGVjdC5mZFNlbGVjdC5wdXNoKHRoaXMuZmRTZWxlY3QuZmRTZWxlY3RbMF0pfWhhc0dseXBoSWQoZSl7aWYoZTwwfHxlPj10aGlzLmNoYXJTdHJpbmdzLmNvdW50KXJldHVybiExO3JldHVybiB0aGlzLmNoYXJTdHJpbmdzLmdldChlKS5sZW5ndGg+MH19Y2xhc3MgQ0ZGSGVhZGVye2NvbnN0cnVjdG9yKGUsdCxyLGEpe3RoaXMubWFqb3I9ZTt0aGlzLm1pbm9yPXQ7dGhpcy5oZHJTaXplPXI7dGhpcy5vZmZTaXplPWF9fWNsYXNzIENGRlN0cmluZ3N7Y29uc3RydWN0b3IoKXt0aGlzLnN0cmluZ3M9W119Z2V0KGUpe3JldHVybiBlPj0wJiZlPD0zOTA/TWFbZV06ZS1EYTw9dGhpcy5zdHJpbmdzLmxlbmd0aD90aGlzLnN0cmluZ3NbZS1EYV06TWFbMF19Z2V0U0lEKGUpe2xldCB0PU1hLmluZGV4T2YoZSk7aWYoLTEhPT10KXJldHVybiB0O3Q9dGhpcy5zdHJpbmdzLmluZGV4T2YoZSk7cmV0dXJuLTEhPT10P3QrRGE6LTF9YWRkKGUpe3RoaXMuc3RyaW5ncy5wdXNoKGUpfWdldCBjb3VudCgpe3JldHVybiB0aGlzLnN0cmluZ3MubGVuZ3RofX1jbGFzcyBDRkZJbmRleHtjb25zdHJ1Y3Rvcigpe3RoaXMub2JqZWN0cz1bXTt0aGlzLmxlbmd0aD0wfWFkZChlKXt0aGlzLmxlbmd0aCs9ZS5sZW5ndGg7dGhpcy5vYmplY3RzLnB1c2goZSl9c2V0KGUsdCl7dGhpcy5sZW5ndGgrPXQubGVuZ3RoLXRoaXMub2JqZWN0c1tlXS5sZW5ndGg7dGhpcy5vYmplY3RzW2VdPXR9Z2V0KGUpe3JldHVybiB0aGlzLm9iamVjdHNbZV19Z2V0IGNvdW50KCl7cmV0dXJuIHRoaXMub2JqZWN0cy5sZW5ndGh9fWNsYXNzIENGRkRpY3R7Y29uc3RydWN0b3IoZSx0KXt0aGlzLmtleVRvTmFtZU1hcD1lLmtleVRvTmFtZU1hcDt0aGlzLm5hbWVUb0tleU1hcD1lLm5hbWVUb0tleU1hcDt0aGlzLmRlZmF1bHRzPWUuZGVmYXVsdHM7dGhpcy50eXBlcz1lLnR5cGVzO3RoaXMub3Bjb2Rlcz1lLm9wY29kZXM7dGhpcy5vcmRlcj1lLm9yZGVyO3RoaXMuc3RyaW5ncz10O3RoaXMudmFsdWVzPU9iamVjdC5jcmVhdGUobnVsbCl9c2V0QnlLZXkoZSx0KXtpZighKGUgaW4gdGhpcy5rZXlUb05hbWVNYXApKXJldHVybiExO2lmKDA9PT10Lmxlbmd0aClyZXR1cm4hMDtmb3IoY29uc3QgciBvZiB0KWlmKGlzTmFOKHIpKXt3YXJuKGBJbnZhbGlkIENGRkRpY3QgdmFsdWU6ICIke3R9IiBmb3Iga2V5ICIke2V9Ii5gKTtyZXR1cm4hMH1jb25zdCByPXRoaXMudHlwZXNbZV07Im51bSIhPT1yJiYic2lkIiE9PXImJiJvZmZzZXQiIT09cnx8KHQ9dFswXSk7dGhpcy52YWx1ZXNbZV09dDtyZXR1cm4hMH1zZXRCeU5hbWUoZSx0KXtpZighKGUgaW4gdGhpcy5uYW1lVG9LZXlNYXApKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBkaWN0aW9uYXJ5IG5hbWUgIiR7ZX0iYCk7dGhpcy52YWx1ZXNbdGhpcy5uYW1lVG9LZXlNYXBbZV1dPXR9aGFzTmFtZShlKXtyZXR1cm4gdGhpcy5uYW1lVG9LZXlNYXBbZV1pbiB0aGlzLnZhbHVlc31nZXRCeU5hbWUoZSl7aWYoIShlIGluIHRoaXMubmFtZVRvS2V5TWFwKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZGljdGlvbmFyeSBuYW1lICR7ZX0iYCk7Y29uc3QgdD10aGlzLm5hbWVUb0tleU1hcFtlXTtyZXR1cm4gdCBpbiB0aGlzLnZhbHVlcz90aGlzLnZhbHVlc1t0XTp0aGlzLmRlZmF1bHRzW3RdfXJlbW92ZUJ5TmFtZShlKXtkZWxldGUgdGhpcy52YWx1ZXNbdGhpcy5uYW1lVG9LZXlNYXBbZV1dfXN0YXRpYyBjcmVhdGVUYWJsZXMoZSl7Y29uc3QgdD17a2V5VG9OYW1lTWFwOnt9LG5hbWVUb0tleU1hcDp7fSxkZWZhdWx0czp7fSx0eXBlczp7fSxvcGNvZGVzOnt9LG9yZGVyOltdfTtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPUFycmF5LmlzQXJyYXkoclswXSk/KHJbMF1bMF08PDgpK3JbMF1bMV06clswXTt0LmtleVRvTmFtZU1hcFtlXT1yWzFdO3QubmFtZVRvS2V5TWFwW3JbMV1dPWU7dC50eXBlc1tlXT1yWzJdO3QuZGVmYXVsdHNbZV09clszXTt0Lm9wY29kZXNbZV09QXJyYXkuaXNBcnJheShyWzBdKT9yWzBdOltyWzBdXTt0Lm9yZGVyLnB1c2goZSl9cmV0dXJuIHR9fWNvbnN0IEVhPVtbWzEyLDMwXSwiUk9TIixbInNpZCIsInNpZCIsIm51bSJdLG51bGxdLFtbMTIsMjBdLCJTeW50aGV0aWNCYXNlIiwibnVtIixudWxsXSxbMCwidmVyc2lvbiIsInNpZCIsbnVsbF0sWzEsIk5vdGljZSIsInNpZCIsbnVsbF0sW1sxMiwwXSwiQ29weXJpZ2h0Iiwic2lkIixudWxsXSxbMiwiRnVsbE5hbWUiLCJzaWQiLG51bGxdLFszLCJGYW1pbHlOYW1lIiwic2lkIixudWxsXSxbNCwiV2VpZ2h0Iiwic2lkIixudWxsXSxbWzEyLDFdLCJpc0ZpeGVkUGl0Y2giLCJudW0iLDBdLFtbMTIsMl0sIkl0YWxpY0FuZ2xlIiwibnVtIiwwXSxbWzEyLDNdLCJVbmRlcmxpbmVQb3NpdGlvbiIsIm51bSIsLTEwMF0sW1sxMiw0XSwiVW5kZXJsaW5lVGhpY2tuZXNzIiwibnVtIiw1MF0sW1sxMiw1XSwiUGFpbnRUeXBlIiwibnVtIiwwXSxbWzEyLDZdLCJDaGFyc3RyaW5nVHlwZSIsIm51bSIsMl0sW1sxMiw3XSwiRm9udE1hdHJpeCIsWyJudW0iLCJudW0iLCJudW0iLCJudW0iLCJudW0iLCJudW0iXSxbLjAwMSwwLDAsLjAwMSwwLDBdXSxbMTMsIlVuaXF1ZUlEIiwibnVtIixudWxsXSxbNSwiRm9udEJCb3giLFsibnVtIiwibnVtIiwibnVtIiwibnVtIl0sWzAsMCwwLDBdXSxbWzEyLDhdLCJTdHJva2VXaWR0aCIsIm51bSIsMF0sWzE0LCJYVUlEIiwiYXJyYXkiLG51bGxdLFsxNSwiY2hhcnNldCIsIm9mZnNldCIsMF0sWzE2LCJFbmNvZGluZyIsIm9mZnNldCIsMF0sWzE3LCJDaGFyU3RyaW5ncyIsIm9mZnNldCIsMF0sWzE4LCJQcml2YXRlIixbIm9mZnNldCIsIm9mZnNldCJdLG51bGxdLFtbMTIsMjFdLCJQb3N0U2NyaXB0Iiwic2lkIixudWxsXSxbWzEyLDIyXSwiQmFzZUZvbnROYW1lIiwic2lkIixudWxsXSxbWzEyLDIzXSwiQmFzZUZvbnRCbGVuZCIsImRlbHRhIixudWxsXSxbWzEyLDMxXSwiQ0lERm9udFZlcnNpb24iLCJudW0iLDBdLFtbMTIsMzJdLCJDSURGb250UmV2aXNpb24iLCJudW0iLDBdLFtbMTIsMzNdLCJDSURGb250VHlwZSIsIm51bSIsMF0sW1sxMiwzNF0sIkNJRENvdW50IiwibnVtIiw4NzIwXSxbWzEyLDM1XSwiVUlEQmFzZSIsIm51bSIsbnVsbF0sW1sxMiwzN10sIkZEU2VsZWN0Iiwib2Zmc2V0IixudWxsXSxbWzEyLDM2XSwiRkRBcnJheSIsIm9mZnNldCIsbnVsbF0sW1sxMiwzOF0sIkZvbnROYW1lIiwic2lkIixudWxsXV07Y2xhc3MgQ0ZGVG9wRGljdCBleHRlbmRzIENGRkRpY3R7c3RhdGljIGdldCB0YWJsZXMoKXtyZXR1cm4gc2hhZG93KHRoaXMsInRhYmxlcyIsdGhpcy5jcmVhdGVUYWJsZXMoRWEpKX1jb25zdHJ1Y3RvcihlKXtzdXBlcihDRkZUb3BEaWN0LnRhYmxlcyxlKTt0aGlzLnByaXZhdGVEaWN0PW51bGx9fWNvbnN0IE5hPVtbNiwiQmx1ZVZhbHVlcyIsImRlbHRhIixudWxsXSxbNywiT3RoZXJCbHVlcyIsImRlbHRhIixudWxsXSxbOCwiRmFtaWx5Qmx1ZXMiLCJkZWx0YSIsbnVsbF0sWzksIkZhbWlseU90aGVyQmx1ZXMiLCJkZWx0YSIsbnVsbF0sW1sxMiw5XSwiQmx1ZVNjYWxlIiwibnVtIiwuMDM5NjI1XSxbWzEyLDEwXSwiQmx1ZVNoaWZ0IiwibnVtIiw3XSxbWzEyLDExXSwiQmx1ZUZ1enoiLCJudW0iLDFdLFsxMCwiU3RkSFciLCJudW0iLG51bGxdLFsxMSwiU3RkVlciLCJudW0iLG51bGxdLFtbMTIsMTJdLCJTdGVtU25hcEgiLCJkZWx0YSIsbnVsbF0sW1sxMiwxM10sIlN0ZW1TbmFwViIsImRlbHRhIixudWxsXSxbWzEyLDE0XSwiRm9yY2VCb2xkIiwibnVtIiwwXSxbWzEyLDE3XSwiTGFuZ3VhZ2VHcm91cCIsIm51bSIsMF0sW1sxMiwxOF0sIkV4cGFuc2lvbkZhY3RvciIsIm51bSIsLjA2XSxbWzEyLDE5XSwiaW5pdGlhbFJhbmRvbVNlZWQiLCJudW0iLDBdLFsyMCwiZGVmYXVsdFdpZHRoWCIsIm51bSIsMF0sWzIxLCJub21pbmFsV2lkdGhYIiwibnVtIiwwXSxbMTksIlN1YnJzIiwib2Zmc2V0IixudWxsXV07Y2xhc3MgQ0ZGUHJpdmF0ZURpY3QgZXh0ZW5kcyBDRkZEaWN0e3N0YXRpYyBnZXQgdGFibGVzKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJ0YWJsZXMiLHRoaXMuY3JlYXRlVGFibGVzKE5hKSl9Y29uc3RydWN0b3IoZSl7c3VwZXIoQ0ZGUHJpdmF0ZURpY3QudGFibGVzLGUpO3RoaXMuc3VicnNJbmRleD1udWxsfX1jb25zdCBQYT17SVNPX0FET0JFOjAsRVhQRVJUOjEsRVhQRVJUX1NVQlNFVDoyfTtjbGFzcyBDRkZDaGFyc2V0e2NvbnN0cnVjdG9yKGUsdCxyLGEpe3RoaXMucHJlZGVmaW5lZD1lO3RoaXMuZm9ybWF0PXQ7dGhpcy5jaGFyc2V0PXI7dGhpcy5yYXc9YX19Y2xhc3MgQ0ZGRW5jb2Rpbmd7Y29uc3RydWN0b3IoZSx0LHIsYSl7dGhpcy5wcmVkZWZpbmVkPWU7dGhpcy5mb3JtYXQ9dDt0aGlzLmVuY29kaW5nPXI7dGhpcy5yYXc9YX19Y2xhc3MgQ0ZGRkRTZWxlY3R7Y29uc3RydWN0b3IoZSx0KXt0aGlzLmZvcm1hdD1lO3RoaXMuZmRTZWxlY3Q9dH1nZXRGREluZGV4KGUpe3JldHVybiBlPDB8fGU+PXRoaXMuZmRTZWxlY3QubGVuZ3RoPy0xOnRoaXMuZmRTZWxlY3RbZV19fWNsYXNzIENGRk9mZnNldFRyYWNrZXJ7Y29uc3RydWN0b3IoKXt0aGlzLm9mZnNldHM9T2JqZWN0LmNyZWF0ZShudWxsKX1pc1RyYWNraW5nKGUpe3JldHVybiBlIGluIHRoaXMub2Zmc2V0c310cmFjayhlLHQpe2lmKGUgaW4gdGhpcy5vZmZzZXRzKXRocm93IG5ldyBGb3JtYXRFcnJvcihgQWxyZWFkeSB0cmFja2luZyBsb2NhdGlvbiBvZiAke2V9YCk7dGhpcy5vZmZzZXRzW2VdPXR9b2Zmc2V0KGUpe2Zvcihjb25zdCB0IGluIHRoaXMub2Zmc2V0cyl0aGlzLm9mZnNldHNbdF0rPWV9c2V0RW50cnlMb2NhdGlvbihlLHQscil7aWYoIShlIGluIHRoaXMub2Zmc2V0cykpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBOb3QgdHJhY2tpbmcgbG9jYXRpb24gb2YgJHtlfWApO2NvbnN0IGE9ci5kYXRhLG49dGhpcy5vZmZzZXRzW2VdO2ZvcihsZXQgZT0wLHI9dC5sZW5ndGg7ZTxyOysrZSl7Y29uc3Qgcj01KmUrbixpPXIrMSxzPXIrMixvPXIrMyxjPXIrNDtpZigyOSE9PWFbcl18fDAhPT1hW2ldfHwwIT09YVtzXXx8MCE9PWFbb118fDAhPT1hW2NdKXRocm93IG5ldyBGb3JtYXRFcnJvcigid3JpdGluZyB0byBhbiBvZmZzZXQgdGhhdCBpcyBub3QgZW1wdHkiKTtjb25zdCBsPXRbZV07YVtyXT0yOTthW2ldPWw+PjI0JjI1NTthW3NdPWw+PjE2JjI1NTthW29dPWw+PjgmMjU1O2FbY109MjU1Jmx9fX1jbGFzcyBDRkZDb21waWxlcntjb25zdHJ1Y3RvcihlKXt0aGlzLmNmZj1lfWNvbXBpbGUoKXtjb25zdCBlPXRoaXMuY2ZmLHQ9e2RhdGE6W10sbGVuZ3RoOjAsYWRkKGUpe3RyeXt0aGlzLmRhdGEucHVzaCguLi5lKX1jYXRjaHt0aGlzLmRhdGE9dGhpcy5kYXRhLmNvbmNhdChlKX10aGlzLmxlbmd0aD10aGlzLmRhdGEubGVuZ3RofX0scj10aGlzLmNvbXBpbGVIZWFkZXIoZS5oZWFkZXIpO3QuYWRkKHIpO2NvbnN0IGE9dGhpcy5jb21waWxlTmFtZUluZGV4KGUubmFtZXMpO3QuYWRkKGEpO2lmKGUuaXNDSURGb250JiZlLnRvcERpY3QuaGFzTmFtZSgiRm9udE1hdHJpeCIpKXtjb25zdCB0PWUudG9wRGljdC5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKTtlLnRvcERpY3QucmVtb3ZlQnlOYW1lKCJGb250TWF0cml4Iik7Zm9yKGNvbnN0IHIgb2YgZS5mZEFycmF5KXtsZXQgZT10LnNsaWNlKDApO3IuaGFzTmFtZSgiRm9udE1hdHJpeCIpJiYoZT1VdGlsLnRyYW5zZm9ybShlLHIuZ2V0QnlOYW1lKCJGb250TWF0cml4IikpKTtyLnNldEJ5TmFtZSgiRm9udE1hdHJpeCIsZSl9fWNvbnN0IG49ZS50b3BEaWN0LmdldEJ5TmFtZSgiWFVJRCIpO24/Lmxlbmd0aD4xNiYmZS50b3BEaWN0LnJlbW92ZUJ5TmFtZSgiWFVJRCIpO2UudG9wRGljdC5zZXRCeU5hbWUoImNoYXJzZXQiLDApO2xldCBpPXRoaXMuY29tcGlsZVRvcERpY3RzKFtlLnRvcERpY3RdLHQubGVuZ3RoLGUuaXNDSURGb250KTt0LmFkZChpLm91dHB1dCk7Y29uc3Qgcz1pLnRyYWNrZXJzWzBdLG89dGhpcy5jb21waWxlU3RyaW5nSW5kZXgoZS5zdHJpbmdzLnN0cmluZ3MpO3QuYWRkKG8pO2NvbnN0IGM9dGhpcy5jb21waWxlSW5kZXgoZS5nbG9iYWxTdWJySW5kZXgpO3QuYWRkKGMpO2lmKGUuZW5jb2RpbmcmJmUudG9wRGljdC5oYXNOYW1lKCJFbmNvZGluZyIpKWlmKGUuZW5jb2RpbmcucHJlZGVmaW5lZClzLnNldEVudHJ5TG9jYXRpb24oIkVuY29kaW5nIixbZS5lbmNvZGluZy5mb3JtYXRdLHQpO2Vsc2V7Y29uc3Qgcj10aGlzLmNvbXBpbGVFbmNvZGluZyhlLmVuY29kaW5nKTtzLnNldEVudHJ5TG9jYXRpb24oIkVuY29kaW5nIixbdC5sZW5ndGhdLHQpO3QuYWRkKHIpfWNvbnN0IGw9dGhpcy5jb21waWxlQ2hhcnNldChlLmNoYXJzZXQsZS5jaGFyU3RyaW5ncy5jb3VudCxlLnN0cmluZ3MsZS5pc0NJREZvbnQpO3Muc2V0RW50cnlMb2NhdGlvbigiY2hhcnNldCIsW3QubGVuZ3RoXSx0KTt0LmFkZChsKTtjb25zdCBoPXRoaXMuY29tcGlsZUNoYXJTdHJpbmdzKGUuY2hhclN0cmluZ3MpO3Muc2V0RW50cnlMb2NhdGlvbigiQ2hhclN0cmluZ3MiLFt0Lmxlbmd0aF0sdCk7dC5hZGQoaCk7aWYoZS5pc0NJREZvbnQpe3Muc2V0RW50cnlMb2NhdGlvbigiRkRTZWxlY3QiLFt0Lmxlbmd0aF0sdCk7Y29uc3Qgcj10aGlzLmNvbXBpbGVGRFNlbGVjdChlLmZkU2VsZWN0KTt0LmFkZChyKTtpPXRoaXMuY29tcGlsZVRvcERpY3RzKGUuZmRBcnJheSx0Lmxlbmd0aCwhMCk7cy5zZXRFbnRyeUxvY2F0aW9uKCJGREFycmF5IixbdC5sZW5ndGhdLHQpO3QuYWRkKGkub3V0cHV0KTtjb25zdCBhPWkudHJhY2tlcnM7dGhpcy5jb21waWxlUHJpdmF0ZURpY3RzKGUuZmRBcnJheSxhLHQpfXRoaXMuY29tcGlsZVByaXZhdGVEaWN0cyhbZS50b3BEaWN0XSxbc10sdCk7dC5hZGQoWzBdKTtyZXR1cm4gdC5kYXRhfWVuY29kZU51bWJlcihlKXtyZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihlKT90aGlzLmVuY29kZUludGVnZXIoZSk6dGhpcy5lbmNvZGVGbG9hdChlKX1zdGF0aWMgZ2V0IEVuY29kZUZsb2F0UmVnRXhwKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJFbmNvZGVGbG9hdFJlZ0V4cCIsL1wuKFxkKj8pKD86OXs1LDIwfXwwezUsMjB9KVxkezAsMn0oPzplKC4rKXwkKS8pfWVuY29kZUZsb2F0KGUpe2xldCB0PWUudG9TdHJpbmcoKTtjb25zdCByPUNGRkNvbXBpbGVyLkVuY29kZUZsb2F0UmVnRXhwLmV4ZWModCk7aWYocil7Y29uc3QgYT1wYXJzZUZsb2F0KCIxZSIrKChyWzJdPytyWzJdOjApK3JbMV0ubGVuZ3RoKSk7dD0oTWF0aC5yb3VuZChlKmEpL2EpLnRvU3RyaW5nKCl9bGV0IGEsbixpPSIiO2ZvcihhPTAsbj10Lmxlbmd0aDthPG47KythKXtjb25zdCBlPXRbYV07aSs9ImUiPT09ZT8iLSI9PT10WysrYV0/ImMiOiJiIjoiLiI9PT1lPyJhIjoiLSI9PT1lPyJlIjplfWkrPTEmaS5sZW5ndGg/ImYiOiJmZiI7Y29uc3Qgcz1bMzBdO2ZvcihhPTAsbj1pLmxlbmd0aDthPG47YSs9MilzLnB1c2gocGFyc2VJbnQoaS5zdWJzdHJpbmcoYSxhKzIpLDE2KSk7cmV0dXJuIHN9ZW5jb2RlSW50ZWdlcihlKXtsZXQgdDt0PWU+PS0xMDcmJmU8PTEwNz9bZSsxMzldOmU+PTEwOCYmZTw9MTEzMT9bMjQ3KygoZS09MTA4KT4+OCksMjU1JmVdOmU+PS0xMTMxJiZlPD0tMTA4P1syNTErKChlPS1lLTEwOCk+PjgpLDI1NSZlXTplPj0tMzI3NjgmJmU8PTMyNzY3P1syOCxlPj44JjI1NSwyNTUmZV06WzI5LGU+PjI0JjI1NSxlPj4xNiYyNTUsZT4+OCYyNTUsMjU1JmVdO3JldHVybiB0fWNvbXBpbGVIZWFkZXIoZSl7cmV0dXJuW2UubWFqb3IsZS5taW5vciw0LGUub2ZmU2l6ZV19Y29tcGlsZU5hbWVJbmRleChlKXtjb25zdCB0PW5ldyBDRkZJbmRleDtmb3IoY29uc3QgciBvZiBlKXtjb25zdCBlPU1hdGgubWluKHIubGVuZ3RoLDEyNyk7bGV0IGE9bmV3IEFycmF5KGUpO2ZvcihsZXQgdD0wO3Q8ZTt0Kyspe2xldCBlPXJbdF07KGU8IiEifHxlPiJ+Inx8IlsiPT09ZXx8Il0iPT09ZXx8IigiPT09ZXx8IikiPT09ZXx8InsiPT09ZXx8In0iPT09ZXx8IjwiPT09ZXx8Ij4iPT09ZXx8Ii8iPT09ZXx8IiUiPT09ZSkmJihlPSJfIik7YVt0XT1lfWE9YS5qb2luKCIiKTsiIj09PWEmJihhPSJCYWRfRm9udF9OYW1lIik7dC5hZGQoc3RyaW5nVG9CeXRlcyhhKSl9cmV0dXJuIHRoaXMuY29tcGlsZUluZGV4KHQpfWNvbXBpbGVUb3BEaWN0cyhlLHQscil7Y29uc3QgYT1bXTtsZXQgbj1uZXcgQ0ZGSW5kZXg7Zm9yKGNvbnN0IGkgb2YgZSl7aWYocil7aS5yZW1vdmVCeU5hbWUoIkNJREZvbnRWZXJzaW9uIik7aS5yZW1vdmVCeU5hbWUoIkNJREZvbnRSZXZpc2lvbiIpO2kucmVtb3ZlQnlOYW1lKCJDSURGb250VHlwZSIpO2kucmVtb3ZlQnlOYW1lKCJDSURDb3VudCIpO2kucmVtb3ZlQnlOYW1lKCJVSURCYXNlIil9Y29uc3QgZT1uZXcgQ0ZGT2Zmc2V0VHJhY2tlcixzPXRoaXMuY29tcGlsZURpY3QoaSxlKTthLnB1c2goZSk7bi5hZGQocyk7ZS5vZmZzZXQodCl9bj10aGlzLmNvbXBpbGVJbmRleChuLGEpO3JldHVybnt0cmFja2VyczphLG91dHB1dDpufX1jb21waWxlUHJpdmF0ZURpY3RzKGUsdCxyKXtmb3IobGV0IGE9MCxuPWUubGVuZ3RoO2E8bjsrK2Epe2NvbnN0IG49ZVthXSxpPW4ucHJpdmF0ZURpY3Q7aWYoIWl8fCFuLmhhc05hbWUoIlByaXZhdGUiKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlRoZXJlIG11c3QgYmUgYSBwcml2YXRlIGRpY3Rpb25hcnkuIik7Y29uc3Qgcz1uZXcgQ0ZGT2Zmc2V0VHJhY2tlcixvPXRoaXMuY29tcGlsZURpY3QoaSxzKTtsZXQgYz1yLmxlbmd0aDtzLm9mZnNldChjKTtvLmxlbmd0aHx8KGM9MCk7dFthXS5zZXRFbnRyeUxvY2F0aW9uKCJQcml2YXRlIixbby5sZW5ndGgsY10scik7ci5hZGQobyk7aWYoaS5zdWJyc0luZGV4JiZpLmhhc05hbWUoIlN1YnJzIikpe2NvbnN0IGU9dGhpcy5jb21waWxlSW5kZXgoaS5zdWJyc0luZGV4KTtzLnNldEVudHJ5TG9jYXRpb24oIlN1YnJzIixbby5sZW5ndGhdLHIpO3IuYWRkKGUpfX19Y29tcGlsZURpY3QoZSx0KXtjb25zdCByPVtdO2Zvcihjb25zdCBhIG9mIGUub3JkZXIpe2lmKCEoYSBpbiBlLnZhbHVlcykpY29udGludWU7bGV0IG49ZS52YWx1ZXNbYV0saT1lLnR5cGVzW2FdO0FycmF5LmlzQXJyYXkoaSl8fChpPVtpXSk7QXJyYXkuaXNBcnJheShuKXx8KG49W25dKTtpZigwIT09bi5sZW5ndGgpe2ZvcihsZXQgcz0wLG89aS5sZW5ndGg7czxvOysrcyl7Y29uc3Qgbz1pW3NdLGM9bltzXTtzd2l0Y2gobyl7Y2FzZSJudW0iOmNhc2Uic2lkIjpyLnB1c2goLi4udGhpcy5lbmNvZGVOdW1iZXIoYykpO2JyZWFrO2Nhc2Uib2Zmc2V0Ijpjb25zdCBpPWUua2V5VG9OYW1lTWFwW2FdO3QuaXNUcmFja2luZyhpKXx8dC50cmFjayhpLHIubGVuZ3RoKTtyLnB1c2goMjksMCwwLDAsMCk7YnJlYWs7Y2FzZSJhcnJheSI6Y2FzZSJkZWx0YSI6ci5wdXNoKC4uLnRoaXMuZW5jb2RlTnVtYmVyKGMpKTtmb3IobGV0IGU9MSx0PW4ubGVuZ3RoO2U8dDsrK2Upci5wdXNoKC4uLnRoaXMuZW5jb2RlTnVtYmVyKG5bZV0pKTticmVhaztkZWZhdWx0OnRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBkYXRhIHR5cGUgb2YgJHtvfWApfX1yLnB1c2goLi4uZS5vcGNvZGVzW2FdKX19cmV0dXJuIHJ9Y29tcGlsZVN0cmluZ0luZGV4KGUpe2NvbnN0IHQ9bmV3IENGRkluZGV4O2Zvcihjb25zdCByIG9mIGUpdC5hZGQoc3RyaW5nVG9CeXRlcyhyKSk7cmV0dXJuIHRoaXMuY29tcGlsZUluZGV4KHQpfWNvbXBpbGVDaGFyU3RyaW5ncyhlKXtjb25zdCB0PW5ldyBDRkZJbmRleDtmb3IobGV0IHI9MDtyPGUuY291bnQ7cisrKXtjb25zdCBhPWUuZ2V0KHIpOzAhPT1hLmxlbmd0aD90LmFkZChhKTp0LmFkZChuZXcgVWludDhBcnJheShbMTM5LDE0XSkpfXJldHVybiB0aGlzLmNvbXBpbGVJbmRleCh0KX1jb21waWxlQ2hhcnNldChlLHQscixhKXtsZXQgbjtjb25zdCBpPXQtMTtpZihhKXtjb25zdCBlPWktMTtuPW5ldyBVaW50OEFycmF5KFsyLDAsMSxlPj44JjI1NSwyNTUmZV0pfWVsc2V7bj1uZXcgVWludDhBcnJheSgxKzIqaSk7blswXT0wO2xldCB0PTA7Y29uc3QgYT1lLmNoYXJzZXQubGVuZ3RoO2xldCBzPSExO2ZvcihsZXQgaT0xO2k8bi5sZW5ndGg7aSs9Mil7bGV0IG89MDtpZih0PGEpe2NvbnN0IGE9ZS5jaGFyc2V0W3QrK107bz1yLmdldFNJRChhKTtpZigtMT09PW8pe289MDtpZighcyl7cz0hMDt3YXJuKGBDb3VsZG4ndCBmaW5kICR7YX0gaW4gQ0ZGIHN0cmluZ3NgKX19fW5baV09bz4+OCYyNTU7bltpKzFdPTI1NSZvfX1yZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShuKX1jb21waWxlRW5jb2RpbmcoZSl7cmV0dXJuIHRoaXMuY29tcGlsZVR5cGVkQXJyYXkoZS5yYXcpfWNvbXBpbGVGRFNlbGVjdChlKXtjb25zdCB0PWUuZm9ybWF0O2xldCByLGE7c3dpdGNoKHQpe2Nhc2UgMDpyPW5ldyBVaW50OEFycmF5KDErZS5mZFNlbGVjdC5sZW5ndGgpO3JbMF09dDtmb3IoYT0wO2E8ZS5mZFNlbGVjdC5sZW5ndGg7YSsrKXJbYSsxXT1lLmZkU2VsZWN0W2FdO2JyZWFrO2Nhc2UgMzpjb25zdCBuPTA7bGV0IGk9ZS5mZFNlbGVjdFswXTtjb25zdCBzPVt0LDAsMCxuPj44JjI1NSwyNTUmbixpXTtmb3IoYT0xO2E8ZS5mZFNlbGVjdC5sZW5ndGg7YSsrKXtjb25zdCB0PWUuZmRTZWxlY3RbYV07aWYodCE9PWkpe3MucHVzaChhPj44JjI1NSwyNTUmYSx0KTtpPXR9fWNvbnN0IG89KHMubGVuZ3RoLTMpLzM7c1sxXT1vPj44JjI1NTtzWzJdPTI1NSZvO3MucHVzaChhPj44JjI1NSwyNTUmYSk7cj1uZXcgVWludDhBcnJheShzKX1yZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShyKX1jb21waWxlVHlwZWRBcnJheShlKXtyZXR1cm4gQXJyYXkuZnJvbShlKX1jb21waWxlSW5kZXgoZSx0PVtdKXtjb25zdCByPWUub2JqZWN0cyxhPXIubGVuZ3RoO2lmKDA9PT1hKXJldHVyblswLDBdO2NvbnN0IG49W2E+PjgmMjU1LDI1NSZhXTtsZXQgaSxzLG89MTtmb3IoaT0wO2k8YTsrK2kpbys9cltpXS5sZW5ndGg7cz1vPDI1Nj8xOm88NjU1MzY/MjpvPDE2Nzc3MjE2PzM6NDtuLnB1c2gocyk7bGV0IGM9MTtmb3IoaT0wO2k8YSsxO2krKyl7MT09PXM/bi5wdXNoKDI1NSZjKToyPT09cz9uLnB1c2goYz4+OCYyNTUsMjU1JmMpOjM9PT1zP24ucHVzaChjPj4xNiYyNTUsYz4+OCYyNTUsMjU1JmMpOm4ucHVzaChjPj4+MjQmMjU1LGM+PjE2JjI1NSxjPj44JjI1NSwyNTUmYyk7cltpXSYmKGMrPXJbaV0ubGVuZ3RoKX1mb3IoaT0wO2k8YTtpKyspe3RbaV0mJnRbaV0ub2Zmc2V0KG4ubGVuZ3RoKTtuLnB1c2goLi4ucltpXSl9cmV0dXJuIG59fWNvbnN0IF9hPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlWyJUaW1lcy1Sb21hbiJdPSJUaW1lcy1Sb21hbiI7ZS5IZWx2ZXRpY2E9IkhlbHZldGljYSI7ZS5Db3VyaWVyPSJDb3VyaWVyIjtlLlN5bWJvbD0iU3ltYm9sIjtlWyJUaW1lcy1Cb2xkIl09IlRpbWVzLUJvbGQiO2VbIkhlbHZldGljYS1Cb2xkIl09IkhlbHZldGljYS1Cb2xkIjtlWyJDb3VyaWVyLUJvbGQiXT0iQ291cmllci1Cb2xkIjtlLlphcGZEaW5nYmF0cz0iWmFwZkRpbmdiYXRzIjtlWyJUaW1lcy1JdGFsaWMiXT0iVGltZXMtSXRhbGljIjtlWyJIZWx2ZXRpY2EtT2JsaXF1ZSJdPSJIZWx2ZXRpY2EtT2JsaXF1ZSI7ZVsiQ291cmllci1PYmxpcXVlIl09IkNvdXJpZXItT2JsaXF1ZSI7ZVsiVGltZXMtQm9sZEl0YWxpYyJdPSJUaW1lcy1Cb2xkSXRhbGljIjtlWyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXT0iSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjtlWyJDb3VyaWVyLUJvbGRPYmxpcXVlIl09IkNvdXJpZXItQm9sZE9ibGlxdWUiO2UuQXJpYWxOYXJyb3c9IkhlbHZldGljYSI7ZVsiQXJpYWxOYXJyb3ctQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiQXJpYWxOYXJyb3ctQm9sZEl0YWxpYyJdPSJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiO2VbIkFyaWFsTmFycm93LUl0YWxpYyJdPSJIZWx2ZXRpY2EtT2JsaXF1ZSI7ZS5BcmlhbEJsYWNrPSJIZWx2ZXRpY2EiO2VbIkFyaWFsQmxhY2stQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiQXJpYWxCbGFjay1Cb2xkSXRhbGljIl09IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7ZVsiQXJpYWxCbGFjay1JdGFsaWMiXT0iSGVsdmV0aWNhLU9ibGlxdWUiO2VbIkFyaWFsLUJsYWNrIl09IkhlbHZldGljYSI7ZVsiQXJpYWwtQmxhY2stQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiQXJpYWwtQmxhY2stQm9sZEl0YWxpYyJdPSJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiO2VbIkFyaWFsLUJsYWNrLUl0YWxpYyJdPSJIZWx2ZXRpY2EtT2JsaXF1ZSI7ZS5BcmlhbD0iSGVsdmV0aWNhIjtlWyJBcmlhbC1Cb2xkIl09IkhlbHZldGljYS1Cb2xkIjtlWyJBcmlhbC1Cb2xkSXRhbGljIl09IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7ZVsiQXJpYWwtSXRhbGljIl09IkhlbHZldGljYS1PYmxpcXVlIjtlLkFyaWFsTVQ9IkhlbHZldGljYSI7ZVsiQXJpYWwtQm9sZEl0YWxpY01UIl09IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7ZVsiQXJpYWwtQm9sZE1UIl09IkhlbHZldGljYS1Cb2xkIjtlWyJBcmlhbC1JdGFsaWNNVCJdPSJIZWx2ZXRpY2EtT2JsaXF1ZSI7ZVsiQXJpYWwtQm9sZEl0YWxpY01ULUJvbGRJdGFsaWMiXT0iSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjtlWyJBcmlhbC1Cb2xkTVQtQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiQXJpYWwtSXRhbGljTVQtSXRhbGljIl09IkhlbHZldGljYS1PYmxpcXVlIjtlLkFyaWFsVW5pY29kZU1TPSJIZWx2ZXRpY2EiO2VbIkFyaWFsVW5pY29kZU1TLUJvbGQiXT0iSGVsdmV0aWNhLUJvbGQiO2VbIkFyaWFsVW5pY29kZU1TLUJvbGRJdGFsaWMiXT0iSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjtlWyJBcmlhbFVuaWNvZGVNUy1JdGFsaWMiXT0iSGVsdmV0aWNhLU9ibGlxdWUiO2VbIkNvdXJpZXItQm9sZEl0YWxpYyJdPSJDb3VyaWVyLUJvbGRPYmxpcXVlIjtlWyJDb3VyaWVyLUl0YWxpYyJdPSJDb3VyaWVyLU9ibGlxdWUiO2UuQ291cmllck5ldz0iQ291cmllciI7ZVsiQ291cmllck5ldy1Cb2xkIl09IkNvdXJpZXItQm9sZCI7ZVsiQ291cmllck5ldy1Cb2xkSXRhbGljIl09IkNvdXJpZXItQm9sZE9ibGlxdWUiO2VbIkNvdXJpZXJOZXctSXRhbGljIl09IkNvdXJpZXItT2JsaXF1ZSI7ZVsiQ291cmllck5ld1BTLUJvbGRJdGFsaWNNVCJdPSJDb3VyaWVyLUJvbGRPYmxpcXVlIjtlWyJDb3VyaWVyTmV3UFMtQm9sZE1UIl09IkNvdXJpZXItQm9sZCI7ZVsiQ291cmllck5ld1BTLUl0YWxpY01UIl09IkNvdXJpZXItT2JsaXF1ZSI7ZS5Db3VyaWVyTmV3UFNNVD0iQ291cmllciI7ZVsiSGVsdmV0aWNhLUJvbGRJdGFsaWMiXT0iSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjtlWyJIZWx2ZXRpY2EtSXRhbGljIl09IkhlbHZldGljYS1PYmxpcXVlIjtlWyJIZWx2ZXRpY2FMVFN0ZC1Cb2xkIl09IkhlbHZldGljYS1Cb2xkIjtlWyJTeW1ib2wtQm9sZCJdPSJTeW1ib2wiO2VbIlN5bWJvbC1Cb2xkSXRhbGljIl09IlN5bWJvbCI7ZVsiU3ltYm9sLUl0YWxpYyJdPSJTeW1ib2wiO2UuVGltZXNOZXdSb21hbj0iVGltZXMtUm9tYW4iO2VbIlRpbWVzTmV3Um9tYW4tQm9sZCJdPSJUaW1lcy1Cb2xkIjtlWyJUaW1lc05ld1JvbWFuLUJvbGRJdGFsaWMiXT0iVGltZXMtQm9sZEl0YWxpYyI7ZVsiVGltZXNOZXdSb21hbi1JdGFsaWMiXT0iVGltZXMtSXRhbGljIjtlLlRpbWVzTmV3Um9tYW5QUz0iVGltZXMtUm9tYW4iO2VbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkIl09IlRpbWVzLUJvbGQiO2VbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkSXRhbGljIl09IlRpbWVzLUJvbGRJdGFsaWMiO2VbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkSXRhbGljTVQiXT0iVGltZXMtQm9sZEl0YWxpYyI7ZVsiVGltZXNOZXdSb21hblBTLUJvbGRNVCJdPSJUaW1lcy1Cb2xkIjtlWyJUaW1lc05ld1JvbWFuUFMtSXRhbGljIl09IlRpbWVzLUl0YWxpYyI7ZVsiVGltZXNOZXdSb21hblBTLUl0YWxpY01UIl09IlRpbWVzLUl0YWxpYyI7ZS5UaW1lc05ld1JvbWFuUFNNVD0iVGltZXMtUm9tYW4iO2VbIlRpbWVzTmV3Um9tYW5QU01ULUJvbGQiXT0iVGltZXMtQm9sZCI7ZVsiVGltZXNOZXdSb21hblBTTVQtQm9sZEl0YWxpYyJdPSJUaW1lcy1Cb2xkSXRhbGljIjtlWyJUaW1lc05ld1JvbWFuUFNNVC1JdGFsaWMiXT0iVGltZXMtSXRhbGljIn0pLExhPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlLkNvdXJpZXI9IkZveGl0Rml4ZWQucGZiIjtlWyJDb3VyaWVyLUJvbGQiXT0iRm94aXRGaXhlZEJvbGQucGZiIjtlWyJDb3VyaWVyLUJvbGRPYmxpcXVlIl09IkZveGl0Rml4ZWRCb2xkSXRhbGljLnBmYiI7ZVsiQ291cmllci1PYmxpcXVlIl09IkZveGl0Rml4ZWRJdGFsaWMucGZiIjtlLkhlbHZldGljYT0iTGliZXJhdGlvblNhbnMtUmVndWxhci50dGYiO2VbIkhlbHZldGljYS1Cb2xkIl09IkxpYmVyYXRpb25TYW5zLUJvbGQudHRmIjtlWyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXT0iTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYy50dGYiO2VbIkhlbHZldGljYS1PYmxpcXVlIl09IkxpYmVyYXRpb25TYW5zLUl0YWxpYy50dGYiO2VbIlRpbWVzLVJvbWFuIl09IkZveGl0U2VyaWYucGZiIjtlWyJUaW1lcy1Cb2xkIl09IkZveGl0U2VyaWZCb2xkLnBmYiI7ZVsiVGltZXMtQm9sZEl0YWxpYyJdPSJGb3hpdFNlcmlmQm9sZEl0YWxpYy5wZmIiO2VbIlRpbWVzLUl0YWxpYyJdPSJGb3hpdFNlcmlmSXRhbGljLnBmYiI7ZS5TeW1ib2w9IkZveGl0U3ltYm9sLnBmYiI7ZS5aYXBmRGluZ2JhdHM9IkZveGl0RGluZ2JhdHMucGZiIjtlWyJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIl09IkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIudHRmIjtlWyJMaWJlcmF0aW9uU2Fucy1Cb2xkIl09IkxpYmVyYXRpb25TYW5zLUJvbGQudHRmIjtlWyJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiXT0iTGliZXJhdGlvblNhbnMtSXRhbGljLnR0ZiI7ZVsiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyJdPSJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljLnR0ZiJ9KSxqYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5DYWxpYnJpPSJIZWx2ZXRpY2EiO2VbIkNhbGlicmktQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiQ2FsaWJyaS1Cb2xkSXRhbGljIl09IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7ZVsiQ2FsaWJyaS1JdGFsaWMiXT0iSGVsdmV0aWNhLU9ibGlxdWUiO2UuQ2VudHVyeUdvdGhpYz0iSGVsdmV0aWNhIjtlWyJDZW50dXJ5R290aGljLUJvbGQiXT0iSGVsdmV0aWNhLUJvbGQiO2VbIkNlbnR1cnlHb3RoaWMtQm9sZEl0YWxpYyJdPSJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiO2VbIkNlbnR1cnlHb3RoaWMtSXRhbGljIl09IkhlbHZldGljYS1PYmxpcXVlIjtlLkNvbWljU2Fuc01TPSJDb21pYyBTYW5zIE1TIjtlWyJDb21pY1NhbnNNUy1Cb2xkIl09IkNvbWljIFNhbnMgTVMtQm9sZCI7ZVsiQ29taWNTYW5zTVMtQm9sZEl0YWxpYyJdPSJDb21pYyBTYW5zIE1TLUJvbGRJdGFsaWMiO2VbIkNvbWljU2Fuc01TLUl0YWxpYyJdPSJDb21pYyBTYW5zIE1TLUl0YWxpYyI7ZS5HaWxsU2Fuc01UPSJIZWx2ZXRpY2EiO2VbIkdpbGxTYW5zTVQtQm9sZCJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiR2lsbFNhbnNNVC1Cb2xkSXRhbGljIl09IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7ZVsiR2lsbFNhbnNNVC1JdGFsaWMiXT0iSGVsdmV0aWNhLU9ibGlxdWUiO2UuSW1wYWN0PSJIZWx2ZXRpY2EiO2VbIkl0Y1N5bWJvbC1Cb2xkIl09IkhlbHZldGljYS1Cb2xkIjtlWyJJdGNTeW1ib2wtQm9sZEl0YWxpYyJdPSJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiO2VbIkl0Y1N5bWJvbC1Cb29rIl09IkhlbHZldGljYSI7ZVsiSXRjU3ltYm9sLUJvb2tJdGFsaWMiXT0iSGVsdmV0aWNhLU9ibGlxdWUiO2VbIkl0Y1N5bWJvbC1NZWRpdW0iXT0iSGVsdmV0aWNhIjtlWyJJdGNTeW1ib2wtTWVkaXVtSXRhbGljIl09IkhlbHZldGljYS1PYmxpcXVlIjtlLkx1Y2lkYUNvbnNvbGU9IkNvdXJpZXIiO2VbIkx1Y2lkYUNvbnNvbGUtQm9sZCJdPSJDb3VyaWVyLUJvbGQiO2VbIkx1Y2lkYUNvbnNvbGUtQm9sZEl0YWxpYyJdPSJDb3VyaWVyLUJvbGRPYmxpcXVlIjtlWyJMdWNpZGFDb25zb2xlLUl0YWxpYyJdPSJDb3VyaWVyLU9ibGlxdWUiO2VbIkx1Y2lkYVNhbnMtRGVtaSJdPSJIZWx2ZXRpY2EtQm9sZCI7ZVsiTVMtR290aGljIl09Ik1TIEdvdGhpYyI7ZVsiTVMtR290aGljLUJvbGQiXT0iTVMgR290aGljLUJvbGQiO2VbIk1TLUdvdGhpYy1Cb2xkSXRhbGljIl09Ik1TIEdvdGhpYy1Cb2xkSXRhbGljIjtlWyJNUy1Hb3RoaWMtSXRhbGljIl09Ik1TIEdvdGhpYy1JdGFsaWMiO2VbIk1TLU1pbmNobyJdPSJNUyBNaW5jaG8iO2VbIk1TLU1pbmNoby1Cb2xkIl09Ik1TIE1pbmNoby1Cb2xkIjtlWyJNUy1NaW5jaG8tQm9sZEl0YWxpYyJdPSJNUyBNaW5jaG8tQm9sZEl0YWxpYyI7ZVsiTVMtTWluY2hvLUl0YWxpYyJdPSJNUyBNaW5jaG8tSXRhbGljIjtlWyJNUy1QR290aGljIl09Ik1TIFBHb3RoaWMiO2VbIk1TLVBHb3RoaWMtQm9sZCJdPSJNUyBQR290aGljLUJvbGQiO2VbIk1TLVBHb3RoaWMtQm9sZEl0YWxpYyJdPSJNUyBQR290aGljLUJvbGRJdGFsaWMiO2VbIk1TLVBHb3RoaWMtSXRhbGljIl09Ik1TIFBHb3RoaWMtSXRhbGljIjtlWyJNUy1QTWluY2hvIl09Ik1TIFBNaW5jaG8iO2VbIk1TLVBNaW5jaG8tQm9sZCJdPSJNUyBQTWluY2hvLUJvbGQiO2VbIk1TLVBNaW5jaG8tQm9sZEl0YWxpYyJdPSJNUyBQTWluY2hvLUJvbGRJdGFsaWMiO2VbIk1TLVBNaW5jaG8tSXRhbGljIl09Ik1TIFBNaW5jaG8tSXRhbGljIjtlLk51cHRpYWxTY3JpcHQ9IlRpbWVzLUl0YWxpYyI7ZS5TZWdvZVVJU3ltYm9sPSJIZWx2ZXRpY2EifSksVWE9Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2VbIkFkb2JlIEplbnNvbiJdPSEwO2VbIkFkb2JlIFRleHQiXT0hMDtlLkFsYmVydHVzPSEwO2UuQWxkdXM9ITA7ZS5BbGV4YW5kcmlhPSEwO2UuQWxnZXJpYW49ITA7ZVsiQW1lcmljYW4gVHlwZXdyaXRlciJdPSEwO2UuQW50aXF1YT0hMDtlLkFwZXg9ITA7ZS5Bcm5vPSEwO2UuQXN0ZXI9ITA7ZS5BdXJvcmE9ITA7ZS5CYXNrZXJ2aWxsZT0hMDtlLkJlbGw9ITA7ZS5CZW1ibz0hMDtlWyJCZW1ibyBTY2hvb2xib29rIl09ITA7ZS5CZW5ndWlhdD0hMDtlWyJCZXJrZWxleSBPbGQgU3R5bGUiXT0hMDtlWyJCZXJuaGFyZCBNb2Rlcm4iXT0hMDtlWyJCZXJ0aG9sZCBDaXR5Il09ITA7ZS5Cb2Rvbmk9ITA7ZVsiQmF1ZXIgQm9kb25pIl09ITA7ZVsiQm9vayBBbnRpcXVhIl09ITA7ZS5Cb29rbWFuPSEwO2VbIkJvcmRlYXV4IFJvbWFuIl09ITA7ZVsiQ2FsaWZvcm5pYW4gRkIiXT0hMDtlLkNhbGlzdG89ITA7ZS5DYWx2ZXJ0PSEwO2UuQ2FwaXRhbHM9ITA7ZS5DYW1icmlhPSEwO2UuQ2FydGllcj0hMDtlLkNhc2xvbj0hMDtlLkNhdHVsbD0hMDtlLkNlbnRhdXI9ITA7ZVsiQ2VudHVyeSBPbGQgU3R5bGUiXT0hMDtlWyJDZW50dXJ5IFNjaG9vbGJvb2siXT0hMDtlLkNoYXBhcnJhbD0hMDtlWyJDaGFyaXMgU0lMIl09ITA7ZS5DaGVsdGVuaGFtPSEwO2VbIkNob2xsYSBTbGFiIl09ITA7ZS5DbGFyZW5kb249ITA7ZS5DbGVhcmZhY2U9ITA7ZS5Db2NoaW49ITA7ZS5Db2xvbm5hPSEwO2VbIkNvbXB1dGVyIE1vZGVybiJdPSEwO2VbIkNvbmNyZXRlIFJvbWFuIl09ITA7ZS5Db25zdGFudGlhPSEwO2VbIkNvb3BlciBCbGFjayJdPSEwO2UuQ29yb25hPSEwO2UuRWNvdHlwZT0hMDtlLkVneXB0aWVubmU9ITA7ZS5FbGVwaGFudD0hMDtlLkV4Y2Vsc2lvcj0hMDtlLkZhaXJmaWVsZD0hMDtlWyJGRiBTY2FsYSJdPSEwO2UuRm9sa2FyZD0hMDtlLkZvb3RsaWdodD0hMDtlLkZyZWVTZXJpZj0hMDtlWyJGcml6IFF1YWRyYXRhIl09ITA7ZS5HYXJhbW9uZD0hMDtlLkdlbnRpdW09ITA7ZS5HZW9yZ2lhPSEwO2UuR2xvdWNlc3Rlcj0hMDtlWyJHb3VkeSBPbGQgU3R5bGUiXT0hMDtlWyJHb3VkeSBTY2hvb2xib29rIl09ITA7ZVsiR291ZHkgUHJvIEZvbnQiXT0hMDtlLkdyYW5qb249ITA7ZVsiR3VhcmRpYW4gRWd5cHRpYW4iXT0hMDtlLkhlYXRoZXI9ITA7ZS5IZXJjdWxlcz0hMDtlWyJIaWdoIFRvd2VyIFRleHQiXT0hMDtlLkhpcm9zaGlnZT0hMDtlWyJIb2VmbGVyIFRleHQiXT0hMDtlWyJIdW1hbmEgU2VyaWYiXT0hMDtlLkltcHJpbnQ9ITA7ZVsiSW9uaWMgTm8uIDUiXT0hMDtlLkphbnNvbj0hMDtlLkpvYW5uYT0hMDtlLktvcmlubmE9ITA7ZS5MZXhpY29uPSEwO2UuTGliZXJhdGlvblNlcmlmPSEwO2VbIkxpYmVyYXRpb24gU2VyaWYiXT0hMDtlWyJMaW51eCBMaWJlcnRpbmUiXT0hMDtlLkxpdGVyYXR1cm5heWE9ITA7ZS5MdWNpZGE9ITA7ZVsiTHVjaWRhIEJyaWdodCJdPSEwO2UuTWVsaW9yPSEwO2UuTWVtcGhpcz0hMDtlLk1pbGxlcj0hMDtlLk1pbmlvbj0hMDtlLk1vZGVybj0hMDtlWyJNb25hIExpc2EiXT0hMDtlWyJNcnMgRWF2ZXMiXT0hMDtlWyJNUyBTZXJpZiJdPSEwO2VbIk11c2VvIFNsYWIiXT0hMDtlWyJOZXcgWW9yayJdPSEwO2VbIk5pbWJ1cyBSb21hbiJdPSEwO2VbIk5QUyBSYXdsaW5zb24gUm9hZHdheSJdPSEwO2UuTnVwdGlhbFNjcmlwdD0hMDtlLlBhbGF0aW5vPSEwO2UuUGVycGV0dWE9ITA7ZS5QbGFudGluPSEwO2VbIlBsYW50aW4gU2Nob29sYm9vayJdPSEwO2UuUGxheWJpbGw9ITA7ZVsiUG9vciBSaWNoYXJkIl09ITA7ZVsiUmF3bGluc29uIFJvYWR3YXkiXT0hMDtlLlJlbmF1bHQ9ITA7ZS5SZXF1aWVtPSEwO2UuUm9ja3dlbGw9ITA7ZS5Sb21hbj0hMDtlWyJSb3RpcyBTZXJpZiJdPSEwO2UuU2Fib249ITA7ZS5TY2FsYT0hMDtlLlNlYWd1bGw9ITA7ZS5TaXN0aW5hPSEwO2UuU291dmVuaXI9ITA7ZS5TVElYPSEwO2VbIlN0b25lIEluZm9ybWFsIl09ITA7ZVsiU3RvbmUgU2VyaWYiXT0hMDtlLlN5bGZhZW49ITA7ZS5UaW1lcz0hMDtlLlRyYWphbj0hMDtlWyJUcmluaXTDqSJdPSEwO2VbIlRydW1wIE1lZGlhZXZhbCJdPSEwO2UuVXRvcGlhPSEwO2VbIlZhbGUgVHlwZSJdPSEwO2VbIkJpdHN0cmVhbSBWZXJhIl09ITA7ZVsiVmVyYSBTZXJpZiJdPSEwO2UuVmVyc2FpbGxlcz0hMDtlLldhbnRlZD0hMDtlLldlaXNzPSEwO2VbIldpZGUgTGF0aW4iXT0hMDtlLldpbmRzb3I9ITA7ZS5YSVRTPSEwfSkscWE9Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2UuRGluZ2JhdHM9ITA7ZS5TeW1ib2w9ITA7ZS5aYXBmRGluZ2JhdHM9ITA7ZS5XaW5nZGluZ3M9ITA7ZVsiV2luZ2RpbmdzLUJvbGQiXT0hMDtlWyJXaW5nZGluZ3MtUmVndWxhciJdPSEwfSksWGE9Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2VbMl09MTA7ZVszXT0zMjtlWzRdPTMzO2VbNV09MzQ7ZVs2XT0zNTtlWzddPTM2O2VbOF09Mzc7ZVs5XT0zODtlWzEwXT0zOTtlWzExXT00MDtlWzEyXT00MTtlWzEzXT00MjtlWzE0XT00MztlWzE1XT00NDtlWzE2XT00NTtlWzE3XT00NjtlWzE4XT00NztlWzE5XT00ODtlWzIwXT00OTtlWzIxXT01MDtlWzIyXT01MTtlWzIzXT01MjtlWzI0XT01MztlWzI1XT01NDtlWzI2XT01NTtlWzI3XT01NjtlWzI4XT01NztlWzI5XT01ODtlWzMwXT04OTQ7ZVszMV09NjA7ZVszMl09NjE7ZVszM109NjI7ZVszNF09NjM7ZVszNV09NjQ7ZVszNl09NjU7ZVszN109NjY7ZVszOF09Njc7ZVszOV09Njg7ZVs0MF09Njk7ZVs0MV09NzA7ZVs0Ml09NzE7ZVs0M109NzI7ZVs0NF09NzM7ZVs0NV09NzQ7ZVs0Nl09NzU7ZVs0N109NzY7ZVs0OF09Nzc7ZVs0OV09Nzg7ZVs1MF09Nzk7ZVs1MV09ODA7ZVs1Ml09ODE7ZVs1M109ODI7ZVs1NF09ODM7ZVs1NV09ODQ7ZVs1Nl09ODU7ZVs1N109ODY7ZVs1OF09ODc7ZVs1OV09ODg7ZVs2MF09ODk7ZVs2MV09OTA7ZVs2Ml09OTE7ZVs2M109OTI7ZVs2NF09OTM7ZVs2NV09OTQ7ZVs2Nl09OTU7ZVs2N109OTY7ZVs2OF09OTc7ZVs2OV09OTg7ZVs3MF09OTk7ZVs3MV09MTAwO2VbNzJdPTEwMTtlWzczXT0xMDI7ZVs3NF09MTAzO2VbNzVdPTEwNDtlWzc2XT0xMDU7ZVs3N109MTA2O2VbNzhdPTEwNztlWzc5XT0xMDg7ZVs4MF09MTA5O2VbODFdPTExMDtlWzgyXT0xMTE7ZVs4M109MTEyO2VbODRdPTExMztlWzg1XT0xMTQ7ZVs4Nl09MTE1O2VbODddPTExNjtlWzg4XT0xMTc7ZVs4OV09MTE4O2VbOTBdPTExOTtlWzkxXT0xMjA7ZVs5Ml09MTIxO2VbOTNdPTEyMjtlWzk0XT0xMjM7ZVs5NV09MTI0O2VbOTZdPTEyNTtlWzk3XT0xMjY7ZVs5OF09MTk2O2VbOTldPTE5NztlWzEwMF09MTk5O2VbMTAxXT0yMDE7ZVsxMDJdPTIwOTtlWzEwM109MjE0O2VbMTA0XT0yMjA7ZVsxMDVdPTIyNTtlWzEwNl09MjI0O2VbMTA3XT0yMjY7ZVsxMDhdPTIyODtlWzEwOV09MjI3O2VbMTEwXT0yMjk7ZVsxMTFdPTIzMTtlWzExMl09MjMzO2VbMTEzXT0yMzI7ZVsxMTRdPTIzNDtlWzExNV09MjM1O2VbMTE2XT0yMzc7ZVsxMTddPTIzNjtlWzExOF09MjM4O2VbMTE5XT0yMzk7ZVsxMjBdPTI0MTtlWzEyMV09MjQzO2VbMTIyXT0yNDI7ZVsxMjNdPTI0NDtlWzEyNF09MjQ2O2VbMTI1XT0yNDU7ZVsxMjZdPTI1MDtlWzEyN109MjQ5O2VbMTI4XT0yNTE7ZVsxMjldPTI1MjtlWzEzMF09ODIyNDtlWzEzMV09MTc2O2VbMTMyXT0xNjI7ZVsxMzNdPTE2MztlWzEzNF09MTY3O2VbMTM1XT04MjI2O2VbMTM2XT0xODI7ZVsxMzddPTIyMztlWzEzOF09MTc0O2VbMTM5XT0xNjk7ZVsxNDBdPTg0ODI7ZVsxNDFdPTE4MDtlWzE0Ml09MTY4O2VbMTQzXT04ODAwO2VbMTQ0XT0xOTg7ZVsxNDVdPTIxNjtlWzE0Nl09ODczNDtlWzE0N109MTc3O2VbMTQ4XT04ODA0O2VbMTQ5XT04ODA1O2VbMTUwXT0xNjU7ZVsxNTFdPTE4MTtlWzE1Ml09ODcwNjtlWzE1M109ODcyMTtlWzE1NF09ODcxOTtlWzE1Nl09ODc0NztlWzE1N109MTcwO2VbMTU4XT0xODY7ZVsxNTldPTg0ODY7ZVsxNjBdPTIzMDtlWzE2MV09MjQ4O2VbMTYyXT0xOTE7ZVsxNjNdPTE2MTtlWzE2NF09MTcyO2VbMTY1XT04NzMwO2VbMTY2XT00MDI7ZVsxNjddPTg3NzY7ZVsxNjhdPTg3MTA7ZVsxNjldPTE3MTtlWzE3MF09MTg3O2VbMTcxXT04MjMwO2VbMTc5XT04MjIwO2VbMTgwXT04MjIxO2VbMTgxXT04MjE2O2VbMTgyXT04MjE3O2VbMjAwXT0xOTM7ZVsyMDNdPTIwNTtlWzIwN109MjExO2VbMjEwXT0yMTg7ZVsyMjNdPTcxMTtlWzIyNF09MzIxO2VbMjI1XT0zMjI7ZVsyMjZdPTM1MjtlWzIyN109MzUzO2VbMjI4XT0zODE7ZVsyMjldPTM4MjtlWzIzM109MjIxO2VbMjM0XT0yNTM7ZVsyNTJdPTI2MztlWzI1M109MjY4O2VbMjU0XT0yNjk7ZVsyNThdPTI1ODtlWzI2MF09MjYwO2VbMjYxXT0yNjE7ZVsyNjVdPTI4MDtlWzI2Nl09MjgxO2VbMjY3XT0yODI7ZVsyNjhdPTI4MztlWzI2OV09MzEzO2VbMjc1XT0zMjM7ZVsyNzZdPTMyNDtlWzI3OF09MzI4O2VbMjgzXT0zNDQ7ZVsyODRdPTM0NTtlWzI4NV09MzQ2O2VbMjg2XT0zNDc7ZVsyOTJdPTM2NztlWzI5NV09Mzc3O2VbMjk2XT0zNzg7ZVsyOThdPTM4MDtlWzMwNV09OTYzO2VbMzA2XT05NjQ7ZVszMDddPTk2NjtlWzMwOF09ODIxNTtlWzMwOV09ODI1MjtlWzMxMF09ODMxOTtlWzMxMV09ODM1OTtlWzMxMl09ODU5MjtlWzMxM109ODU5MztlWzMzN109OTU1MjtlWzQ5M109MTAzOTtlWzQ5NF09MTA0MDtlWzU3MF09MTA0MDtlWzU3MV09MTA0MTtlWzU3Ml09MTA0MjtlWzU3M109MTA0MztlWzU3NF09MTA0NDtlWzU3NV09MTA0NTtlWzU3Nl09MTA0NjtlWzU3N109MTA0NztlWzU3OF09MTA0ODtlWzU3OV09MTA0OTtlWzU4MF09MTA1MDtlWzU4MV09MTA1MTtlWzU4Ml09MTA1MjtlWzU4M109MTA1MztlWzU4NF09MTA1NDtlWzU4NV09MTA1NTtlWzU4Nl09MTA1NjtlWzU4N109MTA1NztlWzU4OF09MTA1ODtlWzU4OV09MTA1OTtlWzU5MF09MTA2MDtlWzU5MV09MTA2MTtlWzU5Ml09MTA2MjtlWzU5M109MTA2MztlWzU5NF09MTA2NDtlWzU5NV09MTA2NTtlWzU5Nl09MTA2NjtlWzU5N109MTA2NztlWzU5OF09MTA2ODtlWzU5OV09MTA2OTtlWzYwMF09MTA3MDtlWzY3Ml09MTQ4ODtlWzY3M109MTQ4OTtlWzY3NF09MTQ5MDtlWzY3NV09MTQ5MTtlWzY3Nl09MTQ5MjtlWzY3N109MTQ5MztlWzY3OF09MTQ5NDtlWzY3OV09MTQ5NTtlWzY4MF09MTQ5NjtlWzY4MV09MTQ5NztlWzY4Ml09MTQ5ODtlWzY4M109MTQ5OTtlWzY4NF09MTUwMDtlWzY4NV09MTUwMTtlWzY4Nl09MTUwMjtlWzY4N109MTUwMztlWzY4OF09MTUwNDtlWzY4OV09MTUwNTtlWzY5MF09MTUwNjtlWzY5MV09MTUwNztlWzY5Ml09MTUwODtlWzY5M109MTUwOTtlWzY5NF09MTUxMDtlWzY5NV09MTUxMTtlWzY5Nl09MTUxMjtlWzY5N109MTUxMztlWzY5OF09MTUxNDtlWzcwNV09MTUyNDtlWzcwNl09ODM2MjtlWzcxMF09NjQyODg7ZVs3MTFdPTY0Mjk4O2VbNzU5XT0xNjE3O2VbNzYxXT0xNzc2O2VbNzYzXT0xNzc4O2VbNzc1XT0xNjUyO2VbNzc3XT0xNzY0O2VbNzc4XT0xNzgwO2VbNzc5XT0xNzgxO2VbNzgwXT0xNzgyO2VbNzgyXT03NzE7ZVs3ODNdPTY0NzI2O2VbNzg2XT04MzYzO2VbNzg4XT04NTMyO2VbNzkwXT03Njg7ZVs3OTFdPTc2OTtlWzc5Ml09NzY4O2VbNzk1XT04MDM7ZVs3OTddPTY0MzM2O2VbNzk4XT02NDMzNztlWzc5OV09NjQzNDI7ZVs4MDBdPTY0MzQzO2VbODAxXT02NDM0NDtlWzgwMl09NjQzNDU7ZVs4MDNdPTY0MzYyO2VbODA0XT02NDM2MztlWzgwNV09NjQzNjQ7ZVsyNDI0XT03ODIxO2VbMjQyNV09NzgyMjtlWzI0MjZdPTc4MjM7ZVsyNDI3XT03ODI0O2VbMjQyOF09NzgyNTtlWzI0MjldPTc4MjY7ZVsyNDMwXT03ODI3O2VbMjQzM109NzY4MjtlWzI2NzhdPTgwNDU7ZVsyNjc5XT04MDQ2O2VbMjgzMF09MTU1MjtlWzI4MzhdPTY4NjtlWzI4NDBdPTc1MTtlWzI4NDJdPTc1MztlWzI4NDNdPTc1NDtlWzI4NDRdPTc1NTtlWzI4NDZdPTc1NztlWzI4NTZdPTc2NztlWzI4NTddPTg0ODtlWzI4NThdPTg0OTtlWzI4NjJdPTg1MztlWzI4NjNdPTg1NDtlWzI4NjRdPTg1NTtlWzI4NjVdPTg2MTtlWzI4NjZdPTg2MjtlWzI5MDZdPTc0NjA7ZVsyOTA4XT03NDYyO2VbMjkwOV09NzQ2MztlWzI5MTBdPTc0NjQ7ZVsyOTEyXT03NDY2O2VbMjkxM109NzQ2NztlWzI5MTRdPTc0Njg7ZVsyOTE2XT03NDcwO2VbMjkxN109NzQ3MTtlWzI5MThdPTc0NzI7ZVsyOTIwXT03NDc0O2VbMjkyMV09NzQ3NTtlWzI5MjJdPTc0NzY7ZVsyOTI0XT03NDc4O2VbMjkyNV09NzQ3OTtlWzI5MjZdPTc0ODA7ZVsyOTI4XT03NDgyO2VbMjkyOV09NzQ4MztlWzI5MzBdPTc0ODQ7ZVsyOTMyXT03NDg2O2VbMjkzM109NzQ4NztlWzI5MzRdPTc0ODg7ZVsyOTM2XT03NDkwO2VbMjkzN109NzQ5MTtlWzI5MzhdPTc0OTI7ZVsyOTQwXT03NDk0O2VbMjk0MV09NzQ5NTtlWzI5NDJdPTc0OTY7ZVsyOTQ0XT03NDk4O2VbMjk0Nl09NzUwMDtlWzI5NDhdPTc1MDI7ZVsyOTUwXT03NTA0O2VbMjk1MV09NzUwNTtlWzI5NTJdPTc1MDY7ZVsyOTU0XT03NTA4O2VbMjk1NV09NzUwOTtlWzI5NTZdPTc1MTA7ZVsyOTU4XT03NTEyO2VbMjk1OV09NzUxMztlWzI5NjBdPTc1MTQ7ZVsyOTYyXT03NTE2O2VbMjk2M109NzUxNztlWzI5NjRdPTc1MTg7ZVsyOTY2XT03NTIwO2VbMjk2N109NzUyMTtlWzI5NjhdPTc1MjI7ZVsyOTcwXT03NTI0O2VbMjk3MV09NzUyNTtlWzI5NzJdPTc1MjY7ZVsyOTc0XT03NTI4O2VbMjk3NV09NzUyOTtlWzI5NzZdPTc1MzA7ZVsyOTc4XT0xNTM3O2VbMjk3OV09MTUzODtlWzI5ODBdPTE1Mzk7ZVsyOTgyXT0xNTQ5O2VbMjk4M109MTU1MTtlWzI5ODRdPTE1NTI7ZVsyOTg2XT0xNTU0O2VbMjk4N109MTU1NTtlWzI5ODhdPTE1NTY7ZVsyOTkwXT0xNjIzO2VbMjk5MV09MTYyNDtlWzI5OTVdPTE3NzU7ZVsyOTk5XT0xNzkxO2VbMzAwMl09NjQyOTA7ZVszMDAzXT02NDI5MTtlWzMwMDRdPTY0MjkyO2VbMzAwNl09NjQyOTQ7ZVszMDA3XT02NDI5NTtlWzMwMDhdPTY0Mjk2O2VbMzAxMV09MTkwMDtlWzMwMTRdPTgyMjM7ZVszMDE1XT04MjQ0O2VbMzAxN109NzUzMjtlWzMwMThdPTc1MzM7ZVszMDE5XT03NTM0O2VbMzA3NV09NzU5MDtlWzMwNzZdPTc1OTE7ZVszMDc5XT03NTk0O2VbMzA4MF09NzU5NTtlWzMwODNdPTc1OTg7ZVszMDg0XT03NTk5O2VbMzA4N109NzYwMjtlWzMwODhdPTc2MDM7ZVszMDkxXT03NjA2O2VbMzA5Ml09NzYwNztlWzMwOTVdPTc2MTA7ZVszMDk2XT03NjExO2VbMzA5OV09NzYxNDtlWzMxMDBdPTc2MTU7ZVszMTAzXT03NjE4O2VbMzEwNF09NzYxOTtlWzMxMDddPTgzMzc7ZVszMTA4XT04MzM4O2VbMzExNl09MTg4NDtlWzMxMTldPTE4ODU7ZVszMTIwXT0xODg1O2VbMzEyM109MTg4NjtlWzMxMjRdPTE4ODY7ZVszMTI3XT0xODg3O2VbMzEyOF09MTg4NztlWzMxMzFdPTE4ODg7ZVszMTMyXT0xODg4O2VbMzEzNV09MTg4OTtlWzMxMzZdPTE4ODk7ZVszMTM5XT0xODkwO2VbMzE0MF09MTg5MDtlWzMxNDNdPTE4OTE7ZVszMTQ0XT0xODkxO2VbMzE0N109MTg5MjtlWzMxNDhdPTE4OTI7ZVszMTUzXT01ODA7ZVszMTU0XT01ODE7ZVszMTU3XT01ODQ7ZVszMTU4XT01ODU7ZVszMTYxXT01ODg7ZVszMTYyXT01ODk7ZVszMTY1XT04OTE7ZVszMTY2XT04OTI7ZVszMTY5XT0xMjc0O2VbMzE3MF09MTI3NTtlWzMxNzNdPTEyNzg7ZVszMTc0XT0xMjc5O2VbMzE4MV09NzYyMjtlWzMxODJdPTc2MjM7ZVszMjgyXT0xMTc5OTtlWzMzMTZdPTU3ODtlWzMzNzldPTQyNzg1O2VbMzM5M109MTE1OTtlWzM0MTZdPTgzNzd9KSxIYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZVsyMjddPTMyMjtlWzI2NF09MjYxO2VbMjkxXT0zNDZ9KSxXYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZVsxXT0zMjtlWzRdPTY1O2VbNV09MTkyO2VbNl09MTkzO2VbOV09MTk2O2VbMTddPTY2O2VbMThdPTY3O2VbMjFdPTI2ODtlWzI0XT02ODtlWzI4XT02OTtlWzI5XT0yMDA7ZVszMF09MjAxO2VbMzJdPTI4MjtlWzM4XT03MDtlWzM5XT03MTtlWzQ0XT03MjtlWzQ3XT03MztlWzQ4XT0yMDQ7ZVs0OV09MjA1O2VbNThdPTc0O2VbNjBdPTc1O2VbNjJdPTc2O2VbNjhdPTc3O2VbNjldPTc4O2VbNzVdPTc5O2VbNzZdPTIxMDtlWzgwXT0yMTQ7ZVs4N109ODA7ZVs4OV09ODE7ZVs5MF09ODI7ZVs5Ml09MzQ0O2VbOTRdPTgzO2VbOTddPTM1MjtlWzEwMF09ODQ7ZVsxMDRdPTg1O2VbMTA5XT0yMjA7ZVsxMTVdPTg2O2VbMTE2XT04NztlWzEyMV09ODg7ZVsxMjJdPTg5O2VbMTI0XT0yMjE7ZVsxMjddPTkwO2VbMTI5XT0zODE7ZVsyNThdPTk3O2VbMjU5XT0yMjQ7ZVsyNjBdPTIyNTtlWzI2M109MjI4O2VbMjY4XT0yNjE7ZVsyNzFdPTk4O2VbMjcyXT05OTtlWzI3M109MjYzO2VbMjc1XT0yNjk7ZVsyODJdPTEwMDtlWzI4Nl09MTAxO2VbMjg3XT0yMzI7ZVsyODhdPTIzMztlWzI5MF09MjgzO2VbMjk1XT0yODE7ZVsyOTZdPTEwMjtlWzMzNl09MTAzO2VbMzQ2XT0xMDQ7ZVszNDldPTEwNTtlWzM1MF09MjM2O2VbMzUxXT0yMzc7ZVszNjFdPTEwNjtlWzM2NF09MTA3O2VbMzY3XT0xMDg7ZVszNzFdPTMyMjtlWzM3M109MTA5O2VbMzc0XT0xMTA7ZVszODFdPTExMTtlWzM4Ml09MjQyO2VbMzgzXT0yNDM7ZVszODZdPTI0NjtlWzM5M109MTEyO2VbMzk1XT0xMTM7ZVszOTZdPTExNDtlWzM5OF09MzQ1O2VbNDAwXT0xMTU7ZVs0MDFdPTM0NztlWzQwM109MzUzO2VbNDEwXT0xMTY7ZVs0MzddPTExNztlWzQ0Ml09MjUyO2VbNDQ4XT0xMTg7ZVs0NDldPTExOTtlWzQ1NF09MTIwO2VbNDU1XT0xMjE7ZVs0NTddPTI1MztlWzQ2MF09MTIyO2VbNDYyXT0zODI7ZVs0NjNdPTM4MDtlWzg1M109NDQ7ZVs4NTVdPTU4O2VbODU2XT00NjtlWzg3Nl09NDc7ZVs4NzhdPTQ1O2VbODgyXT00NTtlWzg5NF09NDA7ZVs4OTVdPTQxO2VbODk2XT05MTtlWzg5N109OTM7ZVs5MjNdPTY0O2VbOTQwXT0xNjM7ZVsxMDA0XT00ODtlWzEwMDVdPTQ5O2VbMTAwNl09NTA7ZVsxMDA3XT01MTtlWzEwMDhdPTUyO2VbMTAwOV09NTM7ZVsxMDEwXT01NDtlWzEwMTFdPTU1O2VbMTAxMl09NTY7ZVsxMDEzXT01NztlWzEwODFdPTM3O2VbMTA4NV09NDM7ZVsxMDg2XT00NX0pO2Z1bmN0aW9uIGdldFN0YW5kYXJkRm9udE5hbWUoZSl7Y29uc3QgdD1ub3JtYWxpemVGb250TmFtZShlKTtyZXR1cm4gX2EoKVt0XX1mdW5jdGlvbiBpc0tub3duRm9udE5hbWUoZSl7Y29uc3QgdD1ub3JtYWxpemVGb250TmFtZShlKTtyZXR1cm4hIShfYSgpW3RdfHxqYSgpW3RdfHxVYSgpW3RdfHxxYSgpW3RdKX1jbGFzcyBUb1VuaWNvZGVNYXB7Y29uc3RydWN0b3IoZT1bXSl7dGhpcy5fbWFwPWV9Z2V0IGxlbmd0aCgpe3JldHVybiB0aGlzLl9tYXAubGVuZ3RofWZvckVhY2goZSl7Zm9yKGNvbnN0IHQgaW4gdGhpcy5fbWFwKWUodCx0aGlzLl9tYXBbdF0uY29kZVBvaW50QXQoMCkpfWhhcyhlKXtyZXR1cm4gdm9pZCAwIT09dGhpcy5fbWFwW2VdfWdldChlKXtyZXR1cm4gdGhpcy5fbWFwW2VdfWNoYXJDb2RlT2YoZSl7Y29uc3QgdD10aGlzLl9tYXA7aWYodC5sZW5ndGg8PTY1NTM2KXJldHVybiB0LmluZGV4T2YoZSk7Zm9yKGNvbnN0IHIgaW4gdClpZih0W3JdPT09ZSlyZXR1cm4gMHxyO3JldHVybi0xfWFtZW5kKGUpe2Zvcihjb25zdCB0IGluIGUpdGhpcy5fbWFwW3RdPWVbdF19fWNsYXNzIElkZW50aXR5VG9Vbmljb2RlTWFwe2NvbnN0cnVjdG9yKGUsdCl7dGhpcy5maXJzdENoYXI9ZTt0aGlzLmxhc3RDaGFyPXR9Z2V0IGxlbmd0aCgpe3JldHVybiB0aGlzLmxhc3RDaGFyKzEtdGhpcy5maXJzdENoYXJ9Zm9yRWFjaChlKXtmb3IobGV0IHQ9dGhpcy5maXJzdENoYXIscj10aGlzLmxhc3RDaGFyO3Q8PXI7dCsrKWUodCx0KX1oYXMoZSl7cmV0dXJuIHRoaXMuZmlyc3RDaGFyPD1lJiZlPD10aGlzLmxhc3RDaGFyfWdldChlKXtpZih0aGlzLmZpcnN0Q2hhcjw9ZSYmZTw9dGhpcy5sYXN0Q2hhcilyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShlKX1jaGFyQ29kZU9mKGUpe3JldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGUpJiZlPj10aGlzLmZpcnN0Q2hhciYmZTw9dGhpcy5sYXN0Q2hhcj9lOi0xfWFtZW5kKGUpe3VucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYW1lbmQoKSIpfX1jbGFzcyBDRkZGb250e2NvbnN0cnVjdG9yKGUsdCl7dGhpcy5wcm9wZXJ0aWVzPXQ7Y29uc3Qgcj1uZXcgQ0ZGUGFyc2VyKGUsdCx4YSk7dGhpcy5jZmY9ci5wYXJzZSgpO3RoaXMuY2ZmLmR1cGxpY2F0ZUZpcnN0R2x5cGgoKTtjb25zdCBhPW5ldyBDRkZDb21waWxlcih0aGlzLmNmZik7dGhpcy5zZWFjcz10aGlzLmNmZi5zZWFjczt0cnl7dGhpcy5kYXRhPWEuY29tcGlsZSgpfWNhdGNoe3dhcm4oIkZhaWxlZCB0byBjb21waWxlIGZvbnQgIit0LmxvYWRlZE5hbWUpO3RoaXMuZGF0YT1lfXRoaXMuX2NyZWF0ZUJ1aWx0SW5FbmNvZGluZygpfWdldCBudW1HbHlwaHMoKXtyZXR1cm4gdGhpcy5jZmYuY2hhclN0cmluZ3MuY291bnR9Z2V0Q2hhcnNldCgpe3JldHVybiB0aGlzLmNmZi5jaGFyc2V0LmNoYXJzZXR9Z2V0R2x5cGhNYXBwaW5nKCl7Y29uc3QgZT10aGlzLmNmZix0PXRoaXMucHJvcGVydGllcyx7Y2lkVG9HaWRNYXA6cixjTWFwOmF9PXQsbj1lLmNoYXJzZXQuY2hhcnNldDtsZXQgaSxzO2lmKHQuY29tcG9zaXRlKXtsZXQgdCxvO2lmKHI/Lmxlbmd0aD4wKXt0PU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGxldCBlPTAsYT1yLmxlbmd0aDtlPGE7ZSsrKXtjb25zdCBhPXJbZV07dm9pZCAwIT09YSYmKHRbYV09ZSl9fWk9T2JqZWN0LmNyZWF0ZShudWxsKTtpZihlLmlzQ0lERm9udClmb3Iocz0wO3M8bi5sZW5ndGg7cysrKXtjb25zdCBlPW5bc107bz1hLmNoYXJDb2RlT2YoZSk7dm9pZCAwIT09dD8uW29dJiYobz10W29dKTtpW29dPXN9ZWxzZSBmb3Iocz0wO3M8ZS5jaGFyU3RyaW5ncy5jb3VudDtzKyspe289YS5jaGFyQ29kZU9mKHMpO2lbb109c31yZXR1cm4gaX1sZXQgbz1lLmVuY29kaW5nP2UuZW5jb2RpbmcuZW5jb2Rpbmc6bnVsbDt0LmlzSW50ZXJuYWxGb250JiYobz10LmRlZmF1bHRFbmNvZGluZyk7aT10eXBlMUZvbnRHbHlwaE1hcHBpbmcodCxvLG4pO3JldHVybiBpfWhhc0dseXBoSWQoZSl7cmV0dXJuIHRoaXMuY2ZmLmhhc0dseXBoSWQoZSl9X2NyZWF0ZUJ1aWx0SW5FbmNvZGluZygpe2NvbnN0e2NoYXJzZXQ6ZSxlbmNvZGluZzp0fT10aGlzLmNmZjtpZighZXx8IXQpcmV0dXJuO2NvbnN0IHI9ZS5jaGFyc2V0LGE9dC5lbmNvZGluZyxuPVtdO2Zvcihjb25zdCBlIGluIGEpe2NvbnN0IHQ9YVtlXTtpZih0Pj0wKXtjb25zdCBhPXJbdF07YSYmKG5bZV09YSl9fW4ubGVuZ3RoPjAmJih0aGlzLnByb3BlcnRpZXMuYnVpbHRJbkVuY29kaW5nPW4pfX1mdW5jdGlvbiBnZXRGbG9hdDIxNChlLHQpe3JldHVybiByZWFkSW50MTYoZSx0KS8xNjM4NH1mdW5jdGlvbiBnZXRTdWJyb3V0aW5lQmlhcyhlKXtjb25zdCB0PWUubGVuZ3RoO2xldCByPTMyNzY4O3Q8MTI0MD9yPTEwNzp0PDMzOTAwJiYocj0xMTMxKTtyZXR1cm4gcn1mdW5jdGlvbiBwYXJzZUNtYXAoZSx0LHIpe2NvbnN0IGE9MT09PXJlYWRVaW50MTYoZSx0KzIpP3JlYWRVaW50MzIoZSx0KzgpOnJlYWRVaW50MzIoZSx0KzE2KSxuPXJlYWRVaW50MTYoZSx0K2EpO2xldCBpLHMsbztpZig0PT09bil7cmVhZFVpbnQxNihlLHQrYSsyKTtjb25zdCByPXJlYWRVaW50MTYoZSx0K2ErNik+PjE7cz10K2ErMTQ7aT1bXTtmb3Iobz0wO288cjtvKysscys9MilpW29dPXtlbmQ6cmVhZFVpbnQxNihlLHMpfTtzKz0yO2ZvcihvPTA7bzxyO28rKyxzKz0yKWlbb10uc3RhcnQ9cmVhZFVpbnQxNihlLHMpO2ZvcihvPTA7bzxyO28rKyxzKz0yKWlbb10uaWREZWx0YT1yZWFkVWludDE2KGUscyk7Zm9yKG89MDtvPHI7bysrLHMrPTIpe2xldCB0PXJlYWRVaW50MTYoZSxzKTtpZigwIT09dCl7aVtvXS5pZHM9W107Zm9yKGxldCByPTAsYT1pW29dLmVuZC1pW29dLnN0YXJ0KzE7cjxhO3IrKyl7aVtvXS5pZHNbcl09cmVhZFVpbnQxNihlLHMrdCk7dCs9Mn19fXJldHVybiBpfWlmKDEyPT09bil7Y29uc3Qgcj1yZWFkVWludDMyKGUsdCthKzEyKTtzPXQrYSsxNjtpPVtdO2ZvcihvPTA7bzxyO28rKyl7dD1yZWFkVWludDMyKGUscyk7aS5wdXNoKHtzdGFydDp0LGVuZDpyZWFkVWludDMyKGUscys0KSxpZERlbHRhOnJlYWRVaW50MzIoZSxzKzgpLXR9KTtzKz0xMn1yZXR1cm4gaX10aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHVuc3VwcG9ydGVkIGNtYXA6ICR7bn1gKX1mdW5jdGlvbiBwYXJzZUNmZihlLHQscixhKXtjb25zdCBuPW5ldyBDRkZQYXJzZXIobmV3IFN0cmVhbShlLHQsci10KSx7fSxhKS5wYXJzZSgpO3JldHVybntnbHlwaHM6bi5jaGFyU3RyaW5ncy5vYmplY3RzLHN1YnJzOm4udG9wRGljdC5wcml2YXRlRGljdD8uc3VicnNJbmRleD8ub2JqZWN0cyxnc3VicnM6bi5nbG9iYWxTdWJySW5kZXg/Lm9iamVjdHMsaXNDRkZDSURGb250Om4uaXNDSURGb250LGZkU2VsZWN0Om4uZmRTZWxlY3QsZmRBcnJheTpuLmZkQXJyYXl9fWZ1bmN0aW9uIGxvb2t1cENtYXAoZSx0KXtjb25zdCByPXQuY29kZVBvaW50QXQoMCk7bGV0IGE9MCxuPTAsaT1lLmxlbmd0aC0xO2Zvcig7bjxpOyl7Y29uc3QgdD1uK2krMT4+MTtyPGVbdF0uc3RhcnQ/aT10LTE6bj10fWVbbl0uc3RhcnQ8PXImJnI8PWVbbl0uZW5kJiYoYT1lW25dLmlkRGVsdGErKGVbbl0uaWRzP2Vbbl0uaWRzW3ItZVtuXS5zdGFydF06cikmNjU1MzUpO3JldHVybntjaGFyQ29kZTpyLGdseXBoSWQ6YX19ZnVuY3Rpb24gY29tcGlsZUdseWYoZSx0LHIpe2Z1bmN0aW9uIG1vdmVUbyhlLHIpe3MmJnQuYWRkKCJMIixzKTtzPVtlLHJdO3QuYWRkKCJNIixbZSxyXSl9ZnVuY3Rpb24gbGluZVRvKGUscil7dC5hZGQoIkwiLFtlLHJdKX1mdW5jdGlvbiBxdWFkcmF0aWNDdXJ2ZVRvKGUscixhLG4pe3QuYWRkKCJRIixbZSxyLGEsbl0pfWxldCBhPTA7Y29uc3Qgbj1yZWFkSW50MTYoZSxhKTtsZXQgaSxzPW51bGwsbz0wLGM9MDthKz0xMDtpZihuPDApZG97aT1yZWFkVWludDE2KGUsYSk7Y29uc3Qgbj1yZWFkVWludDE2KGUsYSsyKTthKz00O2xldCBzLGw7aWYoMSZpKXtpZigyJmkpe3M9cmVhZEludDE2KGUsYSk7bD1yZWFkSW50MTYoZSxhKzIpfWVsc2V7cz1yZWFkVWludDE2KGUsYSk7bD1yZWFkVWludDE2KGUsYSsyKX1hKz00fWVsc2UgaWYoMiZpKXtzPXJlYWRJbnQ4KGUsYSsrKTtsPXJlYWRJbnQ4KGUsYSsrKX1lbHNle3M9ZVthKytdO2w9ZVthKytdfWlmKDImaSl7bz1zO2M9bH1lbHNle289MDtjPTB9bGV0IGg9MSx1PTEsZD0wLGY9MDtpZig4Jmkpe2g9dT1nZXRGbG9hdDIxNChlLGEpO2ErPTJ9ZWxzZSBpZig2NCZpKXtoPWdldEZsb2F0MjE0KGUsYSk7dT1nZXRGbG9hdDIxNChlLGErMik7YSs9NH1lbHNlIGlmKDEyOCZpKXtoPWdldEZsb2F0MjE0KGUsYSk7ZD1nZXRGbG9hdDIxNChlLGErMik7Zj1nZXRGbG9hdDIxNChlLGErNCk7dT1nZXRGbG9hdDIxNChlLGErNik7YSs9OH1jb25zdCBnPXIuZ2x5cGhzW25dO2lmKGcpe3Quc2F2ZSgpO3QudHJhbnNmb3JtKFtoLGQsZix1LG8sY10pO2NvbXBpbGVHbHlmKGcsdCxyKTt0LnJlc3RvcmUoKX19d2hpbGUoMzImaSk7ZWxzZXtjb25zdCB0PVtdO2xldCByLHM7Zm9yKHI9MDtyPG47cisrKXt0LnB1c2gocmVhZFVpbnQxNihlLGEpKTthKz0yfWErPTIrcmVhZFVpbnQxNihlLGEpO2NvbnN0IGw9dC5hdCgtMSkrMSxoPVtdO2Zvcig7aC5sZW5ndGg8bDspe2k9ZVthKytdO2xldCB0PTE7OCZpJiYodCs9ZVthKytdKTtmb3IoO3QtLSA+MDspaC5wdXNoKHtmbGFnczppfSl9Zm9yKHI9MDtyPGw7cisrKXtzd2l0Y2goMTgmaFtyXS5mbGFncyl7Y2FzZSAwOm8rPXJlYWRJbnQxNihlLGEpO2ErPTI7YnJlYWs7Y2FzZSAyOm8tPWVbYSsrXTticmVhaztjYXNlIDE4Om8rPWVbYSsrXX1oW3JdLng9b31mb3Iocj0wO3I8bDtyKyspe3N3aXRjaCgzNiZoW3JdLmZsYWdzKXtjYXNlIDA6Yys9cmVhZEludDE2KGUsYSk7YSs9MjticmVhaztjYXNlIDQ6Yy09ZVthKytdO2JyZWFrO2Nhc2UgMzY6Yys9ZVthKytdfWhbcl0ueT1jfWxldCB1PTA7Zm9yKGE9MDthPG47YSsrKXtjb25zdCBlPXRbYV0sbj1oLnNsaWNlKHUsZSsxKTtpZigxJm5bMF0uZmxhZ3Mpbi5wdXNoKG5bMF0pO2Vsc2UgaWYoMSZuLmF0KC0xKS5mbGFncyluLnVuc2hpZnQobi5hdCgtMSkpO2Vsc2V7Y29uc3QgZT17ZmxhZ3M6MSx4OihuWzBdLngrbi5hdCgtMSkueCkvMix5OihuWzBdLnkrbi5hdCgtMSkueSkvMn07bi51bnNoaWZ0KGUpO24ucHVzaChlKX1tb3ZlVG8oblswXS54LG5bMF0ueSk7Zm9yKHI9MSxzPW4ubGVuZ3RoO3I8cztyKyspaWYoMSZuW3JdLmZsYWdzKWxpbmVUbyhuW3JdLngsbltyXS55KTtlbHNlIGlmKDEmbltyKzFdLmZsYWdzKXtxdWFkcmF0aWNDdXJ2ZVRvKG5bcl0ueCxuW3JdLnksbltyKzFdLngsbltyKzFdLnkpO3IrK31lbHNlIHF1YWRyYXRpY0N1cnZlVG8obltyXS54LG5bcl0ueSwobltyXS54K25bcisxXS54KS8yLChuW3JdLnkrbltyKzFdLnkpLzIpO3U9ZSsxfX19ZnVuY3Rpb24gY29tcGlsZUNoYXJTdHJpbmcoZSx0LHIsYSl7ZnVuY3Rpb24gbW92ZVRvKGUscil7YyYmdC5hZGQoIkwiLGMpO2M9W2Uscl07dC5hZGQoIk0iLFtlLHJdKX1mdW5jdGlvbiBsaW5lVG8oZSxyKXt0LmFkZCgiTCIsW2Uscl0pfWZ1bmN0aW9uIGJlemllckN1cnZlVG8oZSxyLGEsbixpLHMpe3QuYWRkKCJDIixbZSxyLGEsbixpLHNdKX1jb25zdCBuPVtdO2xldCBpPTAscz0wLG89MCxjPW51bGw7IWZ1bmN0aW9uIHBhcnNlKGUpe2xldCBjPTA7Zm9yKDtjPGUubGVuZ3RoOyl7bGV0IGwsaCx1LGQsZixnLHAsbSxiLHk9ITEsdz1lW2MrK107c3dpdGNoKHcpe2Nhc2UgMTpjYXNlIDM6Y2FzZSAxODpjYXNlIDIzOm8rPW4ubGVuZ3RoPj4xO3k9ITA7YnJlYWs7Y2FzZSA0OnMrPW4ucG9wKCk7bW92ZVRvKGkscyk7eT0hMDticmVhaztjYXNlIDU6Zm9yKDtuLmxlbmd0aD4wOyl7aSs9bi5zaGlmdCgpO3MrPW4uc2hpZnQoKTtsaW5lVG8oaSxzKX1icmVhaztjYXNlIDY6Zm9yKDtuLmxlbmd0aD4wOyl7aSs9bi5zaGlmdCgpO2xpbmVUbyhpLHMpO2lmKDA9PT1uLmxlbmd0aClicmVhaztzKz1uLnNoaWZ0KCk7bGluZVRvKGkscyl9YnJlYWs7Y2FzZSA3OmZvcig7bi5sZW5ndGg+MDspe3MrPW4uc2hpZnQoKTtsaW5lVG8oaSxzKTtpZigwPT09bi5sZW5ndGgpYnJlYWs7aSs9bi5zaGlmdCgpO2xpbmVUbyhpLHMpfWJyZWFrO2Nhc2UgODpmb3IoO24ubGVuZ3RoPjA7KXtsPWkrbi5zaGlmdCgpO3U9cytuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKX1icmVhaztjYXNlIDEwOm09bi5wb3AoKTtiPW51bGw7aWYoci5pc0NGRkNJREZvbnQpe2NvbnN0IGU9ci5mZFNlbGVjdC5nZXRGREluZGV4KGEpO2lmKGU+PTAmJmU8ci5mZEFycmF5Lmxlbmd0aCl7Y29uc3QgdD1yLmZkQXJyYXlbZV07bGV0IGE7dC5wcml2YXRlRGljdD8uc3VicnNJbmRleCYmKGE9dC5wcml2YXRlRGljdC5zdWJyc0luZGV4Lm9iamVjdHMpO2lmKGEpe20rPWdldFN1YnJvdXRpbmVCaWFzKGEpO2I9YVttXX19ZWxzZSB3YXJuKCJJbnZhbGlkIGZkIGluZGV4IGZvciBnbHlwaCBpbmRleC4iKX1lbHNlIGI9ci5zdWJyc1ttK3Iuc3VicnNCaWFzXTtiJiZwYXJzZShiKTticmVhaztjYXNlIDExOnJldHVybjtjYXNlIDEyOnc9ZVtjKytdO3N3aXRjaCh3KXtjYXNlIDM0Omw9aStuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtmPXMrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7YmV6aWVyQ3VydmVUbyhsLHMsaCxmLGksZik7bD1pK24uc2hpZnQoKTtoPWwrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7YmV6aWVyQ3VydmVUbyhsLGYsaCxzLGkscyk7YnJlYWs7Y2FzZSAzNTpsPWkrbi5zaGlmdCgpO3U9cytuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKTtsPWkrbi5zaGlmdCgpO3U9cytuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKTtuLnBvcCgpO2JyZWFrO2Nhc2UgMzY6bD1pK24uc2hpZnQoKTtmPXMrbi5zaGlmdCgpO2g9bCtuLnNoaWZ0KCk7Zz1mK24uc2hpZnQoKTtpPWgrbi5zaGlmdCgpO2JlemllckN1cnZlVG8obCxmLGgsZyxpLGcpO2w9aStuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtwPWcrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7YmV6aWVyQ3VydmVUbyhsLGcsaCxwLGkscyk7YnJlYWs7Y2FzZSAzNzpjb25zdCBlPWksdD1zO2w9aStuLnNoaWZ0KCk7dT1zK24uc2hpZnQoKTtoPWwrbi5zaGlmdCgpO2Q9dStuLnNoaWZ0KCk7aT1oK24uc2hpZnQoKTtzPWQrbi5zaGlmdCgpO2JlemllckN1cnZlVG8obCx1LGgsZCxpLHMpO2w9aStuLnNoaWZ0KCk7dT1zK24uc2hpZnQoKTtoPWwrbi5zaGlmdCgpO2Q9dStuLnNoaWZ0KCk7aT1oO3M9ZDtNYXRoLmFicyhpLWUpPk1hdGguYWJzKHMtdCk/aSs9bi5zaGlmdCgpOnMrPW4uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKTticmVhaztkZWZhdWx0OnRocm93IG5ldyBGb3JtYXRFcnJvcihgdW5rbm93biBvcGVyYXRvcjogMTIgJHt3fWApfWJyZWFrO2Nhc2UgMTQ6aWYobi5sZW5ndGg+PTQpe2NvbnN0IGU9bi5wb3AoKSxhPW4ucG9wKCk7cz1uLnBvcCgpO2k9bi5wb3AoKTt0LnNhdmUoKTt0LnRyYW5zbGF0ZShpLHMpO2xldCBvPWxvb2t1cENtYXAoci5jbWFwLFN0cmluZy5mcm9tQ2hhckNvZGUoci5nbHlwaE5hbWVNYXBbaGFbZV1dKSk7Y29tcGlsZUNoYXJTdHJpbmcoci5nbHlwaHNbby5nbHlwaElkXSx0LHIsby5nbHlwaElkKTt0LnJlc3RvcmUoKTtvPWxvb2t1cENtYXAoci5jbWFwLFN0cmluZy5mcm9tQ2hhckNvZGUoci5nbHlwaE5hbWVNYXBbaGFbYV1dKSk7Y29tcGlsZUNoYXJTdHJpbmcoci5nbHlwaHNbby5nbHlwaElkXSx0LHIsby5nbHlwaElkKX1yZXR1cm47Y2FzZSAxOTpjYXNlIDIwOm8rPW4ubGVuZ3RoPj4xO2MrPW8rNz4+Mzt5PSEwO2JyZWFrO2Nhc2UgMjE6cys9bi5wb3AoKTtpKz1uLnBvcCgpO21vdmVUbyhpLHMpO3k9ITA7YnJlYWs7Y2FzZSAyMjppKz1uLnBvcCgpO21vdmVUbyhpLHMpO3k9ITA7YnJlYWs7Y2FzZSAyNDpmb3IoO24ubGVuZ3RoPjI7KXtsPWkrbi5zaGlmdCgpO3U9cytuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKX1pKz1uLnNoaWZ0KCk7cys9bi5zaGlmdCgpO2xpbmVUbyhpLHMpO2JyZWFrO2Nhc2UgMjU6Zm9yKDtuLmxlbmd0aD42Oyl7aSs9bi5zaGlmdCgpO3MrPW4uc2hpZnQoKTtsaW5lVG8oaSxzKX1sPWkrbi5zaGlmdCgpO3U9cytuLnNoaWZ0KCk7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO2k9aCtuLnNoaWZ0KCk7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKTticmVhaztjYXNlIDI2Om4ubGVuZ3RoJTImJihpKz1uLnNoaWZ0KCkpO2Zvcig7bi5sZW5ndGg+MDspe2w9aTt1PXMrbi5zaGlmdCgpO2g9bCtuLnNoaWZ0KCk7ZD11K24uc2hpZnQoKTtpPWg7cz1kK24uc2hpZnQoKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKX1icmVhaztjYXNlIDI3Om4ubGVuZ3RoJTImJihzKz1uLnNoaWZ0KCkpO2Zvcig7bi5sZW5ndGg+MDspe2w9aStuLnNoaWZ0KCk7dT1zO2g9bCtuLnNoaWZ0KCk7ZD11K24uc2hpZnQoKTtpPWgrbi5zaGlmdCgpO3M9ZDtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKX1icmVhaztjYXNlIDI4Om4ucHVzaChyZWFkSW50MTYoZSxjKSk7Yys9MjticmVhaztjYXNlIDI5Om09bi5wb3AoKStyLmdzdWJyc0JpYXM7Yj1yLmdzdWJyc1ttXTtiJiZwYXJzZShiKTticmVhaztjYXNlIDMwOmZvcig7bi5sZW5ndGg+MDspe2w9aTt1PXMrbi5zaGlmdCgpO2g9bCtuLnNoaWZ0KCk7ZD11K24uc2hpZnQoKTtpPWgrbi5zaGlmdCgpO3M9ZCsoMT09PW4ubGVuZ3RoP24uc2hpZnQoKTowKTtiZXppZXJDdXJ2ZVRvKGwsdSxoLGQsaSxzKTtpZigwPT09bi5sZW5ndGgpYnJlYWs7bD1pK24uc2hpZnQoKTt1PXM7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO3M9ZCtuLnNoaWZ0KCk7aT1oKygxPT09bi5sZW5ndGg/bi5zaGlmdCgpOjApO2JlemllckN1cnZlVG8obCx1LGgsZCxpLHMpfWJyZWFrO2Nhc2UgMzE6Zm9yKDtuLmxlbmd0aD4wOyl7bD1pK24uc2hpZnQoKTt1PXM7aD1sK24uc2hpZnQoKTtkPXUrbi5zaGlmdCgpO3M9ZCtuLnNoaWZ0KCk7aT1oKygxPT09bi5sZW5ndGg/bi5zaGlmdCgpOjApO2JlemllckN1cnZlVG8obCx1LGgsZCxpLHMpO2lmKDA9PT1uLmxlbmd0aClicmVhaztsPWk7dT1zK24uc2hpZnQoKTtoPWwrbi5zaGlmdCgpO2Q9dStuLnNoaWZ0KCk7aT1oK24uc2hpZnQoKTtzPWQrKDE9PT1uLmxlbmd0aD9uLnNoaWZ0KCk6MCk7YmV6aWVyQ3VydmVUbyhsLHUsaCxkLGkscyl9YnJlYWs7ZGVmYXVsdDppZih3PDMyKXRocm93IG5ldyBGb3JtYXRFcnJvcihgdW5rbm93biBvcGVyYXRvcjogJHt3fWApO2lmKHc8MjQ3KW4ucHVzaCh3LTEzOSk7ZWxzZSBpZih3PDI1MSluLnB1c2goMjU2Kih3LTI0NykrZVtjKytdKzEwOCk7ZWxzZSBpZih3PDI1NSluLnB1c2goMjU2Ki0ody0yNTEpLWVbYysrXS0xMDgpO2Vsc2V7bi5wdXNoKChlW2NdPDwyNHxlW2MrMV08PDE2fGVbYysyXTw8OHxlW2MrM10pLzY1NTM2KTtjKz00fX15JiYobi5sZW5ndGg9MCl9fShlKX1jbGFzcyBDb21tYW5kc3tjbWRzPVtdO3RyYW5zZm9ybVN0YWNrPVtdO2N1cnJlbnRUcmFuc2Zvcm09WzEsMCwwLDEsMCwwXTthZGQoZSx0KXtpZih0KXtjb25zdHtjdXJyZW50VHJhbnNmb3JtOnJ9PXRoaXM7Zm9yKGxldCBlPTAsYT10Lmxlbmd0aDtlPGE7ZSs9MilVdGlsLmFwcGx5VHJhbnNmb3JtKHQscixlKTt0aGlzLmNtZHMucHVzaChgJHtlfSR7dC5qb2luKCIgIil9YCl9ZWxzZSB0aGlzLmNtZHMucHVzaChlKX10cmFuc2Zvcm0oZSl7dGhpcy5jdXJyZW50VHJhbnNmb3JtPVV0aWwudHJhbnNmb3JtKHRoaXMuY3VycmVudFRyYW5zZm9ybSxlKX10cmFuc2xhdGUoZSx0KXt0aGlzLnRyYW5zZm9ybShbMSwwLDAsMSxlLHRdKX1zYXZlKCl7dGhpcy50cmFuc2Zvcm1TdGFjay5wdXNoKHRoaXMuY3VycmVudFRyYW5zZm9ybS5zbGljZSgpKX1yZXN0b3JlKCl7dGhpcy5jdXJyZW50VHJhbnNmb3JtPXRoaXMudHJhbnNmb3JtU3RhY2sucG9wKCl8fFsxLDAsMCwxLDAsMF19Z2V0U1ZHKCl7cmV0dXJuIHRoaXMuY21kcy5qb2luKCIiKX19Y2xhc3MgQ29tcGlsZWRGb250e2NvbnN0cnVjdG9yKGUpe3RoaXMuZm9udE1hdHJpeD1lO3RoaXMuY29tcGlsZWRHbHlwaHM9T2JqZWN0LmNyZWF0ZShudWxsKTt0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWQ9T2JqZWN0LmNyZWF0ZShudWxsKX1nZXRQYXRoSnMoZSl7Y29uc3R7Y2hhckNvZGU6dCxnbHlwaElkOnJ9PWxvb2t1cENtYXAodGhpcy5jbWFwLGUpO2xldCBhLG49dGhpcy5jb21waWxlZEdseXBoc1tyXTtpZih2b2lkIDA9PT1uKXt0cnl7bj10aGlzLmNvbXBpbGVHbHlwaCh0aGlzLmdseXBoc1tyXSxyKX1jYXRjaChlKXtuPSIiO2E9ZX10aGlzLmNvbXBpbGVkR2x5cGhzW3JdPW59dGhpcy5jb21waWxlZENoYXJDb2RlVG9HbHlwaElkW3RdPz89cjtpZihhKXRocm93IGE7cmV0dXJuIG59Y29tcGlsZUdseXBoKGUsdCl7aWYoIWU/Lmxlbmd0aHx8MTQ9PT1lWzBdKXJldHVybiIiO2xldCByPXRoaXMuZm9udE1hdHJpeDtpZih0aGlzLmlzQ0ZGQ0lERm9udCl7Y29uc3QgZT10aGlzLmZkU2VsZWN0LmdldEZESW5kZXgodCk7aWYoZT49MCYmZTx0aGlzLmZkQXJyYXkubGVuZ3RoKXtyPXRoaXMuZmRBcnJheVtlXS5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKXx8YX1lbHNlIHdhcm4oIkludmFsaWQgZmQgaW5kZXggZm9yIGdseXBoIGluZGV4LiIpfWFzc2VydChpc051bWJlckFycmF5KHIsNiksIkV4cGVjdGVkIGEgdmFsaWQgZm9udE1hdHJpeC4iKTtjb25zdCBuPW5ldyBDb21tYW5kcztuLnRyYW5zZm9ybShyLnNsaWNlKCkpO3RoaXMuY29tcGlsZUdseXBoSW1wbChlLG4sdCk7bi5hZGQoIloiKTtyZXR1cm4gbi5nZXRTVkcoKX1jb21waWxlR2x5cGhJbXBsKCl7dW5yZWFjaGFibGUoIkNoaWxkcmVuIGNsYXNzZXMgc2hvdWxkIGltcGxlbWVudCB0aGlzLiIpfWhhc0J1aWx0UGF0aChlKXtjb25zdHtjaGFyQ29kZTp0LGdseXBoSWQ6cn09bG9va3VwQ21hcCh0aGlzLmNtYXAsZSk7cmV0dXJuIHZvaWQgMCE9PXRoaXMuY29tcGlsZWRHbHlwaHNbcl0mJnZvaWQgMCE9PXRoaXMuY29tcGlsZWRDaGFyQ29kZVRvR2x5cGhJZFt0XX19Y2xhc3MgVHJ1ZVR5cGVDb21waWxlZCBleHRlbmRzIENvbXBpbGVkRm9udHtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIocnx8WzQ4OGUtNiwwLDAsNDg4ZS02LDAsMF0pO3RoaXMuZ2x5cGhzPWU7dGhpcy5jbWFwPXR9Y29tcGlsZUdseXBoSW1wbChlLHQpe2NvbXBpbGVHbHlmKGUsdCx0aGlzKX19Y2xhc3MgVHlwZTJDb21waWxlZCBleHRlbmRzIENvbXBpbGVkRm9udHtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIocnx8Wy4wMDEsMCwwLC4wMDEsMCwwXSk7dGhpcy5nbHlwaHM9ZS5nbHlwaHM7dGhpcy5nc3VicnM9ZS5nc3VicnN8fFtdO3RoaXMuc3VicnM9ZS5zdWJyc3x8W107dGhpcy5jbWFwPXQ7dGhpcy5nbHlwaE5hbWVNYXA9Z2EoKTt0aGlzLmdzdWJyc0JpYXM9Z2V0U3Vicm91dGluZUJpYXModGhpcy5nc3VicnMpO3RoaXMuc3VicnNCaWFzPWdldFN1YnJvdXRpbmVCaWFzKHRoaXMuc3VicnMpO3RoaXMuaXNDRkZDSURGb250PWUuaXNDRkZDSURGb250O3RoaXMuZmRTZWxlY3Q9ZS5mZFNlbGVjdDt0aGlzLmZkQXJyYXk9ZS5mZEFycmF5fWNvbXBpbGVHbHlwaEltcGwoZSx0LHIpe2NvbXBpbGVDaGFyU3RyaW5nKGUsdCx0aGlzLHIpfX1jbGFzcyBGb250UmVuZGVyZXJGYWN0b3J5e3N0YXRpYyBjcmVhdGUoZSx0KXtjb25zdCByPW5ldyBVaW50OEFycmF5KGUuZGF0YSk7bGV0IGEsbixpLHMsbyxjO2NvbnN0IGw9cmVhZFVpbnQxNihyLDQpO2ZvcihsZXQgZT0wLGg9MTI7ZTxsO2UrKyxoKz0xNil7Y29uc3QgZT1ieXRlc1RvU3RyaW5nKHIuc3ViYXJyYXkoaCxoKzQpKSxsPXJlYWRVaW50MzIocixoKzgpLHU9cmVhZFVpbnQzMihyLGgrMTIpO3N3aXRjaChlKXtjYXNlImNtYXAiOmE9cGFyc2VDbWFwKHIsbCk7YnJlYWs7Y2FzZSJnbHlmIjpuPXIuc3ViYXJyYXkobCxsK3UpO2JyZWFrO2Nhc2UibG9jYSI6aT1yLnN1YmFycmF5KGwsbCt1KTticmVhaztjYXNlImhlYWQiOmM9cmVhZFVpbnQxNihyLGwrMTgpO289cmVhZFVpbnQxNihyLGwrNTApO2JyZWFrO2Nhc2UiQ0ZGICI6cz1wYXJzZUNmZihyLGwsbCt1LHQpfX1pZihuKXtjb25zdCB0PWM/WzEvYywwLDAsMS9jLDAsMF06ZS5mb250TWF0cml4O3JldHVybiBuZXcgVHJ1ZVR5cGVDb21waWxlZChmdW5jdGlvbiBwYXJzZUdseWZUYWJsZShlLHQscil7bGV0IGEsbjtpZihyKXthPTQ7bj1yZWFkVWludDMyfWVsc2V7YT0yO249KGUsdCk9PjIqcmVhZFVpbnQxNihlLHQpfWNvbnN0IGk9W107bGV0IHM9bih0LDApO2ZvcihsZXQgcj1hO3I8dC5sZW5ndGg7cis9YSl7Y29uc3QgYT1uKHQscik7aS5wdXNoKGUuc3ViYXJyYXkocyxhKSk7cz1hfXJldHVybiBpfShuLGksbyksYSx0KX1yZXR1cm4gbmV3IFR5cGUyQ29tcGlsZWQocyxhLGUuZm9udE1hdHJpeCl9fWNvbnN0IHphPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlLkNvdXJpZXI9NjAwO2VbIkNvdXJpZXItQm9sZCJdPTYwMDtlWyJDb3VyaWVyLUJvbGRPYmxpcXVlIl09NjAwO2VbIkNvdXJpZXItT2JsaXF1ZSJdPTYwMDtlLkhlbHZldGljYT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNzg7ZS5leGNsYW09Mjc4O2UucXVvdGVkYmw9MzU1O2UubnVtYmVyc2lnbj01NTY7ZS5kb2xsYXI9NTU2O2UucGVyY2VudD04ODk7ZS5hbXBlcnNhbmQ9NjY3O2UucXVvdGVyaWdodD0yMjI7ZS5wYXJlbmxlZnQ9MzMzO2UucGFyZW5yaWdodD0zMzM7ZS5hc3Rlcmlzaz0zODk7ZS5wbHVzPTU4NDtlLmNvbW1hPTI3ODtlLmh5cGhlbj0zMzM7ZS5wZXJpb2Q9Mjc4O2Uuc2xhc2g9Mjc4O2UuemVybz01NTY7ZS5vbmU9NTU2O2UudHdvPTU1NjtlLnRocmVlPTU1NjtlLmZvdXI9NTU2O2UuZml2ZT01NTY7ZS5zaXg9NTU2O2Uuc2V2ZW49NTU2O2UuZWlnaHQ9NTU2O2UubmluZT01NTY7ZS5jb2xvbj0yNzg7ZS5zZW1pY29sb249Mjc4O2UubGVzcz01ODQ7ZS5lcXVhbD01ODQ7ZS5ncmVhdGVyPTU4NDtlLnF1ZXN0aW9uPTU1NjtlLmF0PTEwMTU7ZS5BPTY2NztlLkI9NjY3O2UuQz03MjI7ZS5EPTcyMjtlLkU9NjY3O2UuRj02MTE7ZS5HPTc3ODtlLkg9NzIyO2UuST0yNzg7ZS5KPTUwMDtlLks9NjY3O2UuTD01NTY7ZS5NPTgzMztlLk49NzIyO2UuTz03Nzg7ZS5QPTY2NztlLlE9Nzc4O2UuUj03MjI7ZS5TPTY2NztlLlQ9NjExO2UuVT03MjI7ZS5WPTY2NztlLlc9OTQ0O2UuWD02Njc7ZS5ZPTY2NztlLlo9NjExO2UuYnJhY2tldGxlZnQ9Mjc4O2UuYmFja3NsYXNoPTI3ODtlLmJyYWNrZXRyaWdodD0yNzg7ZS5hc2NpaWNpcmN1bT00Njk7ZS51bmRlcnNjb3JlPTU1NjtlLnF1b3RlbGVmdD0yMjI7ZS5hPTU1NjtlLmI9NTU2O2UuYz01MDA7ZS5kPTU1NjtlLmU9NTU2O2UuZj0yNzg7ZS5nPTU1NjtlLmg9NTU2O2UuaT0yMjI7ZS5qPTIyMjtlLms9NTAwO2UubD0yMjI7ZS5tPTgzMztlLm49NTU2O2Uubz01NTY7ZS5wPTU1NjtlLnE9NTU2O2Uucj0zMzM7ZS5zPTUwMDtlLnQ9Mjc4O2UudT01NTY7ZS52PTUwMDtlLnc9NzIyO2UueD01MDA7ZS55PTUwMDtlLno9NTAwO2UuYnJhY2VsZWZ0PTMzNDtlLmJhcj0yNjA7ZS5icmFjZXJpZ2h0PTMzNDtlLmFzY2lpdGlsZGU9NTg0O2UuZXhjbGFtZG93bj0zMzM7ZS5jZW50PTU1NjtlLnN0ZXJsaW5nPTU1NjtlLmZyYWN0aW9uPTE2NztlLnllbj01NTY7ZS5mbG9yaW49NTU2O2Uuc2VjdGlvbj01NTY7ZS5jdXJyZW5jeT01NTY7ZS5xdW90ZXNpbmdsZT0xOTE7ZS5xdW90ZWRibGxlZnQ9MzMzO2UuZ3VpbGxlbW90bGVmdD01NTY7ZS5ndWlsc2luZ2xsZWZ0PTMzMztlLmd1aWxzaW5nbHJpZ2h0PTMzMztlLmZpPTUwMDtlLmZsPTUwMDtlLmVuZGFzaD01NTY7ZS5kYWdnZXI9NTU2O2UuZGFnZ2VyZGJsPTU1NjtlLnBlcmlvZGNlbnRlcmVkPTI3ODtlLnBhcmFncmFwaD01Mzc7ZS5idWxsZXQ9MzUwO2UucXVvdGVzaW5nbGJhc2U9MjIyO2UucXVvdGVkYmxiYXNlPTMzMztlLnF1b3RlZGJscmlnaHQ9MzMzO2UuZ3VpbGxlbW90cmlnaHQ9NTU2O2UuZWxsaXBzaXM9MWUzO2UucGVydGhvdXNhbmQ9MWUzO2UucXVlc3Rpb25kb3duPTYxMTtlLmdyYXZlPTMzMztlLmFjdXRlPTMzMztlLmNpcmN1bWZsZXg9MzMzO2UudGlsZGU9MzMzO2UubWFjcm9uPTMzMztlLmJyZXZlPTMzMztlLmRvdGFjY2VudD0zMzM7ZS5kaWVyZXNpcz0zMzM7ZS5yaW5nPTMzMztlLmNlZGlsbGE9MzMzO2UuaHVuZ2FydW1sYXV0PTMzMztlLm9nb25laz0zMzM7ZS5jYXJvbj0zMzM7ZS5lbWRhc2g9MWUzO2UuQUU9MWUzO2Uub3JkZmVtaW5pbmU9MzcwO2UuTHNsYXNoPTU1NjtlLk9zbGFzaD03Nzg7ZS5PRT0xZTM7ZS5vcmRtYXNjdWxpbmU9MzY1O2UuYWU9ODg5O2UuZG90bGVzc2k9Mjc4O2UubHNsYXNoPTIyMjtlLm9zbGFzaD02MTE7ZS5vZT05NDQ7ZS5nZXJtYW5kYmxzPTYxMTtlLklkaWVyZXNpcz0yNzg7ZS5lYWN1dGU9NTU2O2UuYWJyZXZlPTU1NjtlLnVodW5nYXJ1bWxhdXQ9NTU2O2UuZWNhcm9uPTU1NjtlLllkaWVyZXNpcz02Njc7ZS5kaXZpZGU9NTg0O2UuWWFjdXRlPTY2NztlLkFjaXJjdW1mbGV4PTY2NztlLmFhY3V0ZT01NTY7ZS5VY2lyY3VtZmxleD03MjI7ZS55YWN1dGU9NTAwO2Uuc2NvbW1hYWNjZW50PTUwMDtlLmVjaXJjdW1mbGV4PTU1NjtlLlVyaW5nPTcyMjtlLlVkaWVyZXNpcz03MjI7ZS5hb2dvbmVrPTU1NjtlLlVhY3V0ZT03MjI7ZS51b2dvbmVrPTU1NjtlLkVkaWVyZXNpcz02Njc7ZS5EY3JvYXQ9NzIyO2UuY29tbWFhY2NlbnQ9MjUwO2UuY29weXJpZ2h0PTczNztlLkVtYWNyb249NjY3O2UuY2Nhcm9uPTUwMDtlLmFyaW5nPTU1NjtlLk5jb21tYWFjY2VudD03MjI7ZS5sYWN1dGU9MjIyO2UuYWdyYXZlPTU1NjtlLlRjb21tYWFjY2VudD02MTE7ZS5DYWN1dGU9NzIyO2UuYXRpbGRlPTU1NjtlLkVkb3RhY2NlbnQ9NjY3O2Uuc2Nhcm9uPTUwMDtlLnNjZWRpbGxhPTUwMDtlLmlhY3V0ZT0yNzg7ZS5sb3plbmdlPTQ3MTtlLlJjYXJvbj03MjI7ZS5HY29tbWFhY2NlbnQ9Nzc4O2UudWNpcmN1bWZsZXg9NTU2O2UuYWNpcmN1bWZsZXg9NTU2O2UuQW1hY3Jvbj02Njc7ZS5yY2Fyb249MzMzO2UuY2NlZGlsbGE9NTAwO2UuWmRvdGFjY2VudD02MTE7ZS5UaG9ybj02Njc7ZS5PbWFjcm9uPTc3ODtlLlJhY3V0ZT03MjI7ZS5TYWN1dGU9NjY3O2UuZGNhcm9uPTY0MztlLlVtYWNyb249NzIyO2UudXJpbmc9NTU2O2UudGhyZWVzdXBlcmlvcj0zMzM7ZS5PZ3JhdmU9Nzc4O2UuQWdyYXZlPTY2NztlLkFicmV2ZT02Njc7ZS5tdWx0aXBseT01ODQ7ZS51YWN1dGU9NTU2O2UuVGNhcm9uPTYxMTtlLnBhcnRpYWxkaWZmPTQ3NjtlLnlkaWVyZXNpcz01MDA7ZS5OYWN1dGU9NzIyO2UuaWNpcmN1bWZsZXg9Mjc4O2UuRWNpcmN1bWZsZXg9NjY3O2UuYWRpZXJlc2lzPTU1NjtlLmVkaWVyZXNpcz01NTY7ZS5jYWN1dGU9NTAwO2UubmFjdXRlPTU1NjtlLnVtYWNyb249NTU2O2UuTmNhcm9uPTcyMjtlLklhY3V0ZT0yNzg7ZS5wbHVzbWludXM9NTg0O2UuYnJva2VuYmFyPTI2MDtlLnJlZ2lzdGVyZWQ9NzM3O2UuR2JyZXZlPTc3ODtlLklkb3RhY2NlbnQ9Mjc4O2Uuc3VtbWF0aW9uPTYwMDtlLkVncmF2ZT02Njc7ZS5yYWN1dGU9MzMzO2Uub21hY3Jvbj01NTY7ZS5aYWN1dGU9NjExO2UuWmNhcm9uPTYxMTtlLmdyZWF0ZXJlcXVhbD01NDk7ZS5FdGg9NzIyO2UuQ2NlZGlsbGE9NzIyO2UubGNvbW1hYWNjZW50PTIyMjtlLnRjYXJvbj0zMTc7ZS5lb2dvbmVrPTU1NjtlLlVvZ29uZWs9NzIyO2UuQWFjdXRlPTY2NztlLkFkaWVyZXNpcz02Njc7ZS5lZ3JhdmU9NTU2O2UuemFjdXRlPTUwMDtlLmlvZ29uZWs9MjIyO2UuT2FjdXRlPTc3ODtlLm9hY3V0ZT01NTY7ZS5hbWFjcm9uPTU1NjtlLnNhY3V0ZT01MDA7ZS5pZGllcmVzaXM9Mjc4O2UuT2NpcmN1bWZsZXg9Nzc4O2UuVWdyYXZlPTcyMjtlLkRlbHRhPTYxMjtlLnRob3JuPTU1NjtlLnR3b3N1cGVyaW9yPTMzMztlLk9kaWVyZXNpcz03Nzg7ZS5tdT01NTY7ZS5pZ3JhdmU9Mjc4O2Uub2h1bmdhcnVtbGF1dD01NTY7ZS5Fb2dvbmVrPTY2NztlLmRjcm9hdD01NTY7ZS50aHJlZXF1YXJ0ZXJzPTgzNDtlLlNjZWRpbGxhPTY2NztlLmxjYXJvbj0yOTk7ZS5LY29tbWFhY2NlbnQ9NjY3O2UuTGFjdXRlPTU1NjtlLnRyYWRlbWFyaz0xZTM7ZS5lZG90YWNjZW50PTU1NjtlLklncmF2ZT0yNzg7ZS5JbWFjcm9uPTI3ODtlLkxjYXJvbj01NTY7ZS5vbmVoYWxmPTgzNDtlLmxlc3NlcXVhbD01NDk7ZS5vY2lyY3VtZmxleD01NTY7ZS5udGlsZGU9NTU2O2UuVWh1bmdhcnVtbGF1dD03MjI7ZS5FYWN1dGU9NjY3O2UuZW1hY3Jvbj01NTY7ZS5nYnJldmU9NTU2O2Uub25lcXVhcnRlcj04MzQ7ZS5TY2Fyb249NjY3O2UuU2NvbW1hYWNjZW50PTY2NztlLk9odW5nYXJ1bWxhdXQ9Nzc4O2UuZGVncmVlPTQwMDtlLm9ncmF2ZT01NTY7ZS5DY2Fyb249NzIyO2UudWdyYXZlPTU1NjtlLnJhZGljYWw9NDUzO2UuRGNhcm9uPTcyMjtlLnJjb21tYWFjY2VudD0zMzM7ZS5OdGlsZGU9NzIyO2Uub3RpbGRlPTU1NjtlLlJjb21tYWFjY2VudD03MjI7ZS5MY29tbWFhY2NlbnQ9NTU2O2UuQXRpbGRlPTY2NztlLkFvZ29uZWs9NjY3O2UuQXJpbmc9NjY3O2UuT3RpbGRlPTc3ODtlLnpkb3RhY2NlbnQ9NTAwO2UuRWNhcm9uPTY2NztlLklvZ29uZWs9Mjc4O2Uua2NvbW1hYWNjZW50PTUwMDtlLm1pbnVzPTU4NDtlLkljaXJjdW1mbGV4PTI3ODtlLm5jYXJvbj01NTY7ZS50Y29tbWFhY2NlbnQ9Mjc4O2UubG9naWNhbG5vdD01ODQ7ZS5vZGllcmVzaXM9NTU2O2UudWRpZXJlc2lzPTU1NjtlLm5vdGVxdWFsPTU0OTtlLmdjb21tYWFjY2VudD01NTY7ZS5ldGg9NTU2O2UuemNhcm9uPTUwMDtlLm5jb21tYWFjY2VudD01NTY7ZS5vbmVzdXBlcmlvcj0zMzM7ZS5pbWFjcm9uPTI3ODtlLkV1cm89NTU2fSk7ZVsiSGVsdmV0aWNhLUJvbGQiXT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNzg7ZS5leGNsYW09MzMzO2UucXVvdGVkYmw9NDc0O2UubnVtYmVyc2lnbj01NTY7ZS5kb2xsYXI9NTU2O2UucGVyY2VudD04ODk7ZS5hbXBlcnNhbmQ9NzIyO2UucXVvdGVyaWdodD0yNzg7ZS5wYXJlbmxlZnQ9MzMzO2UucGFyZW5yaWdodD0zMzM7ZS5hc3Rlcmlzaz0zODk7ZS5wbHVzPTU4NDtlLmNvbW1hPTI3ODtlLmh5cGhlbj0zMzM7ZS5wZXJpb2Q9Mjc4O2Uuc2xhc2g9Mjc4O2UuemVybz01NTY7ZS5vbmU9NTU2O2UudHdvPTU1NjtlLnRocmVlPTU1NjtlLmZvdXI9NTU2O2UuZml2ZT01NTY7ZS5zaXg9NTU2O2Uuc2V2ZW49NTU2O2UuZWlnaHQ9NTU2O2UubmluZT01NTY7ZS5jb2xvbj0zMzM7ZS5zZW1pY29sb249MzMzO2UubGVzcz01ODQ7ZS5lcXVhbD01ODQ7ZS5ncmVhdGVyPTU4NDtlLnF1ZXN0aW9uPTYxMTtlLmF0PTk3NTtlLkE9NzIyO2UuQj03MjI7ZS5DPTcyMjtlLkQ9NzIyO2UuRT02Njc7ZS5GPTYxMTtlLkc9Nzc4O2UuSD03MjI7ZS5JPTI3ODtlLko9NTU2O2UuSz03MjI7ZS5MPTYxMTtlLk09ODMzO2UuTj03MjI7ZS5PPTc3ODtlLlA9NjY3O2UuUT03Nzg7ZS5SPTcyMjtlLlM9NjY3O2UuVD02MTE7ZS5VPTcyMjtlLlY9NjY3O2UuVz05NDQ7ZS5YPTY2NztlLlk9NjY3O2UuWj02MTE7ZS5icmFja2V0bGVmdD0zMzM7ZS5iYWNrc2xhc2g9Mjc4O2UuYnJhY2tldHJpZ2h0PTMzMztlLmFzY2lpY2lyY3VtPTU4NDtlLnVuZGVyc2NvcmU9NTU2O2UucXVvdGVsZWZ0PTI3ODtlLmE9NTU2O2UuYj02MTE7ZS5jPTU1NjtlLmQ9NjExO2UuZT01NTY7ZS5mPTMzMztlLmc9NjExO2UuaD02MTE7ZS5pPTI3ODtlLmo9Mjc4O2Uuaz01NTY7ZS5sPTI3ODtlLm09ODg5O2Uubj02MTE7ZS5vPTYxMTtlLnA9NjExO2UucT02MTE7ZS5yPTM4OTtlLnM9NTU2O2UudD0zMzM7ZS51PTYxMTtlLnY9NTU2O2Uudz03Nzg7ZS54PTU1NjtlLnk9NTU2O2Uuej01MDA7ZS5icmFjZWxlZnQ9Mzg5O2UuYmFyPTI4MDtlLmJyYWNlcmlnaHQ9Mzg5O2UuYXNjaWl0aWxkZT01ODQ7ZS5leGNsYW1kb3duPTMzMztlLmNlbnQ9NTU2O2Uuc3Rlcmxpbmc9NTU2O2UuZnJhY3Rpb249MTY3O2UueWVuPTU1NjtlLmZsb3Jpbj01NTY7ZS5zZWN0aW9uPTU1NjtlLmN1cnJlbmN5PTU1NjtlLnF1b3Rlc2luZ2xlPTIzODtlLnF1b3RlZGJsbGVmdD01MDA7ZS5ndWlsbGVtb3RsZWZ0PTU1NjtlLmd1aWxzaW5nbGxlZnQ9MzMzO2UuZ3VpbHNpbmdscmlnaHQ9MzMzO2UuZmk9NjExO2UuZmw9NjExO2UuZW5kYXNoPTU1NjtlLmRhZ2dlcj01NTY7ZS5kYWdnZXJkYmw9NTU2O2UucGVyaW9kY2VudGVyZWQ9Mjc4O2UucGFyYWdyYXBoPTU1NjtlLmJ1bGxldD0zNTA7ZS5xdW90ZXNpbmdsYmFzZT0yNzg7ZS5xdW90ZWRibGJhc2U9NTAwO2UucXVvdGVkYmxyaWdodD01MDA7ZS5ndWlsbGVtb3RyaWdodD01NTY7ZS5lbGxpcHNpcz0xZTM7ZS5wZXJ0aG91c2FuZD0xZTM7ZS5xdWVzdGlvbmRvd249NjExO2UuZ3JhdmU9MzMzO2UuYWN1dGU9MzMzO2UuY2lyY3VtZmxleD0zMzM7ZS50aWxkZT0zMzM7ZS5tYWNyb249MzMzO2UuYnJldmU9MzMzO2UuZG90YWNjZW50PTMzMztlLmRpZXJlc2lzPTMzMztlLnJpbmc9MzMzO2UuY2VkaWxsYT0zMzM7ZS5odW5nYXJ1bWxhdXQ9MzMzO2Uub2dvbmVrPTMzMztlLmNhcm9uPTMzMztlLmVtZGFzaD0xZTM7ZS5BRT0xZTM7ZS5vcmRmZW1pbmluZT0zNzA7ZS5Mc2xhc2g9NjExO2UuT3NsYXNoPTc3ODtlLk9FPTFlMztlLm9yZG1hc2N1bGluZT0zNjU7ZS5hZT04ODk7ZS5kb3RsZXNzaT0yNzg7ZS5sc2xhc2g9Mjc4O2Uub3NsYXNoPTYxMTtlLm9lPTk0NDtlLmdlcm1hbmRibHM9NjExO2UuSWRpZXJlc2lzPTI3ODtlLmVhY3V0ZT01NTY7ZS5hYnJldmU9NTU2O2UudWh1bmdhcnVtbGF1dD02MTE7ZS5lY2Fyb249NTU2O2UuWWRpZXJlc2lzPTY2NztlLmRpdmlkZT01ODQ7ZS5ZYWN1dGU9NjY3O2UuQWNpcmN1bWZsZXg9NzIyO2UuYWFjdXRlPTU1NjtlLlVjaXJjdW1mbGV4PTcyMjtlLnlhY3V0ZT01NTY7ZS5zY29tbWFhY2NlbnQ9NTU2O2UuZWNpcmN1bWZsZXg9NTU2O2UuVXJpbmc9NzIyO2UuVWRpZXJlc2lzPTcyMjtlLmFvZ29uZWs9NTU2O2UuVWFjdXRlPTcyMjtlLnVvZ29uZWs9NjExO2UuRWRpZXJlc2lzPTY2NztlLkRjcm9hdD03MjI7ZS5jb21tYWFjY2VudD0yNTA7ZS5jb3B5cmlnaHQ9NzM3O2UuRW1hY3Jvbj02Njc7ZS5jY2Fyb249NTU2O2UuYXJpbmc9NTU2O2UuTmNvbW1hYWNjZW50PTcyMjtlLmxhY3V0ZT0yNzg7ZS5hZ3JhdmU9NTU2O2UuVGNvbW1hYWNjZW50PTYxMTtlLkNhY3V0ZT03MjI7ZS5hdGlsZGU9NTU2O2UuRWRvdGFjY2VudD02Njc7ZS5zY2Fyb249NTU2O2Uuc2NlZGlsbGE9NTU2O2UuaWFjdXRlPTI3ODtlLmxvemVuZ2U9NDk0O2UuUmNhcm9uPTcyMjtlLkdjb21tYWFjY2VudD03Nzg7ZS51Y2lyY3VtZmxleD02MTE7ZS5hY2lyY3VtZmxleD01NTY7ZS5BbWFjcm9uPTcyMjtlLnJjYXJvbj0zODk7ZS5jY2VkaWxsYT01NTY7ZS5aZG90YWNjZW50PTYxMTtlLlRob3JuPTY2NztlLk9tYWNyb249Nzc4O2UuUmFjdXRlPTcyMjtlLlNhY3V0ZT02Njc7ZS5kY2Fyb249NzQzO2UuVW1hY3Jvbj03MjI7ZS51cmluZz02MTE7ZS50aHJlZXN1cGVyaW9yPTMzMztlLk9ncmF2ZT03Nzg7ZS5BZ3JhdmU9NzIyO2UuQWJyZXZlPTcyMjtlLm11bHRpcGx5PTU4NDtlLnVhY3V0ZT02MTE7ZS5UY2Fyb249NjExO2UucGFydGlhbGRpZmY9NDk0O2UueWRpZXJlc2lzPTU1NjtlLk5hY3V0ZT03MjI7ZS5pY2lyY3VtZmxleD0yNzg7ZS5FY2lyY3VtZmxleD02Njc7ZS5hZGllcmVzaXM9NTU2O2UuZWRpZXJlc2lzPTU1NjtlLmNhY3V0ZT01NTY7ZS5uYWN1dGU9NjExO2UudW1hY3Jvbj02MTE7ZS5OY2Fyb249NzIyO2UuSWFjdXRlPTI3ODtlLnBsdXNtaW51cz01ODQ7ZS5icm9rZW5iYXI9MjgwO2UucmVnaXN0ZXJlZD03Mzc7ZS5HYnJldmU9Nzc4O2UuSWRvdGFjY2VudD0yNzg7ZS5zdW1tYXRpb249NjAwO2UuRWdyYXZlPTY2NztlLnJhY3V0ZT0zODk7ZS5vbWFjcm9uPTYxMTtlLlphY3V0ZT02MTE7ZS5aY2Fyb249NjExO2UuZ3JlYXRlcmVxdWFsPTU0OTtlLkV0aD03MjI7ZS5DY2VkaWxsYT03MjI7ZS5sY29tbWFhY2NlbnQ9Mjc4O2UudGNhcm9uPTM4OTtlLmVvZ29uZWs9NTU2O2UuVW9nb25laz03MjI7ZS5BYWN1dGU9NzIyO2UuQWRpZXJlc2lzPTcyMjtlLmVncmF2ZT01NTY7ZS56YWN1dGU9NTAwO2UuaW9nb25laz0yNzg7ZS5PYWN1dGU9Nzc4O2Uub2FjdXRlPTYxMTtlLmFtYWNyb249NTU2O2Uuc2FjdXRlPTU1NjtlLmlkaWVyZXNpcz0yNzg7ZS5PY2lyY3VtZmxleD03Nzg7ZS5VZ3JhdmU9NzIyO2UuRGVsdGE9NjEyO2UudGhvcm49NjExO2UudHdvc3VwZXJpb3I9MzMzO2UuT2RpZXJlc2lzPTc3ODtlLm11PTYxMTtlLmlncmF2ZT0yNzg7ZS5vaHVuZ2FydW1sYXV0PTYxMTtlLkVvZ29uZWs9NjY3O2UuZGNyb2F0PTYxMTtlLnRocmVlcXVhcnRlcnM9ODM0O2UuU2NlZGlsbGE9NjY3O2UubGNhcm9uPTQwMDtlLktjb21tYWFjY2VudD03MjI7ZS5MYWN1dGU9NjExO2UudHJhZGVtYXJrPTFlMztlLmVkb3RhY2NlbnQ9NTU2O2UuSWdyYXZlPTI3ODtlLkltYWNyb249Mjc4O2UuTGNhcm9uPTYxMTtlLm9uZWhhbGY9ODM0O2UubGVzc2VxdWFsPTU0OTtlLm9jaXJjdW1mbGV4PTYxMTtlLm50aWxkZT02MTE7ZS5VaHVuZ2FydW1sYXV0PTcyMjtlLkVhY3V0ZT02Njc7ZS5lbWFjcm9uPTU1NjtlLmdicmV2ZT02MTE7ZS5vbmVxdWFydGVyPTgzNDtlLlNjYXJvbj02Njc7ZS5TY29tbWFhY2NlbnQ9NjY3O2UuT2h1bmdhcnVtbGF1dD03Nzg7ZS5kZWdyZWU9NDAwO2Uub2dyYXZlPTYxMTtlLkNjYXJvbj03MjI7ZS51Z3JhdmU9NjExO2UucmFkaWNhbD01NDk7ZS5EY2Fyb249NzIyO2UucmNvbW1hYWNjZW50PTM4OTtlLk50aWxkZT03MjI7ZS5vdGlsZGU9NjExO2UuUmNvbW1hYWNjZW50PTcyMjtlLkxjb21tYWFjY2VudD02MTE7ZS5BdGlsZGU9NzIyO2UuQW9nb25laz03MjI7ZS5BcmluZz03MjI7ZS5PdGlsZGU9Nzc4O2UuemRvdGFjY2VudD01MDA7ZS5FY2Fyb249NjY3O2UuSW9nb25laz0yNzg7ZS5rY29tbWFhY2NlbnQ9NTU2O2UubWludXM9NTg0O2UuSWNpcmN1bWZsZXg9Mjc4O2UubmNhcm9uPTYxMTtlLnRjb21tYWFjY2VudD0zMzM7ZS5sb2dpY2Fsbm90PTU4NDtlLm9kaWVyZXNpcz02MTE7ZS51ZGllcmVzaXM9NjExO2Uubm90ZXF1YWw9NTQ5O2UuZ2NvbW1hYWNjZW50PTYxMTtlLmV0aD02MTE7ZS56Y2Fyb249NTAwO2UubmNvbW1hYWNjZW50PTYxMTtlLm9uZXN1cGVyaW9yPTMzMztlLmltYWNyb249Mjc4O2UuRXVybz01NTZ9KTtlWyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNzg7ZS5leGNsYW09MzMzO2UucXVvdGVkYmw9NDc0O2UubnVtYmVyc2lnbj01NTY7ZS5kb2xsYXI9NTU2O2UucGVyY2VudD04ODk7ZS5hbXBlcnNhbmQ9NzIyO2UucXVvdGVyaWdodD0yNzg7ZS5wYXJlbmxlZnQ9MzMzO2UucGFyZW5yaWdodD0zMzM7ZS5hc3Rlcmlzaz0zODk7ZS5wbHVzPTU4NDtlLmNvbW1hPTI3ODtlLmh5cGhlbj0zMzM7ZS5wZXJpb2Q9Mjc4O2Uuc2xhc2g9Mjc4O2UuemVybz01NTY7ZS5vbmU9NTU2O2UudHdvPTU1NjtlLnRocmVlPTU1NjtlLmZvdXI9NTU2O2UuZml2ZT01NTY7ZS5zaXg9NTU2O2Uuc2V2ZW49NTU2O2UuZWlnaHQ9NTU2O2UubmluZT01NTY7ZS5jb2xvbj0zMzM7ZS5zZW1pY29sb249MzMzO2UubGVzcz01ODQ7ZS5lcXVhbD01ODQ7ZS5ncmVhdGVyPTU4NDtlLnF1ZXN0aW9uPTYxMTtlLmF0PTk3NTtlLkE9NzIyO2UuQj03MjI7ZS5DPTcyMjtlLkQ9NzIyO2UuRT02Njc7ZS5GPTYxMTtlLkc9Nzc4O2UuSD03MjI7ZS5JPTI3ODtlLko9NTU2O2UuSz03MjI7ZS5MPTYxMTtlLk09ODMzO2UuTj03MjI7ZS5PPTc3ODtlLlA9NjY3O2UuUT03Nzg7ZS5SPTcyMjtlLlM9NjY3O2UuVD02MTE7ZS5VPTcyMjtlLlY9NjY3O2UuVz05NDQ7ZS5YPTY2NztlLlk9NjY3O2UuWj02MTE7ZS5icmFja2V0bGVmdD0zMzM7ZS5iYWNrc2xhc2g9Mjc4O2UuYnJhY2tldHJpZ2h0PTMzMztlLmFzY2lpY2lyY3VtPTU4NDtlLnVuZGVyc2NvcmU9NTU2O2UucXVvdGVsZWZ0PTI3ODtlLmE9NTU2O2UuYj02MTE7ZS5jPTU1NjtlLmQ9NjExO2UuZT01NTY7ZS5mPTMzMztlLmc9NjExO2UuaD02MTE7ZS5pPTI3ODtlLmo9Mjc4O2Uuaz01NTY7ZS5sPTI3ODtlLm09ODg5O2Uubj02MTE7ZS5vPTYxMTtlLnA9NjExO2UucT02MTE7ZS5yPTM4OTtlLnM9NTU2O2UudD0zMzM7ZS51PTYxMTtlLnY9NTU2O2Uudz03Nzg7ZS54PTU1NjtlLnk9NTU2O2Uuej01MDA7ZS5icmFjZWxlZnQ9Mzg5O2UuYmFyPTI4MDtlLmJyYWNlcmlnaHQ9Mzg5O2UuYXNjaWl0aWxkZT01ODQ7ZS5leGNsYW1kb3duPTMzMztlLmNlbnQ9NTU2O2Uuc3Rlcmxpbmc9NTU2O2UuZnJhY3Rpb249MTY3O2UueWVuPTU1NjtlLmZsb3Jpbj01NTY7ZS5zZWN0aW9uPTU1NjtlLmN1cnJlbmN5PTU1NjtlLnF1b3Rlc2luZ2xlPTIzODtlLnF1b3RlZGJsbGVmdD01MDA7ZS5ndWlsbGVtb3RsZWZ0PTU1NjtlLmd1aWxzaW5nbGxlZnQ9MzMzO2UuZ3VpbHNpbmdscmlnaHQ9MzMzO2UuZmk9NjExO2UuZmw9NjExO2UuZW5kYXNoPTU1NjtlLmRhZ2dlcj01NTY7ZS5kYWdnZXJkYmw9NTU2O2UucGVyaW9kY2VudGVyZWQ9Mjc4O2UucGFyYWdyYXBoPTU1NjtlLmJ1bGxldD0zNTA7ZS5xdW90ZXNpbmdsYmFzZT0yNzg7ZS5xdW90ZWRibGJhc2U9NTAwO2UucXVvdGVkYmxyaWdodD01MDA7ZS5ndWlsbGVtb3RyaWdodD01NTY7ZS5lbGxpcHNpcz0xZTM7ZS5wZXJ0aG91c2FuZD0xZTM7ZS5xdWVzdGlvbmRvd249NjExO2UuZ3JhdmU9MzMzO2UuYWN1dGU9MzMzO2UuY2lyY3VtZmxleD0zMzM7ZS50aWxkZT0zMzM7ZS5tYWNyb249MzMzO2UuYnJldmU9MzMzO2UuZG90YWNjZW50PTMzMztlLmRpZXJlc2lzPTMzMztlLnJpbmc9MzMzO2UuY2VkaWxsYT0zMzM7ZS5odW5nYXJ1bWxhdXQ9MzMzO2Uub2dvbmVrPTMzMztlLmNhcm9uPTMzMztlLmVtZGFzaD0xZTM7ZS5BRT0xZTM7ZS5vcmRmZW1pbmluZT0zNzA7ZS5Mc2xhc2g9NjExO2UuT3NsYXNoPTc3ODtlLk9FPTFlMztlLm9yZG1hc2N1bGluZT0zNjU7ZS5hZT04ODk7ZS5kb3RsZXNzaT0yNzg7ZS5sc2xhc2g9Mjc4O2Uub3NsYXNoPTYxMTtlLm9lPTk0NDtlLmdlcm1hbmRibHM9NjExO2UuSWRpZXJlc2lzPTI3ODtlLmVhY3V0ZT01NTY7ZS5hYnJldmU9NTU2O2UudWh1bmdhcnVtbGF1dD02MTE7ZS5lY2Fyb249NTU2O2UuWWRpZXJlc2lzPTY2NztlLmRpdmlkZT01ODQ7ZS5ZYWN1dGU9NjY3O2UuQWNpcmN1bWZsZXg9NzIyO2UuYWFjdXRlPTU1NjtlLlVjaXJjdW1mbGV4PTcyMjtlLnlhY3V0ZT01NTY7ZS5zY29tbWFhY2NlbnQ9NTU2O2UuZWNpcmN1bWZsZXg9NTU2O2UuVXJpbmc9NzIyO2UuVWRpZXJlc2lzPTcyMjtlLmFvZ29uZWs9NTU2O2UuVWFjdXRlPTcyMjtlLnVvZ29uZWs9NjExO2UuRWRpZXJlc2lzPTY2NztlLkRjcm9hdD03MjI7ZS5jb21tYWFjY2VudD0yNTA7ZS5jb3B5cmlnaHQ9NzM3O2UuRW1hY3Jvbj02Njc7ZS5jY2Fyb249NTU2O2UuYXJpbmc9NTU2O2UuTmNvbW1hYWNjZW50PTcyMjtlLmxhY3V0ZT0yNzg7ZS5hZ3JhdmU9NTU2O2UuVGNvbW1hYWNjZW50PTYxMTtlLkNhY3V0ZT03MjI7ZS5hdGlsZGU9NTU2O2UuRWRvdGFjY2VudD02Njc7ZS5zY2Fyb249NTU2O2Uuc2NlZGlsbGE9NTU2O2UuaWFjdXRlPTI3ODtlLmxvemVuZ2U9NDk0O2UuUmNhcm9uPTcyMjtlLkdjb21tYWFjY2VudD03Nzg7ZS51Y2lyY3VtZmxleD02MTE7ZS5hY2lyY3VtZmxleD01NTY7ZS5BbWFjcm9uPTcyMjtlLnJjYXJvbj0zODk7ZS5jY2VkaWxsYT01NTY7ZS5aZG90YWNjZW50PTYxMTtlLlRob3JuPTY2NztlLk9tYWNyb249Nzc4O2UuUmFjdXRlPTcyMjtlLlNhY3V0ZT02Njc7ZS5kY2Fyb249NzQzO2UuVW1hY3Jvbj03MjI7ZS51cmluZz02MTE7ZS50aHJlZXN1cGVyaW9yPTMzMztlLk9ncmF2ZT03Nzg7ZS5BZ3JhdmU9NzIyO2UuQWJyZXZlPTcyMjtlLm11bHRpcGx5PTU4NDtlLnVhY3V0ZT02MTE7ZS5UY2Fyb249NjExO2UucGFydGlhbGRpZmY9NDk0O2UueWRpZXJlc2lzPTU1NjtlLk5hY3V0ZT03MjI7ZS5pY2lyY3VtZmxleD0yNzg7ZS5FY2lyY3VtZmxleD02Njc7ZS5hZGllcmVzaXM9NTU2O2UuZWRpZXJlc2lzPTU1NjtlLmNhY3V0ZT01NTY7ZS5uYWN1dGU9NjExO2UudW1hY3Jvbj02MTE7ZS5OY2Fyb249NzIyO2UuSWFjdXRlPTI3ODtlLnBsdXNtaW51cz01ODQ7ZS5icm9rZW5iYXI9MjgwO2UucmVnaXN0ZXJlZD03Mzc7ZS5HYnJldmU9Nzc4O2UuSWRvdGFjY2VudD0yNzg7ZS5zdW1tYXRpb249NjAwO2UuRWdyYXZlPTY2NztlLnJhY3V0ZT0zODk7ZS5vbWFjcm9uPTYxMTtlLlphY3V0ZT02MTE7ZS5aY2Fyb249NjExO2UuZ3JlYXRlcmVxdWFsPTU0OTtlLkV0aD03MjI7ZS5DY2VkaWxsYT03MjI7ZS5sY29tbWFhY2NlbnQ9Mjc4O2UudGNhcm9uPTM4OTtlLmVvZ29uZWs9NTU2O2UuVW9nb25laz03MjI7ZS5BYWN1dGU9NzIyO2UuQWRpZXJlc2lzPTcyMjtlLmVncmF2ZT01NTY7ZS56YWN1dGU9NTAwO2UuaW9nb25laz0yNzg7ZS5PYWN1dGU9Nzc4O2Uub2FjdXRlPTYxMTtlLmFtYWNyb249NTU2O2Uuc2FjdXRlPTU1NjtlLmlkaWVyZXNpcz0yNzg7ZS5PY2lyY3VtZmxleD03Nzg7ZS5VZ3JhdmU9NzIyO2UuRGVsdGE9NjEyO2UudGhvcm49NjExO2UudHdvc3VwZXJpb3I9MzMzO2UuT2RpZXJlc2lzPTc3ODtlLm11PTYxMTtlLmlncmF2ZT0yNzg7ZS5vaHVuZ2FydW1sYXV0PTYxMTtlLkVvZ29uZWs9NjY3O2UuZGNyb2F0PTYxMTtlLnRocmVlcXVhcnRlcnM9ODM0O2UuU2NlZGlsbGE9NjY3O2UubGNhcm9uPTQwMDtlLktjb21tYWFjY2VudD03MjI7ZS5MYWN1dGU9NjExO2UudHJhZGVtYXJrPTFlMztlLmVkb3RhY2NlbnQ9NTU2O2UuSWdyYXZlPTI3ODtlLkltYWNyb249Mjc4O2UuTGNhcm9uPTYxMTtlLm9uZWhhbGY9ODM0O2UubGVzc2VxdWFsPTU0OTtlLm9jaXJjdW1mbGV4PTYxMTtlLm50aWxkZT02MTE7ZS5VaHVuZ2FydW1sYXV0PTcyMjtlLkVhY3V0ZT02Njc7ZS5lbWFjcm9uPTU1NjtlLmdicmV2ZT02MTE7ZS5vbmVxdWFydGVyPTgzNDtlLlNjYXJvbj02Njc7ZS5TY29tbWFhY2NlbnQ9NjY3O2UuT2h1bmdhcnVtbGF1dD03Nzg7ZS5kZWdyZWU9NDAwO2Uub2dyYXZlPTYxMTtlLkNjYXJvbj03MjI7ZS51Z3JhdmU9NjExO2UucmFkaWNhbD01NDk7ZS5EY2Fyb249NzIyO2UucmNvbW1hYWNjZW50PTM4OTtlLk50aWxkZT03MjI7ZS5vdGlsZGU9NjExO2UuUmNvbW1hYWNjZW50PTcyMjtlLkxjb21tYWFjY2VudD02MTE7ZS5BdGlsZGU9NzIyO2UuQW9nb25laz03MjI7ZS5BcmluZz03MjI7ZS5PdGlsZGU9Nzc4O2UuemRvdGFjY2VudD01MDA7ZS5FY2Fyb249NjY3O2UuSW9nb25laz0yNzg7ZS5rY29tbWFhY2NlbnQ9NTU2O2UubWludXM9NTg0O2UuSWNpcmN1bWZsZXg9Mjc4O2UubmNhcm9uPTYxMTtlLnRjb21tYWFjY2VudD0zMzM7ZS5sb2dpY2Fsbm90PTU4NDtlLm9kaWVyZXNpcz02MTE7ZS51ZGllcmVzaXM9NjExO2Uubm90ZXF1YWw9NTQ5O2UuZ2NvbW1hYWNjZW50PTYxMTtlLmV0aD02MTE7ZS56Y2Fyb249NTAwO2UubmNvbW1hYWNjZW50PTYxMTtlLm9uZXN1cGVyaW9yPTMzMztlLmltYWNyb249Mjc4O2UuRXVybz01NTZ9KTtlWyJIZWx2ZXRpY2EtT2JsaXF1ZSJdPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlLnNwYWNlPTI3ODtlLmV4Y2xhbT0yNzg7ZS5xdW90ZWRibD0zNTU7ZS5udW1iZXJzaWduPTU1NjtlLmRvbGxhcj01NTY7ZS5wZXJjZW50PTg4OTtlLmFtcGVyc2FuZD02Njc7ZS5xdW90ZXJpZ2h0PTIyMjtlLnBhcmVubGVmdD0zMzM7ZS5wYXJlbnJpZ2h0PTMzMztlLmFzdGVyaXNrPTM4OTtlLnBsdXM9NTg0O2UuY29tbWE9Mjc4O2UuaHlwaGVuPTMzMztlLnBlcmlvZD0yNzg7ZS5zbGFzaD0yNzg7ZS56ZXJvPTU1NjtlLm9uZT01NTY7ZS50d289NTU2O2UudGhyZWU9NTU2O2UuZm91cj01NTY7ZS5maXZlPTU1NjtlLnNpeD01NTY7ZS5zZXZlbj01NTY7ZS5laWdodD01NTY7ZS5uaW5lPTU1NjtlLmNvbG9uPTI3ODtlLnNlbWljb2xvbj0yNzg7ZS5sZXNzPTU4NDtlLmVxdWFsPTU4NDtlLmdyZWF0ZXI9NTg0O2UucXVlc3Rpb249NTU2O2UuYXQ9MTAxNTtlLkE9NjY3O2UuQj02Njc7ZS5DPTcyMjtlLkQ9NzIyO2UuRT02Njc7ZS5GPTYxMTtlLkc9Nzc4O2UuSD03MjI7ZS5JPTI3ODtlLko9NTAwO2UuSz02Njc7ZS5MPTU1NjtlLk09ODMzO2UuTj03MjI7ZS5PPTc3ODtlLlA9NjY3O2UuUT03Nzg7ZS5SPTcyMjtlLlM9NjY3O2UuVD02MTE7ZS5VPTcyMjtlLlY9NjY3O2UuVz05NDQ7ZS5YPTY2NztlLlk9NjY3O2UuWj02MTE7ZS5icmFja2V0bGVmdD0yNzg7ZS5iYWNrc2xhc2g9Mjc4O2UuYnJhY2tldHJpZ2h0PTI3ODtlLmFzY2lpY2lyY3VtPTQ2OTtlLnVuZGVyc2NvcmU9NTU2O2UucXVvdGVsZWZ0PTIyMjtlLmE9NTU2O2UuYj01NTY7ZS5jPTUwMDtlLmQ9NTU2O2UuZT01NTY7ZS5mPTI3ODtlLmc9NTU2O2UuaD01NTY7ZS5pPTIyMjtlLmo9MjIyO2Uuaz01MDA7ZS5sPTIyMjtlLm09ODMzO2Uubj01NTY7ZS5vPTU1NjtlLnA9NTU2O2UucT01NTY7ZS5yPTMzMztlLnM9NTAwO2UudD0yNzg7ZS51PTU1NjtlLnY9NTAwO2Uudz03MjI7ZS54PTUwMDtlLnk9NTAwO2Uuej01MDA7ZS5icmFjZWxlZnQ9MzM0O2UuYmFyPTI2MDtlLmJyYWNlcmlnaHQ9MzM0O2UuYXNjaWl0aWxkZT01ODQ7ZS5leGNsYW1kb3duPTMzMztlLmNlbnQ9NTU2O2Uuc3Rlcmxpbmc9NTU2O2UuZnJhY3Rpb249MTY3O2UueWVuPTU1NjtlLmZsb3Jpbj01NTY7ZS5zZWN0aW9uPTU1NjtlLmN1cnJlbmN5PTU1NjtlLnF1b3Rlc2luZ2xlPTE5MTtlLnF1b3RlZGJsbGVmdD0zMzM7ZS5ndWlsbGVtb3RsZWZ0PTU1NjtlLmd1aWxzaW5nbGxlZnQ9MzMzO2UuZ3VpbHNpbmdscmlnaHQ9MzMzO2UuZmk9NTAwO2UuZmw9NTAwO2UuZW5kYXNoPTU1NjtlLmRhZ2dlcj01NTY7ZS5kYWdnZXJkYmw9NTU2O2UucGVyaW9kY2VudGVyZWQ9Mjc4O2UucGFyYWdyYXBoPTUzNztlLmJ1bGxldD0zNTA7ZS5xdW90ZXNpbmdsYmFzZT0yMjI7ZS5xdW90ZWRibGJhc2U9MzMzO2UucXVvdGVkYmxyaWdodD0zMzM7ZS5ndWlsbGVtb3RyaWdodD01NTY7ZS5lbGxpcHNpcz0xZTM7ZS5wZXJ0aG91c2FuZD0xZTM7ZS5xdWVzdGlvbmRvd249NjExO2UuZ3JhdmU9MzMzO2UuYWN1dGU9MzMzO2UuY2lyY3VtZmxleD0zMzM7ZS50aWxkZT0zMzM7ZS5tYWNyb249MzMzO2UuYnJldmU9MzMzO2UuZG90YWNjZW50PTMzMztlLmRpZXJlc2lzPTMzMztlLnJpbmc9MzMzO2UuY2VkaWxsYT0zMzM7ZS5odW5nYXJ1bWxhdXQ9MzMzO2Uub2dvbmVrPTMzMztlLmNhcm9uPTMzMztlLmVtZGFzaD0xZTM7ZS5BRT0xZTM7ZS5vcmRmZW1pbmluZT0zNzA7ZS5Mc2xhc2g9NTU2O2UuT3NsYXNoPTc3ODtlLk9FPTFlMztlLm9yZG1hc2N1bGluZT0zNjU7ZS5hZT04ODk7ZS5kb3RsZXNzaT0yNzg7ZS5sc2xhc2g9MjIyO2Uub3NsYXNoPTYxMTtlLm9lPTk0NDtlLmdlcm1hbmRibHM9NjExO2UuSWRpZXJlc2lzPTI3ODtlLmVhY3V0ZT01NTY7ZS5hYnJldmU9NTU2O2UudWh1bmdhcnVtbGF1dD01NTY7ZS5lY2Fyb249NTU2O2UuWWRpZXJlc2lzPTY2NztlLmRpdmlkZT01ODQ7ZS5ZYWN1dGU9NjY3O2UuQWNpcmN1bWZsZXg9NjY3O2UuYWFjdXRlPTU1NjtlLlVjaXJjdW1mbGV4PTcyMjtlLnlhY3V0ZT01MDA7ZS5zY29tbWFhY2NlbnQ9NTAwO2UuZWNpcmN1bWZsZXg9NTU2O2UuVXJpbmc9NzIyO2UuVWRpZXJlc2lzPTcyMjtlLmFvZ29uZWs9NTU2O2UuVWFjdXRlPTcyMjtlLnVvZ29uZWs9NTU2O2UuRWRpZXJlc2lzPTY2NztlLkRjcm9hdD03MjI7ZS5jb21tYWFjY2VudD0yNTA7ZS5jb3B5cmlnaHQ9NzM3O2UuRW1hY3Jvbj02Njc7ZS5jY2Fyb249NTAwO2UuYXJpbmc9NTU2O2UuTmNvbW1hYWNjZW50PTcyMjtlLmxhY3V0ZT0yMjI7ZS5hZ3JhdmU9NTU2O2UuVGNvbW1hYWNjZW50PTYxMTtlLkNhY3V0ZT03MjI7ZS5hdGlsZGU9NTU2O2UuRWRvdGFjY2VudD02Njc7ZS5zY2Fyb249NTAwO2Uuc2NlZGlsbGE9NTAwO2UuaWFjdXRlPTI3ODtlLmxvemVuZ2U9NDcxO2UuUmNhcm9uPTcyMjtlLkdjb21tYWFjY2VudD03Nzg7ZS51Y2lyY3VtZmxleD01NTY7ZS5hY2lyY3VtZmxleD01NTY7ZS5BbWFjcm9uPTY2NztlLnJjYXJvbj0zMzM7ZS5jY2VkaWxsYT01MDA7ZS5aZG90YWNjZW50PTYxMTtlLlRob3JuPTY2NztlLk9tYWNyb249Nzc4O2UuUmFjdXRlPTcyMjtlLlNhY3V0ZT02Njc7ZS5kY2Fyb249NjQzO2UuVW1hY3Jvbj03MjI7ZS51cmluZz01NTY7ZS50aHJlZXN1cGVyaW9yPTMzMztlLk9ncmF2ZT03Nzg7ZS5BZ3JhdmU9NjY3O2UuQWJyZXZlPTY2NztlLm11bHRpcGx5PTU4NDtlLnVhY3V0ZT01NTY7ZS5UY2Fyb249NjExO2UucGFydGlhbGRpZmY9NDc2O2UueWRpZXJlc2lzPTUwMDtlLk5hY3V0ZT03MjI7ZS5pY2lyY3VtZmxleD0yNzg7ZS5FY2lyY3VtZmxleD02Njc7ZS5hZGllcmVzaXM9NTU2O2UuZWRpZXJlc2lzPTU1NjtlLmNhY3V0ZT01MDA7ZS5uYWN1dGU9NTU2O2UudW1hY3Jvbj01NTY7ZS5OY2Fyb249NzIyO2UuSWFjdXRlPTI3ODtlLnBsdXNtaW51cz01ODQ7ZS5icm9rZW5iYXI9MjYwO2UucmVnaXN0ZXJlZD03Mzc7ZS5HYnJldmU9Nzc4O2UuSWRvdGFjY2VudD0yNzg7ZS5zdW1tYXRpb249NjAwO2UuRWdyYXZlPTY2NztlLnJhY3V0ZT0zMzM7ZS5vbWFjcm9uPTU1NjtlLlphY3V0ZT02MTE7ZS5aY2Fyb249NjExO2UuZ3JlYXRlcmVxdWFsPTU0OTtlLkV0aD03MjI7ZS5DY2VkaWxsYT03MjI7ZS5sY29tbWFhY2NlbnQ9MjIyO2UudGNhcm9uPTMxNztlLmVvZ29uZWs9NTU2O2UuVW9nb25laz03MjI7ZS5BYWN1dGU9NjY3O2UuQWRpZXJlc2lzPTY2NztlLmVncmF2ZT01NTY7ZS56YWN1dGU9NTAwO2UuaW9nb25laz0yMjI7ZS5PYWN1dGU9Nzc4O2Uub2FjdXRlPTU1NjtlLmFtYWNyb249NTU2O2Uuc2FjdXRlPTUwMDtlLmlkaWVyZXNpcz0yNzg7ZS5PY2lyY3VtZmxleD03Nzg7ZS5VZ3JhdmU9NzIyO2UuRGVsdGE9NjEyO2UudGhvcm49NTU2O2UudHdvc3VwZXJpb3I9MzMzO2UuT2RpZXJlc2lzPTc3ODtlLm11PTU1NjtlLmlncmF2ZT0yNzg7ZS5vaHVuZ2FydW1sYXV0PTU1NjtlLkVvZ29uZWs9NjY3O2UuZGNyb2F0PTU1NjtlLnRocmVlcXVhcnRlcnM9ODM0O2UuU2NlZGlsbGE9NjY3O2UubGNhcm9uPTI5OTtlLktjb21tYWFjY2VudD02Njc7ZS5MYWN1dGU9NTU2O2UudHJhZGVtYXJrPTFlMztlLmVkb3RhY2NlbnQ9NTU2O2UuSWdyYXZlPTI3ODtlLkltYWNyb249Mjc4O2UuTGNhcm9uPTU1NjtlLm9uZWhhbGY9ODM0O2UubGVzc2VxdWFsPTU0OTtlLm9jaXJjdW1mbGV4PTU1NjtlLm50aWxkZT01NTY7ZS5VaHVuZ2FydW1sYXV0PTcyMjtlLkVhY3V0ZT02Njc7ZS5lbWFjcm9uPTU1NjtlLmdicmV2ZT01NTY7ZS5vbmVxdWFydGVyPTgzNDtlLlNjYXJvbj02Njc7ZS5TY29tbWFhY2NlbnQ9NjY3O2UuT2h1bmdhcnVtbGF1dD03Nzg7ZS5kZWdyZWU9NDAwO2Uub2dyYXZlPTU1NjtlLkNjYXJvbj03MjI7ZS51Z3JhdmU9NTU2O2UucmFkaWNhbD00NTM7ZS5EY2Fyb249NzIyO2UucmNvbW1hYWNjZW50PTMzMztlLk50aWxkZT03MjI7ZS5vdGlsZGU9NTU2O2UuUmNvbW1hYWNjZW50PTcyMjtlLkxjb21tYWFjY2VudD01NTY7ZS5BdGlsZGU9NjY3O2UuQW9nb25laz02Njc7ZS5BcmluZz02Njc7ZS5PdGlsZGU9Nzc4O2UuemRvdGFjY2VudD01MDA7ZS5FY2Fyb249NjY3O2UuSW9nb25laz0yNzg7ZS5rY29tbWFhY2NlbnQ9NTAwO2UubWludXM9NTg0O2UuSWNpcmN1bWZsZXg9Mjc4O2UubmNhcm9uPTU1NjtlLnRjb21tYWFjY2VudD0yNzg7ZS5sb2dpY2Fsbm90PTU4NDtlLm9kaWVyZXNpcz01NTY7ZS51ZGllcmVzaXM9NTU2O2Uubm90ZXF1YWw9NTQ5O2UuZ2NvbW1hYWNjZW50PTU1NjtlLmV0aD01NTY7ZS56Y2Fyb249NTAwO2UubmNvbW1hYWNjZW50PTU1NjtlLm9uZXN1cGVyaW9yPTMzMztlLmltYWNyb249Mjc4O2UuRXVybz01NTZ9KTtlLlN5bWJvbD1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNTA7ZS5leGNsYW09MzMzO2UudW5pdmVyc2FsPTcxMztlLm51bWJlcnNpZ249NTAwO2UuZXhpc3RlbnRpYWw9NTQ5O2UucGVyY2VudD04MzM7ZS5hbXBlcnNhbmQ9Nzc4O2Uuc3VjaHRoYXQ9NDM5O2UucGFyZW5sZWZ0PTMzMztlLnBhcmVucmlnaHQ9MzMzO2UuYXN0ZXJpc2ttYXRoPTUwMDtlLnBsdXM9NTQ5O2UuY29tbWE9MjUwO2UubWludXM9NTQ5O2UucGVyaW9kPTI1MDtlLnNsYXNoPTI3ODtlLnplcm89NTAwO2Uub25lPTUwMDtlLnR3bz01MDA7ZS50aHJlZT01MDA7ZS5mb3VyPTUwMDtlLmZpdmU9NTAwO2Uuc2l4PTUwMDtlLnNldmVuPTUwMDtlLmVpZ2h0PTUwMDtlLm5pbmU9NTAwO2UuY29sb249Mjc4O2Uuc2VtaWNvbG9uPTI3ODtlLmxlc3M9NTQ5O2UuZXF1YWw9NTQ5O2UuZ3JlYXRlcj01NDk7ZS5xdWVzdGlvbj00NDQ7ZS5jb25ncnVlbnQ9NTQ5O2UuQWxwaGE9NzIyO2UuQmV0YT02Njc7ZS5DaGk9NzIyO2UuRGVsdGE9NjEyO2UuRXBzaWxvbj02MTE7ZS5QaGk9NzYzO2UuR2FtbWE9NjAzO2UuRXRhPTcyMjtlLklvdGE9MzMzO2UudGhldGExPTYzMTtlLkthcHBhPTcyMjtlLkxhbWJkYT02ODY7ZS5NdT04ODk7ZS5OdT03MjI7ZS5PbWljcm9uPTcyMjtlLlBpPTc2ODtlLlRoZXRhPTc0MTtlLlJobz01NTY7ZS5TaWdtYT01OTI7ZS5UYXU9NjExO2UuVXBzaWxvbj02OTA7ZS5zaWdtYTE9NDM5O2UuT21lZ2E9NzY4O2UuWGk9NjQ1O2UuUHNpPTc5NTtlLlpldGE9NjExO2UuYnJhY2tldGxlZnQ9MzMzO2UudGhlcmVmb3JlPTg2MztlLmJyYWNrZXRyaWdodD0zMzM7ZS5wZXJwZW5kaWN1bGFyPTY1ODtlLnVuZGVyc2NvcmU9NTAwO2UucmFkaWNhbGV4PTUwMDtlLmFscGhhPTYzMTtlLmJldGE9NTQ5O2UuY2hpPTU0OTtlLmRlbHRhPTQ5NDtlLmVwc2lsb249NDM5O2UucGhpPTUyMTtlLmdhbW1hPTQxMTtlLmV0YT02MDM7ZS5pb3RhPTMyOTtlLnBoaTE9NjAzO2Uua2FwcGE9NTQ5O2UubGFtYmRhPTU0OTtlLm11PTU3NjtlLm51PTUyMTtlLm9taWNyb249NTQ5O2UucGk9NTQ5O2UudGhldGE9NTIxO2UucmhvPTU0OTtlLnNpZ21hPTYwMztlLnRhdT00Mzk7ZS51cHNpbG9uPTU3NjtlLm9tZWdhMT03MTM7ZS5vbWVnYT02ODY7ZS54aT00OTM7ZS5wc2k9Njg2O2UuemV0YT00OTQ7ZS5icmFjZWxlZnQ9NDgwO2UuYmFyPTIwMDtlLmJyYWNlcmlnaHQ9NDgwO2Uuc2ltaWxhcj01NDk7ZS5FdXJvPTc1MDtlLlVwc2lsb24xPTYyMDtlLm1pbnV0ZT0yNDc7ZS5sZXNzZXF1YWw9NTQ5O2UuZnJhY3Rpb249MTY3O2UuaW5maW5pdHk9NzEzO2UuZmxvcmluPTUwMDtlLmNsdWI9NzUzO2UuZGlhbW9uZD03NTM7ZS5oZWFydD03NTM7ZS5zcGFkZT03NTM7ZS5hcnJvd2JvdGg9MTA0MjtlLmFycm93bGVmdD05ODc7ZS5hcnJvd3VwPTYwMztlLmFycm93cmlnaHQ9OTg3O2UuYXJyb3dkb3duPTYwMztlLmRlZ3JlZT00MDA7ZS5wbHVzbWludXM9NTQ5O2Uuc2Vjb25kPTQxMTtlLmdyZWF0ZXJlcXVhbD01NDk7ZS5tdWx0aXBseT01NDk7ZS5wcm9wb3J0aW9uYWw9NzEzO2UucGFydGlhbGRpZmY9NDk0O2UuYnVsbGV0PTQ2MDtlLmRpdmlkZT01NDk7ZS5ub3RlcXVhbD01NDk7ZS5lcXVpdmFsZW5jZT01NDk7ZS5hcHByb3hlcXVhbD01NDk7ZS5lbGxpcHNpcz0xZTM7ZS5hcnJvd3ZlcnRleD02MDM7ZS5hcnJvd2hvcml6ZXg9MWUzO2UuY2FycmlhZ2VyZXR1cm49NjU4O2UuYWxlcGg9ODIzO2UuSWZyYWt0dXI9Njg2O2UuUmZyYWt0dXI9Nzk1O2Uud2VpZXJzdHJhc3M9OTg3O2UuY2lyY2xlbXVsdGlwbHk9NzY4O2UuY2lyY2xlcGx1cz03Njg7ZS5lbXB0eXNldD04MjM7ZS5pbnRlcnNlY3Rpb249NzY4O2UudW5pb249NzY4O2UucHJvcGVyc3VwZXJzZXQ9NzEzO2UucmVmbGV4c3VwZXJzZXQ9NzEzO2Uubm90c3Vic2V0PTcxMztlLnByb3BlcnN1YnNldD03MTM7ZS5yZWZsZXhzdWJzZXQ9NzEzO2UuZWxlbWVudD03MTM7ZS5ub3RlbGVtZW50PTcxMztlLmFuZ2xlPTc2ODtlLmdyYWRpZW50PTcxMztlLnJlZ2lzdGVyc2VyaWY9NzkwO2UuY29weXJpZ2h0c2VyaWY9NzkwO2UudHJhZGVtYXJrc2VyaWY9ODkwO2UucHJvZHVjdD04MjM7ZS5yYWRpY2FsPTU0OTtlLmRvdG1hdGg9MjUwO2UubG9naWNhbG5vdD03MTM7ZS5sb2dpY2FsYW5kPTYwMztlLmxvZ2ljYWxvcj02MDM7ZS5hcnJvd2RibGJvdGg9MTA0MjtlLmFycm93ZGJsbGVmdD05ODc7ZS5hcnJvd2RibHVwPTYwMztlLmFycm93ZGJscmlnaHQ9OTg3O2UuYXJyb3dkYmxkb3duPTYwMztlLmxvemVuZ2U9NDk0O2UuYW5nbGVsZWZ0PTMyOTtlLnJlZ2lzdGVyc2Fucz03OTA7ZS5jb3B5cmlnaHRzYW5zPTc5MDtlLnRyYWRlbWFya3NhbnM9Nzg2O2Uuc3VtbWF0aW9uPTcxMztlLnBhcmVubGVmdHRwPTM4NDtlLnBhcmVubGVmdGV4PTM4NDtlLnBhcmVubGVmdGJ0PTM4NDtlLmJyYWNrZXRsZWZ0dHA9Mzg0O2UuYnJhY2tldGxlZnRleD0zODQ7ZS5icmFja2V0bGVmdGJ0PTM4NDtlLmJyYWNlbGVmdHRwPTQ5NDtlLmJyYWNlbGVmdG1pZD00OTQ7ZS5icmFjZWxlZnRidD00OTQ7ZS5icmFjZWV4PTQ5NDtlLmFuZ2xlcmlnaHQ9MzI5O2UuaW50ZWdyYWw9Mjc0O2UuaW50ZWdyYWx0cD02ODY7ZS5pbnRlZ3JhbGV4PTY4NjtlLmludGVncmFsYnQ9Njg2O2UucGFyZW5yaWdodHRwPTM4NDtlLnBhcmVucmlnaHRleD0zODQ7ZS5wYXJlbnJpZ2h0YnQ9Mzg0O2UuYnJhY2tldHJpZ2h0dHA9Mzg0O2UuYnJhY2tldHJpZ2h0ZXg9Mzg0O2UuYnJhY2tldHJpZ2h0YnQ9Mzg0O2UuYnJhY2VyaWdodHRwPTQ5NDtlLmJyYWNlcmlnaHRtaWQ9NDk0O2UuYnJhY2VyaWdodGJ0PTQ5NDtlLmFwcGxlPTc5MH0pO2VbIlRpbWVzLVJvbWFuIl09Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2Uuc3BhY2U9MjUwO2UuZXhjbGFtPTMzMztlLnF1b3RlZGJsPTQwODtlLm51bWJlcnNpZ249NTAwO2UuZG9sbGFyPTUwMDtlLnBlcmNlbnQ9ODMzO2UuYW1wZXJzYW5kPTc3ODtlLnF1b3RlcmlnaHQ9MzMzO2UucGFyZW5sZWZ0PTMzMztlLnBhcmVucmlnaHQ9MzMzO2UuYXN0ZXJpc2s9NTAwO2UucGx1cz01NjQ7ZS5jb21tYT0yNTA7ZS5oeXBoZW49MzMzO2UucGVyaW9kPTI1MDtlLnNsYXNoPTI3ODtlLnplcm89NTAwO2Uub25lPTUwMDtlLnR3bz01MDA7ZS50aHJlZT01MDA7ZS5mb3VyPTUwMDtlLmZpdmU9NTAwO2Uuc2l4PTUwMDtlLnNldmVuPTUwMDtlLmVpZ2h0PTUwMDtlLm5pbmU9NTAwO2UuY29sb249Mjc4O2Uuc2VtaWNvbG9uPTI3ODtlLmxlc3M9NTY0O2UuZXF1YWw9NTY0O2UuZ3JlYXRlcj01NjQ7ZS5xdWVzdGlvbj00NDQ7ZS5hdD05MjE7ZS5BPTcyMjtlLkI9NjY3O2UuQz02Njc7ZS5EPTcyMjtlLkU9NjExO2UuRj01NTY7ZS5HPTcyMjtlLkg9NzIyO2UuST0zMzM7ZS5KPTM4OTtlLks9NzIyO2UuTD02MTE7ZS5NPTg4OTtlLk49NzIyO2UuTz03MjI7ZS5QPTU1NjtlLlE9NzIyO2UuUj02Njc7ZS5TPTU1NjtlLlQ9NjExO2UuVT03MjI7ZS5WPTcyMjtlLlc9OTQ0O2UuWD03MjI7ZS5ZPTcyMjtlLlo9NjExO2UuYnJhY2tldGxlZnQ9MzMzO2UuYmFja3NsYXNoPTI3ODtlLmJyYWNrZXRyaWdodD0zMzM7ZS5hc2NpaWNpcmN1bT00Njk7ZS51bmRlcnNjb3JlPTUwMDtlLnF1b3RlbGVmdD0zMzM7ZS5hPTQ0NDtlLmI9NTAwO2UuYz00NDQ7ZS5kPTUwMDtlLmU9NDQ0O2UuZj0zMzM7ZS5nPTUwMDtlLmg9NTAwO2UuaT0yNzg7ZS5qPTI3ODtlLms9NTAwO2UubD0yNzg7ZS5tPTc3ODtlLm49NTAwO2Uubz01MDA7ZS5wPTUwMDtlLnE9NTAwO2Uucj0zMzM7ZS5zPTM4OTtlLnQ9Mjc4O2UudT01MDA7ZS52PTUwMDtlLnc9NzIyO2UueD01MDA7ZS55PTUwMDtlLno9NDQ0O2UuYnJhY2VsZWZ0PTQ4MDtlLmJhcj0yMDA7ZS5icmFjZXJpZ2h0PTQ4MDtlLmFzY2lpdGlsZGU9NTQxO2UuZXhjbGFtZG93bj0zMzM7ZS5jZW50PTUwMDtlLnN0ZXJsaW5nPTUwMDtlLmZyYWN0aW9uPTE2NztlLnllbj01MDA7ZS5mbG9yaW49NTAwO2Uuc2VjdGlvbj01MDA7ZS5jdXJyZW5jeT01MDA7ZS5xdW90ZXNpbmdsZT0xODA7ZS5xdW90ZWRibGxlZnQ9NDQ0O2UuZ3VpbGxlbW90bGVmdD01MDA7ZS5ndWlsc2luZ2xsZWZ0PTMzMztlLmd1aWxzaW5nbHJpZ2h0PTMzMztlLmZpPTU1NjtlLmZsPTU1NjtlLmVuZGFzaD01MDA7ZS5kYWdnZXI9NTAwO2UuZGFnZ2VyZGJsPTUwMDtlLnBlcmlvZGNlbnRlcmVkPTI1MDtlLnBhcmFncmFwaD00NTM7ZS5idWxsZXQ9MzUwO2UucXVvdGVzaW5nbGJhc2U9MzMzO2UucXVvdGVkYmxiYXNlPTQ0NDtlLnF1b3RlZGJscmlnaHQ9NDQ0O2UuZ3VpbGxlbW90cmlnaHQ9NTAwO2UuZWxsaXBzaXM9MWUzO2UucGVydGhvdXNhbmQ9MWUzO2UucXVlc3Rpb25kb3duPTQ0NDtlLmdyYXZlPTMzMztlLmFjdXRlPTMzMztlLmNpcmN1bWZsZXg9MzMzO2UudGlsZGU9MzMzO2UubWFjcm9uPTMzMztlLmJyZXZlPTMzMztlLmRvdGFjY2VudD0zMzM7ZS5kaWVyZXNpcz0zMzM7ZS5yaW5nPTMzMztlLmNlZGlsbGE9MzMzO2UuaHVuZ2FydW1sYXV0PTMzMztlLm9nb25laz0zMzM7ZS5jYXJvbj0zMzM7ZS5lbWRhc2g9MWUzO2UuQUU9ODg5O2Uub3JkZmVtaW5pbmU9Mjc2O2UuTHNsYXNoPTYxMTtlLk9zbGFzaD03MjI7ZS5PRT04ODk7ZS5vcmRtYXNjdWxpbmU9MzEwO2UuYWU9NjY3O2UuZG90bGVzc2k9Mjc4O2UubHNsYXNoPTI3ODtlLm9zbGFzaD01MDA7ZS5vZT03MjI7ZS5nZXJtYW5kYmxzPTUwMDtlLklkaWVyZXNpcz0zMzM7ZS5lYWN1dGU9NDQ0O2UuYWJyZXZlPTQ0NDtlLnVodW5nYXJ1bWxhdXQ9NTAwO2UuZWNhcm9uPTQ0NDtlLllkaWVyZXNpcz03MjI7ZS5kaXZpZGU9NTY0O2UuWWFjdXRlPTcyMjtlLkFjaXJjdW1mbGV4PTcyMjtlLmFhY3V0ZT00NDQ7ZS5VY2lyY3VtZmxleD03MjI7ZS55YWN1dGU9NTAwO2Uuc2NvbW1hYWNjZW50PTM4OTtlLmVjaXJjdW1mbGV4PTQ0NDtlLlVyaW5nPTcyMjtlLlVkaWVyZXNpcz03MjI7ZS5hb2dvbmVrPTQ0NDtlLlVhY3V0ZT03MjI7ZS51b2dvbmVrPTUwMDtlLkVkaWVyZXNpcz02MTE7ZS5EY3JvYXQ9NzIyO2UuY29tbWFhY2NlbnQ9MjUwO2UuY29weXJpZ2h0PTc2MDtlLkVtYWNyb249NjExO2UuY2Nhcm9uPTQ0NDtlLmFyaW5nPTQ0NDtlLk5jb21tYWFjY2VudD03MjI7ZS5sYWN1dGU9Mjc4O2UuYWdyYXZlPTQ0NDtlLlRjb21tYWFjY2VudD02MTE7ZS5DYWN1dGU9NjY3O2UuYXRpbGRlPTQ0NDtlLkVkb3RhY2NlbnQ9NjExO2Uuc2Nhcm9uPTM4OTtlLnNjZWRpbGxhPTM4OTtlLmlhY3V0ZT0yNzg7ZS5sb3plbmdlPTQ3MTtlLlJjYXJvbj02Njc7ZS5HY29tbWFhY2NlbnQ9NzIyO2UudWNpcmN1bWZsZXg9NTAwO2UuYWNpcmN1bWZsZXg9NDQ0O2UuQW1hY3Jvbj03MjI7ZS5yY2Fyb249MzMzO2UuY2NlZGlsbGE9NDQ0O2UuWmRvdGFjY2VudD02MTE7ZS5UaG9ybj01NTY7ZS5PbWFjcm9uPTcyMjtlLlJhY3V0ZT02Njc7ZS5TYWN1dGU9NTU2O2UuZGNhcm9uPTU4ODtlLlVtYWNyb249NzIyO2UudXJpbmc9NTAwO2UudGhyZWVzdXBlcmlvcj0zMDA7ZS5PZ3JhdmU9NzIyO2UuQWdyYXZlPTcyMjtlLkFicmV2ZT03MjI7ZS5tdWx0aXBseT01NjQ7ZS51YWN1dGU9NTAwO2UuVGNhcm9uPTYxMTtlLnBhcnRpYWxkaWZmPTQ3NjtlLnlkaWVyZXNpcz01MDA7ZS5OYWN1dGU9NzIyO2UuaWNpcmN1bWZsZXg9Mjc4O2UuRWNpcmN1bWZsZXg9NjExO2UuYWRpZXJlc2lzPTQ0NDtlLmVkaWVyZXNpcz00NDQ7ZS5jYWN1dGU9NDQ0O2UubmFjdXRlPTUwMDtlLnVtYWNyb249NTAwO2UuTmNhcm9uPTcyMjtlLklhY3V0ZT0zMzM7ZS5wbHVzbWludXM9NTY0O2UuYnJva2VuYmFyPTIwMDtlLnJlZ2lzdGVyZWQ9NzYwO2UuR2JyZXZlPTcyMjtlLklkb3RhY2NlbnQ9MzMzO2Uuc3VtbWF0aW9uPTYwMDtlLkVncmF2ZT02MTE7ZS5yYWN1dGU9MzMzO2Uub21hY3Jvbj01MDA7ZS5aYWN1dGU9NjExO2UuWmNhcm9uPTYxMTtlLmdyZWF0ZXJlcXVhbD01NDk7ZS5FdGg9NzIyO2UuQ2NlZGlsbGE9NjY3O2UubGNvbW1hYWNjZW50PTI3ODtlLnRjYXJvbj0zMjY7ZS5lb2dvbmVrPTQ0NDtlLlVvZ29uZWs9NzIyO2UuQWFjdXRlPTcyMjtlLkFkaWVyZXNpcz03MjI7ZS5lZ3JhdmU9NDQ0O2UuemFjdXRlPTQ0NDtlLmlvZ29uZWs9Mjc4O2UuT2FjdXRlPTcyMjtlLm9hY3V0ZT01MDA7ZS5hbWFjcm9uPTQ0NDtlLnNhY3V0ZT0zODk7ZS5pZGllcmVzaXM9Mjc4O2UuT2NpcmN1bWZsZXg9NzIyO2UuVWdyYXZlPTcyMjtlLkRlbHRhPTYxMjtlLnRob3JuPTUwMDtlLnR3b3N1cGVyaW9yPTMwMDtlLk9kaWVyZXNpcz03MjI7ZS5tdT01MDA7ZS5pZ3JhdmU9Mjc4O2Uub2h1bmdhcnVtbGF1dD01MDA7ZS5Fb2dvbmVrPTYxMTtlLmRjcm9hdD01MDA7ZS50aHJlZXF1YXJ0ZXJzPTc1MDtlLlNjZWRpbGxhPTU1NjtlLmxjYXJvbj0zNDQ7ZS5LY29tbWFhY2NlbnQ9NzIyO2UuTGFjdXRlPTYxMTtlLnRyYWRlbWFyaz05ODA7ZS5lZG90YWNjZW50PTQ0NDtlLklncmF2ZT0zMzM7ZS5JbWFjcm9uPTMzMztlLkxjYXJvbj02MTE7ZS5vbmVoYWxmPTc1MDtlLmxlc3NlcXVhbD01NDk7ZS5vY2lyY3VtZmxleD01MDA7ZS5udGlsZGU9NTAwO2UuVWh1bmdhcnVtbGF1dD03MjI7ZS5FYWN1dGU9NjExO2UuZW1hY3Jvbj00NDQ7ZS5nYnJldmU9NTAwO2Uub25lcXVhcnRlcj03NTA7ZS5TY2Fyb249NTU2O2UuU2NvbW1hYWNjZW50PTU1NjtlLk9odW5nYXJ1bWxhdXQ9NzIyO2UuZGVncmVlPTQwMDtlLm9ncmF2ZT01MDA7ZS5DY2Fyb249NjY3O2UudWdyYXZlPTUwMDtlLnJhZGljYWw9NDUzO2UuRGNhcm9uPTcyMjtlLnJjb21tYWFjY2VudD0zMzM7ZS5OdGlsZGU9NzIyO2Uub3RpbGRlPTUwMDtlLlJjb21tYWFjY2VudD02Njc7ZS5MY29tbWFhY2NlbnQ9NjExO2UuQXRpbGRlPTcyMjtlLkFvZ29uZWs9NzIyO2UuQXJpbmc9NzIyO2UuT3RpbGRlPTcyMjtlLnpkb3RhY2NlbnQ9NDQ0O2UuRWNhcm9uPTYxMTtlLklvZ29uZWs9MzMzO2Uua2NvbW1hYWNjZW50PTUwMDtlLm1pbnVzPTU2NDtlLkljaXJjdW1mbGV4PTMzMztlLm5jYXJvbj01MDA7ZS50Y29tbWFhY2NlbnQ9Mjc4O2UubG9naWNhbG5vdD01NjQ7ZS5vZGllcmVzaXM9NTAwO2UudWRpZXJlc2lzPTUwMDtlLm5vdGVxdWFsPTU0OTtlLmdjb21tYWFjY2VudD01MDA7ZS5ldGg9NTAwO2UuemNhcm9uPTQ0NDtlLm5jb21tYWFjY2VudD01MDA7ZS5vbmVzdXBlcmlvcj0zMDA7ZS5pbWFjcm9uPTI3ODtlLkV1cm89NTAwfSk7ZVsiVGltZXMtQm9sZCJdPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlLnNwYWNlPTI1MDtlLmV4Y2xhbT0zMzM7ZS5xdW90ZWRibD01NTU7ZS5udW1iZXJzaWduPTUwMDtlLmRvbGxhcj01MDA7ZS5wZXJjZW50PTFlMztlLmFtcGVyc2FuZD04MzM7ZS5xdW90ZXJpZ2h0PTMzMztlLnBhcmVubGVmdD0zMzM7ZS5wYXJlbnJpZ2h0PTMzMztlLmFzdGVyaXNrPTUwMDtlLnBsdXM9NTcwO2UuY29tbWE9MjUwO2UuaHlwaGVuPTMzMztlLnBlcmlvZD0yNTA7ZS5zbGFzaD0yNzg7ZS56ZXJvPTUwMDtlLm9uZT01MDA7ZS50d289NTAwO2UudGhyZWU9NTAwO2UuZm91cj01MDA7ZS5maXZlPTUwMDtlLnNpeD01MDA7ZS5zZXZlbj01MDA7ZS5laWdodD01MDA7ZS5uaW5lPTUwMDtlLmNvbG9uPTMzMztlLnNlbWljb2xvbj0zMzM7ZS5sZXNzPTU3MDtlLmVxdWFsPTU3MDtlLmdyZWF0ZXI9NTcwO2UucXVlc3Rpb249NTAwO2UuYXQ9OTMwO2UuQT03MjI7ZS5CPTY2NztlLkM9NzIyO2UuRD03MjI7ZS5FPTY2NztlLkY9NjExO2UuRz03Nzg7ZS5IPTc3ODtlLkk9Mzg5O2UuSj01MDA7ZS5LPTc3ODtlLkw9NjY3O2UuTT05NDQ7ZS5OPTcyMjtlLk89Nzc4O2UuUD02MTE7ZS5RPTc3ODtlLlI9NzIyO2UuUz01NTY7ZS5UPTY2NztlLlU9NzIyO2UuVj03MjI7ZS5XPTFlMztlLlg9NzIyO2UuWT03MjI7ZS5aPTY2NztlLmJyYWNrZXRsZWZ0PTMzMztlLmJhY2tzbGFzaD0yNzg7ZS5icmFja2V0cmlnaHQ9MzMzO2UuYXNjaWljaXJjdW09NTgxO2UudW5kZXJzY29yZT01MDA7ZS5xdW90ZWxlZnQ9MzMzO2UuYT01MDA7ZS5iPTU1NjtlLmM9NDQ0O2UuZD01NTY7ZS5lPTQ0NDtlLmY9MzMzO2UuZz01MDA7ZS5oPTU1NjtlLmk9Mjc4O2Uuaj0zMzM7ZS5rPTU1NjtlLmw9Mjc4O2UubT04MzM7ZS5uPTU1NjtlLm89NTAwO2UucD01NTY7ZS5xPTU1NjtlLnI9NDQ0O2Uucz0zODk7ZS50PTMzMztlLnU9NTU2O2Uudj01MDA7ZS53PTcyMjtlLng9NTAwO2UueT01MDA7ZS56PTQ0NDtlLmJyYWNlbGVmdD0zOTQ7ZS5iYXI9MjIwO2UuYnJhY2VyaWdodD0zOTQ7ZS5hc2NpaXRpbGRlPTUyMDtlLmV4Y2xhbWRvd249MzMzO2UuY2VudD01MDA7ZS5zdGVybGluZz01MDA7ZS5mcmFjdGlvbj0xNjc7ZS55ZW49NTAwO2UuZmxvcmluPTUwMDtlLnNlY3Rpb249NTAwO2UuY3VycmVuY3k9NTAwO2UucXVvdGVzaW5nbGU9Mjc4O2UucXVvdGVkYmxsZWZ0PTUwMDtlLmd1aWxsZW1vdGxlZnQ9NTAwO2UuZ3VpbHNpbmdsbGVmdD0zMzM7ZS5ndWlsc2luZ2xyaWdodD0zMzM7ZS5maT01NTY7ZS5mbD01NTY7ZS5lbmRhc2g9NTAwO2UuZGFnZ2VyPTUwMDtlLmRhZ2dlcmRibD01MDA7ZS5wZXJpb2RjZW50ZXJlZD0yNTA7ZS5wYXJhZ3JhcGg9NTQwO2UuYnVsbGV0PTM1MDtlLnF1b3Rlc2luZ2xiYXNlPTMzMztlLnF1b3RlZGJsYmFzZT01MDA7ZS5xdW90ZWRibHJpZ2h0PTUwMDtlLmd1aWxsZW1vdHJpZ2h0PTUwMDtlLmVsbGlwc2lzPTFlMztlLnBlcnRob3VzYW5kPTFlMztlLnF1ZXN0aW9uZG93bj01MDA7ZS5ncmF2ZT0zMzM7ZS5hY3V0ZT0zMzM7ZS5jaXJjdW1mbGV4PTMzMztlLnRpbGRlPTMzMztlLm1hY3Jvbj0zMzM7ZS5icmV2ZT0zMzM7ZS5kb3RhY2NlbnQ9MzMzO2UuZGllcmVzaXM9MzMzO2UucmluZz0zMzM7ZS5jZWRpbGxhPTMzMztlLmh1bmdhcnVtbGF1dD0zMzM7ZS5vZ29uZWs9MzMzO2UuY2Fyb249MzMzO2UuZW1kYXNoPTFlMztlLkFFPTFlMztlLm9yZGZlbWluaW5lPTMwMDtlLkxzbGFzaD02Njc7ZS5Pc2xhc2g9Nzc4O2UuT0U9MWUzO2Uub3JkbWFzY3VsaW5lPTMzMDtlLmFlPTcyMjtlLmRvdGxlc3NpPTI3ODtlLmxzbGFzaD0yNzg7ZS5vc2xhc2g9NTAwO2Uub2U9NzIyO2UuZ2VybWFuZGJscz01NTY7ZS5JZGllcmVzaXM9Mzg5O2UuZWFjdXRlPTQ0NDtlLmFicmV2ZT01MDA7ZS51aHVuZ2FydW1sYXV0PTU1NjtlLmVjYXJvbj00NDQ7ZS5ZZGllcmVzaXM9NzIyO2UuZGl2aWRlPTU3MDtlLllhY3V0ZT03MjI7ZS5BY2lyY3VtZmxleD03MjI7ZS5hYWN1dGU9NTAwO2UuVWNpcmN1bWZsZXg9NzIyO2UueWFjdXRlPTUwMDtlLnNjb21tYWFjY2VudD0zODk7ZS5lY2lyY3VtZmxleD00NDQ7ZS5VcmluZz03MjI7ZS5VZGllcmVzaXM9NzIyO2UuYW9nb25laz01MDA7ZS5VYWN1dGU9NzIyO2UudW9nb25laz01NTY7ZS5FZGllcmVzaXM9NjY3O2UuRGNyb2F0PTcyMjtlLmNvbW1hYWNjZW50PTI1MDtlLmNvcHlyaWdodD03NDc7ZS5FbWFjcm9uPTY2NztlLmNjYXJvbj00NDQ7ZS5hcmluZz01MDA7ZS5OY29tbWFhY2NlbnQ9NzIyO2UubGFjdXRlPTI3ODtlLmFncmF2ZT01MDA7ZS5UY29tbWFhY2NlbnQ9NjY3O2UuQ2FjdXRlPTcyMjtlLmF0aWxkZT01MDA7ZS5FZG90YWNjZW50PTY2NztlLnNjYXJvbj0zODk7ZS5zY2VkaWxsYT0zODk7ZS5pYWN1dGU9Mjc4O2UubG96ZW5nZT00OTQ7ZS5SY2Fyb249NzIyO2UuR2NvbW1hYWNjZW50PTc3ODtlLnVjaXJjdW1mbGV4PTU1NjtlLmFjaXJjdW1mbGV4PTUwMDtlLkFtYWNyb249NzIyO2UucmNhcm9uPTQ0NDtlLmNjZWRpbGxhPTQ0NDtlLlpkb3RhY2NlbnQ9NjY3O2UuVGhvcm49NjExO2UuT21hY3Jvbj03Nzg7ZS5SYWN1dGU9NzIyO2UuU2FjdXRlPTU1NjtlLmRjYXJvbj02NzI7ZS5VbWFjcm9uPTcyMjtlLnVyaW5nPTU1NjtlLnRocmVlc3VwZXJpb3I9MzAwO2UuT2dyYXZlPTc3ODtlLkFncmF2ZT03MjI7ZS5BYnJldmU9NzIyO2UubXVsdGlwbHk9NTcwO2UudWFjdXRlPTU1NjtlLlRjYXJvbj02Njc7ZS5wYXJ0aWFsZGlmZj00OTQ7ZS55ZGllcmVzaXM9NTAwO2UuTmFjdXRlPTcyMjtlLmljaXJjdW1mbGV4PTI3ODtlLkVjaXJjdW1mbGV4PTY2NztlLmFkaWVyZXNpcz01MDA7ZS5lZGllcmVzaXM9NDQ0O2UuY2FjdXRlPTQ0NDtlLm5hY3V0ZT01NTY7ZS51bWFjcm9uPTU1NjtlLk5jYXJvbj03MjI7ZS5JYWN1dGU9Mzg5O2UucGx1c21pbnVzPTU3MDtlLmJyb2tlbmJhcj0yMjA7ZS5yZWdpc3RlcmVkPTc0NztlLkdicmV2ZT03Nzg7ZS5JZG90YWNjZW50PTM4OTtlLnN1bW1hdGlvbj02MDA7ZS5FZ3JhdmU9NjY3O2UucmFjdXRlPTQ0NDtlLm9tYWNyb249NTAwO2UuWmFjdXRlPTY2NztlLlpjYXJvbj02Njc7ZS5ncmVhdGVyZXF1YWw9NTQ5O2UuRXRoPTcyMjtlLkNjZWRpbGxhPTcyMjtlLmxjb21tYWFjY2VudD0yNzg7ZS50Y2Fyb249NDE2O2UuZW9nb25laz00NDQ7ZS5Vb2dvbmVrPTcyMjtlLkFhY3V0ZT03MjI7ZS5BZGllcmVzaXM9NzIyO2UuZWdyYXZlPTQ0NDtlLnphY3V0ZT00NDQ7ZS5pb2dvbmVrPTI3ODtlLk9hY3V0ZT03Nzg7ZS5vYWN1dGU9NTAwO2UuYW1hY3Jvbj01MDA7ZS5zYWN1dGU9Mzg5O2UuaWRpZXJlc2lzPTI3ODtlLk9jaXJjdW1mbGV4PTc3ODtlLlVncmF2ZT03MjI7ZS5EZWx0YT02MTI7ZS50aG9ybj01NTY7ZS50d29zdXBlcmlvcj0zMDA7ZS5PZGllcmVzaXM9Nzc4O2UubXU9NTU2O2UuaWdyYXZlPTI3ODtlLm9odW5nYXJ1bWxhdXQ9NTAwO2UuRW9nb25laz02Njc7ZS5kY3JvYXQ9NTU2O2UudGhyZWVxdWFydGVycz03NTA7ZS5TY2VkaWxsYT01NTY7ZS5sY2Fyb249Mzk0O2UuS2NvbW1hYWNjZW50PTc3ODtlLkxhY3V0ZT02Njc7ZS50cmFkZW1hcms9MWUzO2UuZWRvdGFjY2VudD00NDQ7ZS5JZ3JhdmU9Mzg5O2UuSW1hY3Jvbj0zODk7ZS5MY2Fyb249NjY3O2Uub25laGFsZj03NTA7ZS5sZXNzZXF1YWw9NTQ5O2Uub2NpcmN1bWZsZXg9NTAwO2UubnRpbGRlPTU1NjtlLlVodW5nYXJ1bWxhdXQ9NzIyO2UuRWFjdXRlPTY2NztlLmVtYWNyb249NDQ0O2UuZ2JyZXZlPTUwMDtlLm9uZXF1YXJ0ZXI9NzUwO2UuU2Nhcm9uPTU1NjtlLlNjb21tYWFjY2VudD01NTY7ZS5PaHVuZ2FydW1sYXV0PTc3ODtlLmRlZ3JlZT00MDA7ZS5vZ3JhdmU9NTAwO2UuQ2Nhcm9uPTcyMjtlLnVncmF2ZT01NTY7ZS5yYWRpY2FsPTU0OTtlLkRjYXJvbj03MjI7ZS5yY29tbWFhY2NlbnQ9NDQ0O2UuTnRpbGRlPTcyMjtlLm90aWxkZT01MDA7ZS5SY29tbWFhY2NlbnQ9NzIyO2UuTGNvbW1hYWNjZW50PTY2NztlLkF0aWxkZT03MjI7ZS5Bb2dvbmVrPTcyMjtlLkFyaW5nPTcyMjtlLk90aWxkZT03Nzg7ZS56ZG90YWNjZW50PTQ0NDtlLkVjYXJvbj02Njc7ZS5Jb2dvbmVrPTM4OTtlLmtjb21tYWFjY2VudD01NTY7ZS5taW51cz01NzA7ZS5JY2lyY3VtZmxleD0zODk7ZS5uY2Fyb249NTU2O2UudGNvbW1hYWNjZW50PTMzMztlLmxvZ2ljYWxub3Q9NTcwO2Uub2RpZXJlc2lzPTUwMDtlLnVkaWVyZXNpcz01NTY7ZS5ub3RlcXVhbD01NDk7ZS5nY29tbWFhY2NlbnQ9NTAwO2UuZXRoPTUwMDtlLnpjYXJvbj00NDQ7ZS5uY29tbWFhY2NlbnQ9NTU2O2Uub25lc3VwZXJpb3I9MzAwO2UuaW1hY3Jvbj0yNzg7ZS5FdXJvPTUwMH0pO2VbIlRpbWVzLUJvbGRJdGFsaWMiXT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNTA7ZS5leGNsYW09Mzg5O2UucXVvdGVkYmw9NTU1O2UubnVtYmVyc2lnbj01MDA7ZS5kb2xsYXI9NTAwO2UucGVyY2VudD04MzM7ZS5hbXBlcnNhbmQ9Nzc4O2UucXVvdGVyaWdodD0zMzM7ZS5wYXJlbmxlZnQ9MzMzO2UucGFyZW5yaWdodD0zMzM7ZS5hc3Rlcmlzaz01MDA7ZS5wbHVzPTU3MDtlLmNvbW1hPTI1MDtlLmh5cGhlbj0zMzM7ZS5wZXJpb2Q9MjUwO2Uuc2xhc2g9Mjc4O2UuemVybz01MDA7ZS5vbmU9NTAwO2UudHdvPTUwMDtlLnRocmVlPTUwMDtlLmZvdXI9NTAwO2UuZml2ZT01MDA7ZS5zaXg9NTAwO2Uuc2V2ZW49NTAwO2UuZWlnaHQ9NTAwO2UubmluZT01MDA7ZS5jb2xvbj0zMzM7ZS5zZW1pY29sb249MzMzO2UubGVzcz01NzA7ZS5lcXVhbD01NzA7ZS5ncmVhdGVyPTU3MDtlLnF1ZXN0aW9uPTUwMDtlLmF0PTgzMjtlLkE9NjY3O2UuQj02Njc7ZS5DPTY2NztlLkQ9NzIyO2UuRT02Njc7ZS5GPTY2NztlLkc9NzIyO2UuSD03Nzg7ZS5JPTM4OTtlLko9NTAwO2UuSz02Njc7ZS5MPTYxMTtlLk09ODg5O2UuTj03MjI7ZS5PPTcyMjtlLlA9NjExO2UuUT03MjI7ZS5SPTY2NztlLlM9NTU2O2UuVD02MTE7ZS5VPTcyMjtlLlY9NjY3O2UuVz04ODk7ZS5YPTY2NztlLlk9NjExO2UuWj02MTE7ZS5icmFja2V0bGVmdD0zMzM7ZS5iYWNrc2xhc2g9Mjc4O2UuYnJhY2tldHJpZ2h0PTMzMztlLmFzY2lpY2lyY3VtPTU3MDtlLnVuZGVyc2NvcmU9NTAwO2UucXVvdGVsZWZ0PTMzMztlLmE9NTAwO2UuYj01MDA7ZS5jPTQ0NDtlLmQ9NTAwO2UuZT00NDQ7ZS5mPTMzMztlLmc9NTAwO2UuaD01NTY7ZS5pPTI3ODtlLmo9Mjc4O2Uuaz01MDA7ZS5sPTI3ODtlLm09Nzc4O2Uubj01NTY7ZS5vPTUwMDtlLnA9NTAwO2UucT01MDA7ZS5yPTM4OTtlLnM9Mzg5O2UudD0yNzg7ZS51PTU1NjtlLnY9NDQ0O2Uudz02Njc7ZS54PTUwMDtlLnk9NDQ0O2Uuej0zODk7ZS5icmFjZWxlZnQ9MzQ4O2UuYmFyPTIyMDtlLmJyYWNlcmlnaHQ9MzQ4O2UuYXNjaWl0aWxkZT01NzA7ZS5leGNsYW1kb3duPTM4OTtlLmNlbnQ9NTAwO2Uuc3Rlcmxpbmc9NTAwO2UuZnJhY3Rpb249MTY3O2UueWVuPTUwMDtlLmZsb3Jpbj01MDA7ZS5zZWN0aW9uPTUwMDtlLmN1cnJlbmN5PTUwMDtlLnF1b3Rlc2luZ2xlPTI3ODtlLnF1b3RlZGJsbGVmdD01MDA7ZS5ndWlsbGVtb3RsZWZ0PTUwMDtlLmd1aWxzaW5nbGxlZnQ9MzMzO2UuZ3VpbHNpbmdscmlnaHQ9MzMzO2UuZmk9NTU2O2UuZmw9NTU2O2UuZW5kYXNoPTUwMDtlLmRhZ2dlcj01MDA7ZS5kYWdnZXJkYmw9NTAwO2UucGVyaW9kY2VudGVyZWQ9MjUwO2UucGFyYWdyYXBoPTUwMDtlLmJ1bGxldD0zNTA7ZS5xdW90ZXNpbmdsYmFzZT0zMzM7ZS5xdW90ZWRibGJhc2U9NTAwO2UucXVvdGVkYmxyaWdodD01MDA7ZS5ndWlsbGVtb3RyaWdodD01MDA7ZS5lbGxpcHNpcz0xZTM7ZS5wZXJ0aG91c2FuZD0xZTM7ZS5xdWVzdGlvbmRvd249NTAwO2UuZ3JhdmU9MzMzO2UuYWN1dGU9MzMzO2UuY2lyY3VtZmxleD0zMzM7ZS50aWxkZT0zMzM7ZS5tYWNyb249MzMzO2UuYnJldmU9MzMzO2UuZG90YWNjZW50PTMzMztlLmRpZXJlc2lzPTMzMztlLnJpbmc9MzMzO2UuY2VkaWxsYT0zMzM7ZS5odW5nYXJ1bWxhdXQ9MzMzO2Uub2dvbmVrPTMzMztlLmNhcm9uPTMzMztlLmVtZGFzaD0xZTM7ZS5BRT05NDQ7ZS5vcmRmZW1pbmluZT0yNjY7ZS5Mc2xhc2g9NjExO2UuT3NsYXNoPTcyMjtlLk9FPTk0NDtlLm9yZG1hc2N1bGluZT0zMDA7ZS5hZT03MjI7ZS5kb3RsZXNzaT0yNzg7ZS5sc2xhc2g9Mjc4O2Uub3NsYXNoPTUwMDtlLm9lPTcyMjtlLmdlcm1hbmRibHM9NTAwO2UuSWRpZXJlc2lzPTM4OTtlLmVhY3V0ZT00NDQ7ZS5hYnJldmU9NTAwO2UudWh1bmdhcnVtbGF1dD01NTY7ZS5lY2Fyb249NDQ0O2UuWWRpZXJlc2lzPTYxMTtlLmRpdmlkZT01NzA7ZS5ZYWN1dGU9NjExO2UuQWNpcmN1bWZsZXg9NjY3O2UuYWFjdXRlPTUwMDtlLlVjaXJjdW1mbGV4PTcyMjtlLnlhY3V0ZT00NDQ7ZS5zY29tbWFhY2NlbnQ9Mzg5O2UuZWNpcmN1bWZsZXg9NDQ0O2UuVXJpbmc9NzIyO2UuVWRpZXJlc2lzPTcyMjtlLmFvZ29uZWs9NTAwO2UuVWFjdXRlPTcyMjtlLnVvZ29uZWs9NTU2O2UuRWRpZXJlc2lzPTY2NztlLkRjcm9hdD03MjI7ZS5jb21tYWFjY2VudD0yNTA7ZS5jb3B5cmlnaHQ9NzQ3O2UuRW1hY3Jvbj02Njc7ZS5jY2Fyb249NDQ0O2UuYXJpbmc9NTAwO2UuTmNvbW1hYWNjZW50PTcyMjtlLmxhY3V0ZT0yNzg7ZS5hZ3JhdmU9NTAwO2UuVGNvbW1hYWNjZW50PTYxMTtlLkNhY3V0ZT02Njc7ZS5hdGlsZGU9NTAwO2UuRWRvdGFjY2VudD02Njc7ZS5zY2Fyb249Mzg5O2Uuc2NlZGlsbGE9Mzg5O2UuaWFjdXRlPTI3ODtlLmxvemVuZ2U9NDk0O2UuUmNhcm9uPTY2NztlLkdjb21tYWFjY2VudD03MjI7ZS51Y2lyY3VtZmxleD01NTY7ZS5hY2lyY3VtZmxleD01MDA7ZS5BbWFjcm9uPTY2NztlLnJjYXJvbj0zODk7ZS5jY2VkaWxsYT00NDQ7ZS5aZG90YWNjZW50PTYxMTtlLlRob3JuPTYxMTtlLk9tYWNyb249NzIyO2UuUmFjdXRlPTY2NztlLlNhY3V0ZT01NTY7ZS5kY2Fyb249NjA4O2UuVW1hY3Jvbj03MjI7ZS51cmluZz01NTY7ZS50aHJlZXN1cGVyaW9yPTMwMDtlLk9ncmF2ZT03MjI7ZS5BZ3JhdmU9NjY3O2UuQWJyZXZlPTY2NztlLm11bHRpcGx5PTU3MDtlLnVhY3V0ZT01NTY7ZS5UY2Fyb249NjExO2UucGFydGlhbGRpZmY9NDk0O2UueWRpZXJlc2lzPTQ0NDtlLk5hY3V0ZT03MjI7ZS5pY2lyY3VtZmxleD0yNzg7ZS5FY2lyY3VtZmxleD02Njc7ZS5hZGllcmVzaXM9NTAwO2UuZWRpZXJlc2lzPTQ0NDtlLmNhY3V0ZT00NDQ7ZS5uYWN1dGU9NTU2O2UudW1hY3Jvbj01NTY7ZS5OY2Fyb249NzIyO2UuSWFjdXRlPTM4OTtlLnBsdXNtaW51cz01NzA7ZS5icm9rZW5iYXI9MjIwO2UucmVnaXN0ZXJlZD03NDc7ZS5HYnJldmU9NzIyO2UuSWRvdGFjY2VudD0zODk7ZS5zdW1tYXRpb249NjAwO2UuRWdyYXZlPTY2NztlLnJhY3V0ZT0zODk7ZS5vbWFjcm9uPTUwMDtlLlphY3V0ZT02MTE7ZS5aY2Fyb249NjExO2UuZ3JlYXRlcmVxdWFsPTU0OTtlLkV0aD03MjI7ZS5DY2VkaWxsYT02Njc7ZS5sY29tbWFhY2NlbnQ9Mjc4O2UudGNhcm9uPTM2NjtlLmVvZ29uZWs9NDQ0O2UuVW9nb25laz03MjI7ZS5BYWN1dGU9NjY3O2UuQWRpZXJlc2lzPTY2NztlLmVncmF2ZT00NDQ7ZS56YWN1dGU9Mzg5O2UuaW9nb25laz0yNzg7ZS5PYWN1dGU9NzIyO2Uub2FjdXRlPTUwMDtlLmFtYWNyb249NTAwO2Uuc2FjdXRlPTM4OTtlLmlkaWVyZXNpcz0yNzg7ZS5PY2lyY3VtZmxleD03MjI7ZS5VZ3JhdmU9NzIyO2UuRGVsdGE9NjEyO2UudGhvcm49NTAwO2UudHdvc3VwZXJpb3I9MzAwO2UuT2RpZXJlc2lzPTcyMjtlLm11PTU3NjtlLmlncmF2ZT0yNzg7ZS5vaHVuZ2FydW1sYXV0PTUwMDtlLkVvZ29uZWs9NjY3O2UuZGNyb2F0PTUwMDtlLnRocmVlcXVhcnRlcnM9NzUwO2UuU2NlZGlsbGE9NTU2O2UubGNhcm9uPTM4MjtlLktjb21tYWFjY2VudD02Njc7ZS5MYWN1dGU9NjExO2UudHJhZGVtYXJrPTFlMztlLmVkb3RhY2NlbnQ9NDQ0O2UuSWdyYXZlPTM4OTtlLkltYWNyb249Mzg5O2UuTGNhcm9uPTYxMTtlLm9uZWhhbGY9NzUwO2UubGVzc2VxdWFsPTU0OTtlLm9jaXJjdW1mbGV4PTUwMDtlLm50aWxkZT01NTY7ZS5VaHVuZ2FydW1sYXV0PTcyMjtlLkVhY3V0ZT02Njc7ZS5lbWFjcm9uPTQ0NDtlLmdicmV2ZT01MDA7ZS5vbmVxdWFydGVyPTc1MDtlLlNjYXJvbj01NTY7ZS5TY29tbWFhY2NlbnQ9NTU2O2UuT2h1bmdhcnVtbGF1dD03MjI7ZS5kZWdyZWU9NDAwO2Uub2dyYXZlPTUwMDtlLkNjYXJvbj02Njc7ZS51Z3JhdmU9NTU2O2UucmFkaWNhbD01NDk7ZS5EY2Fyb249NzIyO2UucmNvbW1hYWNjZW50PTM4OTtlLk50aWxkZT03MjI7ZS5vdGlsZGU9NTAwO2UuUmNvbW1hYWNjZW50PTY2NztlLkxjb21tYWFjY2VudD02MTE7ZS5BdGlsZGU9NjY3O2UuQW9nb25laz02Njc7ZS5BcmluZz02Njc7ZS5PdGlsZGU9NzIyO2UuemRvdGFjY2VudD0zODk7ZS5FY2Fyb249NjY3O2UuSW9nb25laz0zODk7ZS5rY29tbWFhY2NlbnQ9NTAwO2UubWludXM9NjA2O2UuSWNpcmN1bWZsZXg9Mzg5O2UubmNhcm9uPTU1NjtlLnRjb21tYWFjY2VudD0yNzg7ZS5sb2dpY2Fsbm90PTYwNjtlLm9kaWVyZXNpcz01MDA7ZS51ZGllcmVzaXM9NTU2O2Uubm90ZXF1YWw9NTQ5O2UuZ2NvbW1hYWNjZW50PTUwMDtlLmV0aD01MDA7ZS56Y2Fyb249Mzg5O2UubmNvbW1hYWNjZW50PTU1NjtlLm9uZXN1cGVyaW9yPTMwMDtlLmltYWNyb249Mjc4O2UuRXVybz01MDB9KTtlWyJUaW1lcy1JdGFsaWMiXT1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNTA7ZS5leGNsYW09MzMzO2UucXVvdGVkYmw9NDIwO2UubnVtYmVyc2lnbj01MDA7ZS5kb2xsYXI9NTAwO2UucGVyY2VudD04MzM7ZS5hbXBlcnNhbmQ9Nzc4O2UucXVvdGVyaWdodD0zMzM7ZS5wYXJlbmxlZnQ9MzMzO2UucGFyZW5yaWdodD0zMzM7ZS5hc3Rlcmlzaz01MDA7ZS5wbHVzPTY3NTtlLmNvbW1hPTI1MDtlLmh5cGhlbj0zMzM7ZS5wZXJpb2Q9MjUwO2Uuc2xhc2g9Mjc4O2UuemVybz01MDA7ZS5vbmU9NTAwO2UudHdvPTUwMDtlLnRocmVlPTUwMDtlLmZvdXI9NTAwO2UuZml2ZT01MDA7ZS5zaXg9NTAwO2Uuc2V2ZW49NTAwO2UuZWlnaHQ9NTAwO2UubmluZT01MDA7ZS5jb2xvbj0zMzM7ZS5zZW1pY29sb249MzMzO2UubGVzcz02NzU7ZS5lcXVhbD02NzU7ZS5ncmVhdGVyPTY3NTtlLnF1ZXN0aW9uPTUwMDtlLmF0PTkyMDtlLkE9NjExO2UuQj02MTE7ZS5DPTY2NztlLkQ9NzIyO2UuRT02MTE7ZS5GPTYxMTtlLkc9NzIyO2UuSD03MjI7ZS5JPTMzMztlLko9NDQ0O2UuSz02Njc7ZS5MPTU1NjtlLk09ODMzO2UuTj02Njc7ZS5PPTcyMjtlLlA9NjExO2UuUT03MjI7ZS5SPTYxMTtlLlM9NTAwO2UuVD01NTY7ZS5VPTcyMjtlLlY9NjExO2UuVz04MzM7ZS5YPTYxMTtlLlk9NTU2O2UuWj01NTY7ZS5icmFja2V0bGVmdD0zODk7ZS5iYWNrc2xhc2g9Mjc4O2UuYnJhY2tldHJpZ2h0PTM4OTtlLmFzY2lpY2lyY3VtPTQyMjtlLnVuZGVyc2NvcmU9NTAwO2UucXVvdGVsZWZ0PTMzMztlLmE9NTAwO2UuYj01MDA7ZS5jPTQ0NDtlLmQ9NTAwO2UuZT00NDQ7ZS5mPTI3ODtlLmc9NTAwO2UuaD01MDA7ZS5pPTI3ODtlLmo9Mjc4O2Uuaz00NDQ7ZS5sPTI3ODtlLm09NzIyO2Uubj01MDA7ZS5vPTUwMDtlLnA9NTAwO2UucT01MDA7ZS5yPTM4OTtlLnM9Mzg5O2UudD0yNzg7ZS51PTUwMDtlLnY9NDQ0O2Uudz02Njc7ZS54PTQ0NDtlLnk9NDQ0O2Uuej0zODk7ZS5icmFjZWxlZnQ9NDAwO2UuYmFyPTI3NTtlLmJyYWNlcmlnaHQ9NDAwO2UuYXNjaWl0aWxkZT01NDE7ZS5leGNsYW1kb3duPTM4OTtlLmNlbnQ9NTAwO2Uuc3Rlcmxpbmc9NTAwO2UuZnJhY3Rpb249MTY3O2UueWVuPTUwMDtlLmZsb3Jpbj01MDA7ZS5zZWN0aW9uPTUwMDtlLmN1cnJlbmN5PTUwMDtlLnF1b3Rlc2luZ2xlPTIxNDtlLnF1b3RlZGJsbGVmdD01NTY7ZS5ndWlsbGVtb3RsZWZ0PTUwMDtlLmd1aWxzaW5nbGxlZnQ9MzMzO2UuZ3VpbHNpbmdscmlnaHQ9MzMzO2UuZmk9NTAwO2UuZmw9NTAwO2UuZW5kYXNoPTUwMDtlLmRhZ2dlcj01MDA7ZS5kYWdnZXJkYmw9NTAwO2UucGVyaW9kY2VudGVyZWQ9MjUwO2UucGFyYWdyYXBoPTUyMztlLmJ1bGxldD0zNTA7ZS5xdW90ZXNpbmdsYmFzZT0zMzM7ZS5xdW90ZWRibGJhc2U9NTU2O2UucXVvdGVkYmxyaWdodD01NTY7ZS5ndWlsbGVtb3RyaWdodD01MDA7ZS5lbGxpcHNpcz04ODk7ZS5wZXJ0aG91c2FuZD0xZTM7ZS5xdWVzdGlvbmRvd249NTAwO2UuZ3JhdmU9MzMzO2UuYWN1dGU9MzMzO2UuY2lyY3VtZmxleD0zMzM7ZS50aWxkZT0zMzM7ZS5tYWNyb249MzMzO2UuYnJldmU9MzMzO2UuZG90YWNjZW50PTMzMztlLmRpZXJlc2lzPTMzMztlLnJpbmc9MzMzO2UuY2VkaWxsYT0zMzM7ZS5odW5nYXJ1bWxhdXQ9MzMzO2Uub2dvbmVrPTMzMztlLmNhcm9uPTMzMztlLmVtZGFzaD04ODk7ZS5BRT04ODk7ZS5vcmRmZW1pbmluZT0yNzY7ZS5Mc2xhc2g9NTU2O2UuT3NsYXNoPTcyMjtlLk9FPTk0NDtlLm9yZG1hc2N1bGluZT0zMTA7ZS5hZT02Njc7ZS5kb3RsZXNzaT0yNzg7ZS5sc2xhc2g9Mjc4O2Uub3NsYXNoPTUwMDtlLm9lPTY2NztlLmdlcm1hbmRibHM9NTAwO2UuSWRpZXJlc2lzPTMzMztlLmVhY3V0ZT00NDQ7ZS5hYnJldmU9NTAwO2UudWh1bmdhcnVtbGF1dD01MDA7ZS5lY2Fyb249NDQ0O2UuWWRpZXJlc2lzPTU1NjtlLmRpdmlkZT02NzU7ZS5ZYWN1dGU9NTU2O2UuQWNpcmN1bWZsZXg9NjExO2UuYWFjdXRlPTUwMDtlLlVjaXJjdW1mbGV4PTcyMjtlLnlhY3V0ZT00NDQ7ZS5zY29tbWFhY2NlbnQ9Mzg5O2UuZWNpcmN1bWZsZXg9NDQ0O2UuVXJpbmc9NzIyO2UuVWRpZXJlc2lzPTcyMjtlLmFvZ29uZWs9NTAwO2UuVWFjdXRlPTcyMjtlLnVvZ29uZWs9NTAwO2UuRWRpZXJlc2lzPTYxMTtlLkRjcm9hdD03MjI7ZS5jb21tYWFjY2VudD0yNTA7ZS5jb3B5cmlnaHQ9NzYwO2UuRW1hY3Jvbj02MTE7ZS5jY2Fyb249NDQ0O2UuYXJpbmc9NTAwO2UuTmNvbW1hYWNjZW50PTY2NztlLmxhY3V0ZT0yNzg7ZS5hZ3JhdmU9NTAwO2UuVGNvbW1hYWNjZW50PTU1NjtlLkNhY3V0ZT02Njc7ZS5hdGlsZGU9NTAwO2UuRWRvdGFjY2VudD02MTE7ZS5zY2Fyb249Mzg5O2Uuc2NlZGlsbGE9Mzg5O2UuaWFjdXRlPTI3ODtlLmxvemVuZ2U9NDcxO2UuUmNhcm9uPTYxMTtlLkdjb21tYWFjY2VudD03MjI7ZS51Y2lyY3VtZmxleD01MDA7ZS5hY2lyY3VtZmxleD01MDA7ZS5BbWFjcm9uPTYxMTtlLnJjYXJvbj0zODk7ZS5jY2VkaWxsYT00NDQ7ZS5aZG90YWNjZW50PTU1NjtlLlRob3JuPTYxMTtlLk9tYWNyb249NzIyO2UuUmFjdXRlPTYxMTtlLlNhY3V0ZT01MDA7ZS5kY2Fyb249NTQ0O2UuVW1hY3Jvbj03MjI7ZS51cmluZz01MDA7ZS50aHJlZXN1cGVyaW9yPTMwMDtlLk9ncmF2ZT03MjI7ZS5BZ3JhdmU9NjExO2UuQWJyZXZlPTYxMTtlLm11bHRpcGx5PTY3NTtlLnVhY3V0ZT01MDA7ZS5UY2Fyb249NTU2O2UucGFydGlhbGRpZmY9NDc2O2UueWRpZXJlc2lzPTQ0NDtlLk5hY3V0ZT02Njc7ZS5pY2lyY3VtZmxleD0yNzg7ZS5FY2lyY3VtZmxleD02MTE7ZS5hZGllcmVzaXM9NTAwO2UuZWRpZXJlc2lzPTQ0NDtlLmNhY3V0ZT00NDQ7ZS5uYWN1dGU9NTAwO2UudW1hY3Jvbj01MDA7ZS5OY2Fyb249NjY3O2UuSWFjdXRlPTMzMztlLnBsdXNtaW51cz02NzU7ZS5icm9rZW5iYXI9Mjc1O2UucmVnaXN0ZXJlZD03NjA7ZS5HYnJldmU9NzIyO2UuSWRvdGFjY2VudD0zMzM7ZS5zdW1tYXRpb249NjAwO2UuRWdyYXZlPTYxMTtlLnJhY3V0ZT0zODk7ZS5vbWFjcm9uPTUwMDtlLlphY3V0ZT01NTY7ZS5aY2Fyb249NTU2O2UuZ3JlYXRlcmVxdWFsPTU0OTtlLkV0aD03MjI7ZS5DY2VkaWxsYT02Njc7ZS5sY29tbWFhY2NlbnQ9Mjc4O2UudGNhcm9uPTMwMDtlLmVvZ29uZWs9NDQ0O2UuVW9nb25laz03MjI7ZS5BYWN1dGU9NjExO2UuQWRpZXJlc2lzPTYxMTtlLmVncmF2ZT00NDQ7ZS56YWN1dGU9Mzg5O2UuaW9nb25laz0yNzg7ZS5PYWN1dGU9NzIyO2Uub2FjdXRlPTUwMDtlLmFtYWNyb249NTAwO2Uuc2FjdXRlPTM4OTtlLmlkaWVyZXNpcz0yNzg7ZS5PY2lyY3VtZmxleD03MjI7ZS5VZ3JhdmU9NzIyO2UuRGVsdGE9NjEyO2UudGhvcm49NTAwO2UudHdvc3VwZXJpb3I9MzAwO2UuT2RpZXJlc2lzPTcyMjtlLm11PTUwMDtlLmlncmF2ZT0yNzg7ZS5vaHVuZ2FydW1sYXV0PTUwMDtlLkVvZ29uZWs9NjExO2UuZGNyb2F0PTUwMDtlLnRocmVlcXVhcnRlcnM9NzUwO2UuU2NlZGlsbGE9NTAwO2UubGNhcm9uPTMwMDtlLktjb21tYWFjY2VudD02Njc7ZS5MYWN1dGU9NTU2O2UudHJhZGVtYXJrPTk4MDtlLmVkb3RhY2NlbnQ9NDQ0O2UuSWdyYXZlPTMzMztlLkltYWNyb249MzMzO2UuTGNhcm9uPTYxMTtlLm9uZWhhbGY9NzUwO2UubGVzc2VxdWFsPTU0OTtlLm9jaXJjdW1mbGV4PTUwMDtlLm50aWxkZT01MDA7ZS5VaHVuZ2FydW1sYXV0PTcyMjtlLkVhY3V0ZT02MTE7ZS5lbWFjcm9uPTQ0NDtlLmdicmV2ZT01MDA7ZS5vbmVxdWFydGVyPTc1MDtlLlNjYXJvbj01MDA7ZS5TY29tbWFhY2NlbnQ9NTAwO2UuT2h1bmdhcnVtbGF1dD03MjI7ZS5kZWdyZWU9NDAwO2Uub2dyYXZlPTUwMDtlLkNjYXJvbj02Njc7ZS51Z3JhdmU9NTAwO2UucmFkaWNhbD00NTM7ZS5EY2Fyb249NzIyO2UucmNvbW1hYWNjZW50PTM4OTtlLk50aWxkZT02Njc7ZS5vdGlsZGU9NTAwO2UuUmNvbW1hYWNjZW50PTYxMTtlLkxjb21tYWFjY2VudD01NTY7ZS5BdGlsZGU9NjExO2UuQW9nb25laz02MTE7ZS5BcmluZz02MTE7ZS5PdGlsZGU9NzIyO2UuemRvdGFjY2VudD0zODk7ZS5FY2Fyb249NjExO2UuSW9nb25laz0zMzM7ZS5rY29tbWFhY2NlbnQ9NDQ0O2UubWludXM9Njc1O2UuSWNpcmN1bWZsZXg9MzMzO2UubmNhcm9uPTUwMDtlLnRjb21tYWFjY2VudD0yNzg7ZS5sb2dpY2Fsbm90PTY3NTtlLm9kaWVyZXNpcz01MDA7ZS51ZGllcmVzaXM9NTAwO2Uubm90ZXF1YWw9NTQ5O2UuZ2NvbW1hYWNjZW50PTUwMDtlLmV0aD01MDA7ZS56Y2Fyb249Mzg5O2UubmNvbW1hYWNjZW50PTUwMDtlLm9uZXN1cGVyaW9yPTMwMDtlLmltYWNyb249Mjc4O2UuRXVybz01MDB9KTtlLlphcGZEaW5nYmF0cz1nZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24oZSl7ZS5zcGFjZT0yNzg7ZS5hMT05NzQ7ZS5hMj05NjE7ZS5hMjAyPTk3NDtlLmEzPTk4MDtlLmE0PTcxOTtlLmE1PTc4OTtlLmExMTk9NzkwO2UuYTExOD03OTE7ZS5hMTE3PTY5MDtlLmExMT05NjA7ZS5hMTI9OTM5O2UuYTEzPTU0OTtlLmExND04NTU7ZS5hMTU9OTExO2UuYTE2PTkzMztlLmExMDU9OTExO2UuYTE3PTk0NTtlLmExOD05NzQ7ZS5hMTk9NzU1O2UuYTIwPTg0NjtlLmEyMT03NjI7ZS5hMjI9NzYxO2UuYTIzPTU3MTtlLmEyND02Nzc7ZS5hMjU9NzYzO2UuYTI2PTc2MDtlLmEyNz03NTk7ZS5hMjg9NzU0O2UuYTY9NDk0O2UuYTc9NTUyO2UuYTg9NTM3O2UuYTk9NTc3O2UuYTEwPTY5MjtlLmEyOT03ODY7ZS5hMzA9Nzg4O2UuYTMxPTc4ODtlLmEzMj03OTA7ZS5hMzM9NzkzO2UuYTM0PTc5NDtlLmEzNT04MTY7ZS5hMzY9ODIzO2UuYTM3PTc4OTtlLmEzOD04NDE7ZS5hMzk9ODIzO2UuYTQwPTgzMztlLmE0MT04MTY7ZS5hNDI9ODMxO2UuYTQzPTkyMztlLmE0ND03NDQ7ZS5hNDU9NzIzO2UuYTQ2PTc0OTtlLmE0Nz03OTA7ZS5hNDg9NzkyO2UuYTQ5PTY5NTtlLmE1MD03NzY7ZS5hNTE9NzY4O2UuYTUyPTc5MjtlLmE1Mz03NTk7ZS5hNTQ9NzA3O2UuYTU1PTcwODtlLmE1Nj02ODI7ZS5hNTc9NzAxO2UuYTU4PTgyNjtlLmE1OT04MTU7ZS5hNjA9Nzg5O2UuYTYxPTc4OTtlLmE2Mj03MDc7ZS5hNjM9Njg3O2UuYTY0PTY5NjtlLmE2NT02ODk7ZS5hNjY9Nzg2O2UuYTY3PTc4NztlLmE2OD03MTM7ZS5hNjk9NzkxO2UuYTcwPTc4NTtlLmE3MT03OTE7ZS5hNzI9ODczO2UuYTczPTc2MTtlLmE3ND03NjI7ZS5hMjAzPTc2MjtlLmE3NT03NTk7ZS5hMjA0PTc1OTtlLmE3Nj04OTI7ZS5hNzc9ODkyO2UuYTc4PTc4ODtlLmE3OT03ODQ7ZS5hODE9NDM4O2UuYTgyPTEzODtlLmE4Mz0yNzc7ZS5hODQ9NDE1O2UuYTk3PTM5MjtlLmE5OD0zOTI7ZS5hOTk9NjY4O2UuYTEwMD02Njg7ZS5hODk9MzkwO2UuYTkwPTM5MDtlLmE5Mz0zMTc7ZS5hOTQ9MzE3O2UuYTkxPTI3NjtlLmE5Mj0yNzY7ZS5hMjA1PTUwOTtlLmE4NT01MDk7ZS5hMjA2PTQxMDtlLmE4Nj00MTA7ZS5hODc9MjM0O2UuYTg4PTIzNDtlLmE5NT0zMzQ7ZS5hOTY9MzM0O2UuYTEwMT03MzI7ZS5hMTAyPTU0NDtlLmExMDM9NTQ0O2UuYTEwND05MTA7ZS5hMTA2PTY2NztlLmExMDc9NzYwO2UuYTEwOD03NjA7ZS5hMTEyPTc3NjtlLmExMTE9NTk1O2UuYTExMD02OTQ7ZS5hMTA5PTYyNjtlLmExMjA9Nzg4O2UuYTEyMT03ODg7ZS5hMTIyPTc4ODtlLmExMjM9Nzg4O2UuYTEyND03ODg7ZS5hMTI1PTc4ODtlLmExMjY9Nzg4O2UuYTEyNz03ODg7ZS5hMTI4PTc4ODtlLmExMjk9Nzg4O2UuYTEzMD03ODg7ZS5hMTMxPTc4ODtlLmExMzI9Nzg4O2UuYTEzMz03ODg7ZS5hMTM0PTc4ODtlLmExMzU9Nzg4O2UuYTEzNj03ODg7ZS5hMTM3PTc4ODtlLmExMzg9Nzg4O2UuYTEzOT03ODg7ZS5hMTQwPTc4ODtlLmExNDE9Nzg4O2UuYTE0Mj03ODg7ZS5hMTQzPTc4ODtlLmExNDQ9Nzg4O2UuYTE0NT03ODg7ZS5hMTQ2PTc4ODtlLmExNDc9Nzg4O2UuYTE0OD03ODg7ZS5hMTQ5PTc4ODtlLmExNTA9Nzg4O2UuYTE1MT03ODg7ZS5hMTUyPTc4ODtlLmExNTM9Nzg4O2UuYTE1ND03ODg7ZS5hMTU1PTc4ODtlLmExNTY9Nzg4O2UuYTE1Nz03ODg7ZS5hMTU4PTc4ODtlLmExNTk9Nzg4O2UuYTE2MD04OTQ7ZS5hMTYxPTgzODtlLmExNjM9MTAxNjtlLmExNjQ9NDU4O2UuYTE5Nj03NDg7ZS5hMTY1PTkyNDtlLmExOTI9NzQ4O2UuYTE2Nj05MTg7ZS5hMTY3PTkyNztlLmExNjg9OTI4O2UuYTE2OT05Mjg7ZS5hMTcwPTgzNDtlLmExNzE9ODczO2UuYTE3Mj04Mjg7ZS5hMTczPTkyNDtlLmExNjI9OTI0O2UuYTE3ND05MTc7ZS5hMTc1PTkzMDtlLmExNzY9OTMxO2UuYTE3Nz00NjM7ZS5hMTc4PTg4MztlLmExNzk9ODM2O2UuYTE5Mz04MzY7ZS5hMTgwPTg2NztlLmExOTk9ODY3O2UuYTE4MT02OTY7ZS5hMjAwPTY5NjtlLmExODI9ODc0O2UuYTIwMT04NzQ7ZS5hMTgzPTc2MDtlLmExODQ9OTQ2O2UuYTE5Nz03NzE7ZS5hMTg1PTg2NTtlLmExOTQ9NzcxO2UuYTE5OD04ODg7ZS5hMTg2PTk2NztlLmExOTU9ODg4O2UuYTE4Nz04MzE7ZS5hMTg4PTg3MztlLmExODk9OTI3O2UuYTE5MD05NzA7ZS5hMTkxPTkxOH0pfSksR2E9Z2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uKGUpe2UuQ291cmllcj17YXNjZW50OjYyOSxkZXNjZW50Oi0xNTcsY2FwSGVpZ2h0OjU2Mix4SGVpZ2h0Oi00MjZ9O2VbIkNvdXJpZXItQm9sZCJdPXthc2NlbnQ6NjI5LGRlc2NlbnQ6LTE1NyxjYXBIZWlnaHQ6NTYyLHhIZWlnaHQ6NDM5fTtlWyJDb3VyaWVyLU9ibGlxdWUiXT17YXNjZW50OjYyOSxkZXNjZW50Oi0xNTcsY2FwSGVpZ2h0OjU2Mix4SGVpZ2h0OjQyNn07ZVsiQ291cmllci1Cb2xkT2JsaXF1ZSJdPXthc2NlbnQ6NjI5LGRlc2NlbnQ6LTE1NyxjYXBIZWlnaHQ6NTYyLHhIZWlnaHQ6NDI2fTtlLkhlbHZldGljYT17YXNjZW50OjcxOCxkZXNjZW50Oi0yMDcsY2FwSGVpZ2h0OjcxOCx4SGVpZ2h0OjUyM307ZVsiSGVsdmV0aWNhLUJvbGQiXT17YXNjZW50OjcxOCxkZXNjZW50Oi0yMDcsY2FwSGVpZ2h0OjcxOCx4SGVpZ2h0OjUzMn07ZVsiSGVsdmV0aWNhLU9ibGlxdWUiXT17YXNjZW50OjcxOCxkZXNjZW50Oi0yMDcsY2FwSGVpZ2h0OjcxOCx4SGVpZ2h0OjUyM307ZVsiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIl09e2FzY2VudDo3MTgsZGVzY2VudDotMjA3LGNhcEhlaWdodDo3MTgseEhlaWdodDo1MzJ9O2VbIlRpbWVzLVJvbWFuIl09e2FzY2VudDo2ODMsZGVzY2VudDotMjE3LGNhcEhlaWdodDo2NjIseEhlaWdodDo0NTB9O2VbIlRpbWVzLUJvbGQiXT17YXNjZW50OjY4MyxkZXNjZW50Oi0yMTcsY2FwSGVpZ2h0OjY3Nix4SGVpZ2h0OjQ2MX07ZVsiVGltZXMtSXRhbGljIl09e2FzY2VudDo2ODMsZGVzY2VudDotMjE3LGNhcEhlaWdodDo2NTMseEhlaWdodDo0NDF9O2VbIlRpbWVzLUJvbGRJdGFsaWMiXT17YXNjZW50OjY4MyxkZXNjZW50Oi0yMTcsY2FwSGVpZ2h0OjY2OSx4SGVpZ2h0OjQ2Mn07ZS5TeW1ib2w9e2FzY2VudDpNYXRoLk5hTixkZXNjZW50Ok1hdGguTmFOLGNhcEhlaWdodDpNYXRoLk5hTix4SGVpZ2h0Ok1hdGguTmFOfTtlLlphcGZEaW5nYmF0cz17YXNjZW50Ok1hdGguTmFOLGRlc2NlbnQ6TWF0aC5OYU4sY2FwSGVpZ2h0Ok1hdGguTmFOLHhIZWlnaHQ6TWF0aC5OYU59fSk7Y2xhc3MgR2x5ZlRhYmxle2NvbnN0cnVjdG9yKHtnbHlmVGFibGU6ZSxpc0dseXBoTG9jYXRpb25zTG9uZzp0LGxvY2FUYWJsZTpyLG51bUdseXBoczphfSl7dGhpcy5nbHlwaHM9W107Y29uc3Qgbj1uZXcgRGF0YVZpZXcoci5idWZmZXIsci5ieXRlT2Zmc2V0LHIuYnl0ZUxlbmd0aCksaT1uZXcgRGF0YVZpZXcoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCkscz10PzQ6MjtsZXQgbz10P24uZ2V0VWludDMyKDApOjIqbi5nZXRVaW50MTYoMCksYz0wO2ZvcihsZXQgZT0wO2U8YTtlKyspe2MrPXM7Y29uc3QgZT10P24uZ2V0VWludDMyKGMpOjIqbi5nZXRVaW50MTYoYyk7aWYoZT09PW8pe3RoaXMuZ2x5cGhzLnB1c2gobmV3IEdseXBoKHt9KSk7Y29udGludWV9Y29uc3Qgcj1HbHlwaC5wYXJzZShvLGkpO3RoaXMuZ2x5cGhzLnB1c2gocik7bz1lfX1nZXRTaXplKCl7cmV0dXJuIE1hdGguc3VtUHJlY2lzZSh0aGlzLmdseXBocy5tYXAoZT0+ZS5nZXRTaXplKCkrMyYtNCkpfXdyaXRlKCl7Y29uc3QgZT10aGlzLmdldFNpemUoKSx0PW5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoZSkpLHI9ZT4xMzEwNzAsYT1yPzQ6MixuPW5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoKHRoaXMuZ2x5cGhzLmxlbmd0aCsxKSphKSk7cj9uLnNldFVpbnQzMigwLDApOm4uc2V0VWludDE2KDAsMCk7bGV0IGk9MCxzPTA7Zm9yKGNvbnN0IGUgb2YgdGhpcy5nbHlwaHMpe2krPWUud3JpdGUoaSx0KTtpPWkrMyYtNDtzKz1hO3I/bi5zZXRVaW50MzIocyxpKTpuLnNldFVpbnQxNihzLGk+PjEpfXJldHVybntpc0xvY2F0aW9uTG9uZzpyLGxvY2E6bmV3IFVpbnQ4QXJyYXkobi5idWZmZXIpLGdseWY6bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIpfX1zY2FsZShlKXtmb3IobGV0IHQ9MCxyPXRoaXMuZ2x5cGhzLmxlbmd0aDt0PHI7dCsrKXRoaXMuZ2x5cGhzW3RdLnNjYWxlKGVbdF0pfX1jbGFzcyBHbHlwaHtjb25zdHJ1Y3Rvcih7aGVhZGVyOmU9bnVsbCxzaW1wbGU6dD1udWxsLGNvbXBvc2l0ZXM6cj1udWxsfSl7dGhpcy5oZWFkZXI9ZTt0aGlzLnNpbXBsZT10O3RoaXMuY29tcG9zaXRlcz1yfXN0YXRpYyBwYXJzZShlLHQpe2NvbnN0W3IsYV09R2x5cGhIZWFkZXIucGFyc2UoZSx0KTtlKz1yO2lmKGEubnVtYmVyT2ZDb250b3VyczwwKXtjb25zdCByPVtdO2Zvcig7Oyl7Y29uc3RbYSxuXT1Db21wb3NpdGVHbHlwaC5wYXJzZShlLHQpO2UrPWE7ci5wdXNoKG4pO2lmKCEoMzImbi5mbGFncykpYnJlYWt9cmV0dXJuIG5ldyBHbHlwaCh7aGVhZGVyOmEsY29tcG9zaXRlczpyfSl9Y29uc3Qgbj1TaW1wbGVHbHlwaC5wYXJzZShlLHQsYS5udW1iZXJPZkNvbnRvdXJzKTtyZXR1cm4gbmV3IEdseXBoKHtoZWFkZXI6YSxzaW1wbGU6bn0pfWdldFNpemUoKXtpZighdGhpcy5oZWFkZXIpcmV0dXJuIDA7Y29uc3QgZT10aGlzLnNpbXBsZT90aGlzLnNpbXBsZS5nZXRTaXplKCk6TWF0aC5zdW1QcmVjaXNlKHRoaXMuY29tcG9zaXRlcy5tYXAoZT0+ZS5nZXRTaXplKCkpKTtyZXR1cm4gdGhpcy5oZWFkZXIuZ2V0U2l6ZSgpK2V9d3JpdGUoZSx0KXtpZighdGhpcy5oZWFkZXIpcmV0dXJuIDA7Y29uc3Qgcj1lO2UrPXRoaXMuaGVhZGVyLndyaXRlKGUsdCk7aWYodGhpcy5zaW1wbGUpZSs9dGhpcy5zaW1wbGUud3JpdGUoZSx0KTtlbHNlIGZvcihjb25zdCByIG9mIHRoaXMuY29tcG9zaXRlcyllKz1yLndyaXRlKGUsdCk7cmV0dXJuIGUtcn1zY2FsZShlKXtpZighdGhpcy5oZWFkZXIpcmV0dXJuO2NvbnN0IHQ9KHRoaXMuaGVhZGVyLnhNaW4rdGhpcy5oZWFkZXIueE1heCkvMjt0aGlzLmhlYWRlci5zY2FsZSh0LGUpO2lmKHRoaXMuc2ltcGxlKXRoaXMuc2ltcGxlLnNjYWxlKHQsZSk7ZWxzZSBmb3IoY29uc3QgciBvZiB0aGlzLmNvbXBvc2l0ZXMpci5zY2FsZSh0LGUpfX1jbGFzcyBHbHlwaEhlYWRlcntjb25zdHJ1Y3Rvcih7bnVtYmVyT2ZDb250b3VyczplLHhNaW46dCx5TWluOnIseE1heDphLHlNYXg6bn0pe3RoaXMubnVtYmVyT2ZDb250b3Vycz1lO3RoaXMueE1pbj10O3RoaXMueU1pbj1yO3RoaXMueE1heD1hO3RoaXMueU1heD1ufXN0YXRpYyBwYXJzZShlLHQpe3JldHVyblsxMCxuZXcgR2x5cGhIZWFkZXIoe251bWJlck9mQ29udG91cnM6dC5nZXRJbnQxNihlKSx4TWluOnQuZ2V0SW50MTYoZSsyKSx5TWluOnQuZ2V0SW50MTYoZSs0KSx4TWF4OnQuZ2V0SW50MTYoZSs2KSx5TWF4OnQuZ2V0SW50MTYoZSs4KX0pXX1nZXRTaXplKCl7cmV0dXJuIDEwfXdyaXRlKGUsdCl7dC5zZXRJbnQxNihlLHRoaXMubnVtYmVyT2ZDb250b3Vycyk7dC5zZXRJbnQxNihlKzIsdGhpcy54TWluKTt0LnNldEludDE2KGUrNCx0aGlzLnlNaW4pO3Quc2V0SW50MTYoZSs2LHRoaXMueE1heCk7dC5zZXRJbnQxNihlKzgsdGhpcy55TWF4KTtyZXR1cm4gMTB9c2NhbGUoZSx0KXt0aGlzLnhNaW49TWF0aC5yb3VuZChlKyh0aGlzLnhNaW4tZSkqdCk7dGhpcy54TWF4PU1hdGgucm91bmQoZSsodGhpcy54TWF4LWUpKnQpfX1jbGFzcyBDb250b3Vye2NvbnN0cnVjdG9yKHtmbGFnczplLHhDb29yZGluYXRlczp0LHlDb29yZGluYXRlczpyfSl7dGhpcy54Q29vcmRpbmF0ZXM9dDt0aGlzLnlDb29yZGluYXRlcz1yO3RoaXMuZmxhZ3M9ZX19Y2xhc3MgU2ltcGxlR2x5cGh7Y29uc3RydWN0b3Ioe2NvbnRvdXJzOmUsaW5zdHJ1Y3Rpb25zOnR9KXt0aGlzLmNvbnRvdXJzPWU7dGhpcy5pbnN0cnVjdGlvbnM9dH1zdGF0aWMgcGFyc2UoZSx0LHIpe2NvbnN0IGE9W107Zm9yKGxldCBuPTA7bjxyO24rKyl7Y29uc3Qgcj10LmdldFVpbnQxNihlKTtlKz0yO2EucHVzaChyKX1jb25zdCBuPWFbci0xXSsxLGk9dC5nZXRVaW50MTYoZSk7ZSs9Mjtjb25zdCBzPW5ldyBVaW50OEFycmF5KHQpLnNsaWNlKGUsZStpKTtlKz1pO2NvbnN0IG89W107Zm9yKGxldCByPTA7cjxuO2UrKyxyKyspe2xldCBhPXQuZ2V0VWludDgoZSk7by5wdXNoKGEpO2lmKDgmYSl7Y29uc3Qgbj10LmdldFVpbnQ4KCsrZSk7YV49ODtmb3IobGV0IGU9MDtlPG47ZSsrKW8ucHVzaChhKTtyKz1ufX1jb25zdCBjPVtdO2xldCBsPVtdLGg9W10sdT1bXTtjb25zdCBkPVtdO2xldCBmPTAsZz0wO2ZvcihsZXQgcj0wO3I8bjtyKyspe2NvbnN0IG49b1tyXTtpZigyJm4pe2NvbnN0IHI9dC5nZXRVaW50OChlKyspO2crPTE2Jm4/cjotcjtsLnB1c2goZyl9ZWxzZSBpZigxNiZuKWwucHVzaChnKTtlbHNle2crPXQuZ2V0SW50MTYoZSk7ZSs9MjtsLnB1c2goZyl9aWYoYVtmXT09PXIpe2YrKztjLnB1c2gobCk7bD1bXX19Zz0wO2Y9MDtmb3IobGV0IHI9MDtyPG47cisrKXtjb25zdCBuPW9bcl07aWYoNCZuKXtjb25zdCByPXQuZ2V0VWludDgoZSsrKTtnKz0zMiZuP3I6LXI7aC5wdXNoKGcpfWVsc2UgaWYoMzImbiloLnB1c2goZyk7ZWxzZXtnKz10LmdldEludDE2KGUpO2UrPTI7aC5wdXNoKGcpfXUucHVzaCgxJm58NjQmbik7aWYoYVtmXT09PXIpe2w9Y1tmXTtmKys7ZC5wdXNoKG5ldyBDb250b3VyKHtmbGFnczp1LHhDb29yZGluYXRlczpsLHlDb29yZGluYXRlczpofSkpO2g9W107dT1bXX19cmV0dXJuIG5ldyBTaW1wbGVHbHlwaCh7Y29udG91cnM6ZCxpbnN0cnVjdGlvbnM6c30pfWdldFNpemUoKXtsZXQgZT0yKnRoaXMuY29udG91cnMubGVuZ3RoKzIrdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoLHQ9MCxyPTA7Zm9yKGNvbnN0IGEgb2YgdGhpcy5jb250b3Vycyl7ZSs9YS5mbGFncy5sZW5ndGg7Zm9yKGxldCBuPTAsaT1hLnhDb29yZGluYXRlcy5sZW5ndGg7bjxpO24rKyl7Y29uc3QgaT1hLnhDb29yZGluYXRlc1tuXSxzPWEueUNvb3JkaW5hdGVzW25dO2xldCBvPU1hdGguYWJzKGktdCk7bz4yNTU/ZSs9MjpvPjAmJihlKz0xKTt0PWk7bz1NYXRoLmFicyhzLXIpO28+MjU1P2UrPTI6bz4wJiYoZSs9MSk7cj1zfX1yZXR1cm4gZX13cml0ZShlLHQpe2NvbnN0IHI9ZSxhPVtdLG49W10saT1bXTtsZXQgcz0wLG89MDtmb3IoY29uc3QgciBvZiB0aGlzLmNvbnRvdXJzKXtmb3IobGV0IGU9MCx0PXIueENvb3JkaW5hdGVzLmxlbmd0aDtlPHQ7ZSsrKXtsZXQgdD1yLmZsYWdzW2VdO2NvbnN0IGM9ci54Q29vcmRpbmF0ZXNbZV07bGV0IGw9Yy1zO2lmKDA9PT1sKXt0fD0xNjthLnB1c2goMCl9ZWxzZXtjb25zdCBlPU1hdGguYWJzKGwpO2lmKGU8PTI1NSl7dHw9bD49MD8xODoyO2EucHVzaChlKX1lbHNlIGEucHVzaChsKX1zPWM7Y29uc3QgaD1yLnlDb29yZGluYXRlc1tlXTtsPWgtbztpZigwPT09bCl7dHw9MzI7bi5wdXNoKDApfWVsc2V7Y29uc3QgZT1NYXRoLmFicyhsKTtpZihlPD0yNTUpe3R8PWw+PTA/MzY6NDtuLnB1c2goZSl9ZWxzZSBuLnB1c2gobCl9bz1oO2kucHVzaCh0KX10LnNldFVpbnQxNihlLGEubGVuZ3RoLTEpO2UrPTJ9dC5zZXRVaW50MTYoZSx0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpO2UrPTI7aWYodGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKXtuZXcgVWludDhBcnJheSh0LmJ1ZmZlciwwLHQuYnVmZmVyLmJ5dGVMZW5ndGgpLnNldCh0aGlzLmluc3RydWN0aW9ucyxlKTtlKz10aGlzLmluc3RydWN0aW9ucy5sZW5ndGh9Zm9yKGNvbnN0IHIgb2YgaSl0LnNldFVpbnQ4KGUrKyxyKTtmb3IobGV0IHI9MCxuPWEubGVuZ3RoO3I8bjtyKyspe2NvbnN0IG49YVtyXSxzPWlbcl07aWYoMiZzKXQuc2V0VWludDgoZSsrLG4pO2Vsc2UgaWYoISgxNiZzKSl7dC5zZXRJbnQxNihlLG4pO2UrPTJ9fWZvcihsZXQgcj0wLGE9bi5sZW5ndGg7cjxhO3IrKyl7Y29uc3QgYT1uW3JdLHM9aVtyXTtpZig0JnMpdC5zZXRVaW50OChlKyssYSk7ZWxzZSBpZighKDMyJnMpKXt0LnNldEludDE2KGUsYSk7ZSs9Mn19cmV0dXJuIGUtcn1zY2FsZShlLHQpe2Zvcihjb25zdCByIG9mIHRoaXMuY29udG91cnMpaWYoMCE9PXIueENvb3JkaW5hdGVzLmxlbmd0aClmb3IobGV0IGE9MCxuPXIueENvb3JkaW5hdGVzLmxlbmd0aDthPG47YSsrKXIueENvb3JkaW5hdGVzW2FdPU1hdGgucm91bmQoZSsoci54Q29vcmRpbmF0ZXNbYV0tZSkqdCl9fWNsYXNzIENvbXBvc2l0ZUdseXBoe2NvbnN0cnVjdG9yKHtmbGFnczplLGdseXBoSW5kZXg6dCxhcmd1bWVudDE6cixhcmd1bWVudDI6YSx0cmFuc2Y6bixpbnN0cnVjdGlvbnM6aX0pe3RoaXMuZmxhZ3M9ZTt0aGlzLmdseXBoSW5kZXg9dDt0aGlzLmFyZ3VtZW50MT1yO3RoaXMuYXJndW1lbnQyPWE7dGhpcy50cmFuc2Y9bjt0aGlzLmluc3RydWN0aW9ucz1pfXN0YXRpYyBwYXJzZShlLHQpe2NvbnN0IHI9ZSxhPVtdO2xldCBuPXQuZ2V0VWludDE2KGUpO2NvbnN0IGk9dC5nZXRVaW50MTYoZSsyKTtlKz00O2xldCBzLG87aWYoMSZuKXtpZigyJm4pe3M9dC5nZXRJbnQxNihlKTtvPXQuZ2V0SW50MTYoZSsyKX1lbHNle3M9dC5nZXRVaW50MTYoZSk7bz10LmdldFVpbnQxNihlKzIpfWUrPTQ7bl49MX1lbHNle2lmKDImbil7cz10LmdldEludDgoZSk7bz10LmdldEludDgoZSsxKX1lbHNle3M9dC5nZXRVaW50OChlKTtvPXQuZ2V0VWludDgoZSsxKX1lKz0yfWlmKDgmbil7YS5wdXNoKHQuZ2V0VWludDE2KGUpKTtlKz0yfWVsc2UgaWYoNjQmbil7YS5wdXNoKHQuZ2V0VWludDE2KGUpLHQuZ2V0VWludDE2KGUrMikpO2UrPTR9ZWxzZSBpZigxMjgmbil7YS5wdXNoKHQuZ2V0VWludDE2KGUpLHQuZ2V0VWludDE2KGUrMiksdC5nZXRVaW50MTYoZSs0KSx0LmdldFVpbnQxNihlKzYpKTtlKz04fWxldCBjPW51bGw7aWYoMjU2Jm4pe2NvbnN0IHI9dC5nZXRVaW50MTYoZSk7ZSs9MjtjPW5ldyBVaW50OEFycmF5KHQpLnNsaWNlKGUsZStyKTtlKz1yfXJldHVybltlLXIsbmV3IENvbXBvc2l0ZUdseXBoKHtmbGFnczpuLGdseXBoSW5kZXg6aSxhcmd1bWVudDE6cyxhcmd1bWVudDI6byx0cmFuc2Y6YSxpbnN0cnVjdGlvbnM6Y30pXX1nZXRTaXplKCl7bGV0IGU9NCsyKnRoaXMudHJhbnNmLmxlbmd0aDsyNTYmdGhpcy5mbGFncyYmKGUrPTIrdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTtlKz0yOzImdGhpcy5mbGFncz90aGlzLmFyZ3VtZW50MT49LTEyOCYmdGhpcy5hcmd1bWVudDE8PTEyNyYmdGhpcy5hcmd1bWVudDI+PS0xMjgmJnRoaXMuYXJndW1lbnQyPD0xMjd8fChlKz0yKTp0aGlzLmFyZ3VtZW50MT49MCYmdGhpcy5hcmd1bWVudDE8PTI1NSYmdGhpcy5hcmd1bWVudDI+PTAmJnRoaXMuYXJndW1lbnQyPD0yNTV8fChlKz0yKTtyZXR1cm4gZX13cml0ZShlLHQpe2NvbnN0IHI9ZTsyJnRoaXMuZmxhZ3M/dGhpcy5hcmd1bWVudDE+PS0xMjgmJnRoaXMuYXJndW1lbnQxPD0xMjcmJnRoaXMuYXJndW1lbnQyPj0tMTI4JiZ0aGlzLmFyZ3VtZW50Mjw9MTI3fHwodGhpcy5mbGFnc3w9MSk6dGhpcy5hcmd1bWVudDE+PTAmJnRoaXMuYXJndW1lbnQxPD0yNTUmJnRoaXMuYXJndW1lbnQyPj0wJiZ0aGlzLmFyZ3VtZW50Mjw9MjU1fHwodGhpcy5mbGFnc3w9MSk7dC5zZXRVaW50MTYoZSx0aGlzLmZsYWdzKTt0LnNldFVpbnQxNihlKzIsdGhpcy5nbHlwaEluZGV4KTtlKz00O2lmKDEmdGhpcy5mbGFncyl7aWYoMiZ0aGlzLmZsYWdzKXt0LnNldEludDE2KGUsdGhpcy5hcmd1bWVudDEpO3Quc2V0SW50MTYoZSsyLHRoaXMuYXJndW1lbnQyKX1lbHNle3Quc2V0VWludDE2KGUsdGhpcy5hcmd1bWVudDEpO3Quc2V0VWludDE2KGUrMix0aGlzLmFyZ3VtZW50Mil9ZSs9NH1lbHNle3Quc2V0VWludDgoZSx0aGlzLmFyZ3VtZW50MSk7dC5zZXRVaW50OChlKzEsdGhpcy5hcmd1bWVudDIpO2UrPTJ9aWYoMjU2JnRoaXMuZmxhZ3Mpe3Quc2V0VWludDE2KGUsdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTtlKz0yO2lmKHRoaXMuaW5zdHJ1Y3Rpb25zLmxlbmd0aCl7bmV3IFVpbnQ4QXJyYXkodC5idWZmZXIsMCx0LmJ1ZmZlci5ieXRlTGVuZ3RoKS5zZXQodGhpcy5pbnN0cnVjdGlvbnMsZSk7ZSs9dGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RofX1yZXR1cm4gZS1yfXNjYWxlKGUsdCl7fX1mdW5jdGlvbiB3cml0ZUludDE2KGUsdCxyKXtlW3RdPXI+PjgmMjU1O2VbdCsxXT0yNTUmcn1mdW5jdGlvbiB3cml0ZUludDMyKGUsdCxyKXtlW3RdPXI+PjI0JjI1NTtlW3QrMV09cj4+MTYmMjU1O2VbdCsyXT1yPj44JjI1NTtlW3QrM109MjU1JnJ9ZnVuY3Rpb24gd3JpdGVEYXRhKGUsdCxyKXtpZihyIGluc3RhbmNlb2YgVWludDhBcnJheSllLnNldChyLHQpO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiByKWZvcihsZXQgYT0wLG49ci5sZW5ndGg7YTxuO2ErKyllW3QrK109MjU1JnIuY2hhckNvZGVBdChhKTtlbHNlIGZvcihjb25zdCBhIG9mIHIpZVt0KytdPTI1NSZhfWNsYXNzIE9wZW5UeXBlRmlsZUJ1aWxkZXJ7Y29uc3RydWN0b3IoZSl7dGhpcy5zZm50PWU7dGhpcy50YWJsZXM9T2JqZWN0LmNyZWF0ZShudWxsKX1zdGF0aWMgZ2V0U2VhcmNoUGFyYW1zKGUsdCl7bGV0IHI9MSxhPTA7Zm9yKDsocl5lKT5yOyl7cjw8PTE7YSsrfWNvbnN0IG49cip0O3JldHVybntyYW5nZTpuLGVudHJ5OmEscmFuZ2VTaGlmdDp0KmUtbn19dG9BcnJheSgpe2xldCBlPXRoaXMuc2ZudDtjb25zdCB0PXRoaXMudGFibGVzLHI9T2JqZWN0LmtleXModCk7ci5zb3J0KCk7Y29uc3QgYT1yLmxlbmd0aDtsZXQgbixpLHMsbyxjLGw9MTIrMTYqYTtjb25zdCBoPVtsXTtmb3Iobj0wO248YTtuKyspe289dFtyW25dXTtsKz0oby5sZW5ndGgrMyYtNCk+Pj4wO2gucHVzaChsKX1jb25zdCB1PW5ldyBVaW50OEFycmF5KGwpO2ZvcihuPTA7bjxhO24rKyl7bz10W3Jbbl1dO3dyaXRlRGF0YSh1LGhbbl0sbyl9InRydWUiPT09ZSYmKGU9c3RyaW5nMzIoNjU1MzYpKTt1WzBdPTI1NSZlLmNoYXJDb2RlQXQoMCk7dVsxXT0yNTUmZS5jaGFyQ29kZUF0KDEpO3VbMl09MjU1JmUuY2hhckNvZGVBdCgyKTt1WzNdPTI1NSZlLmNoYXJDb2RlQXQoMyk7d3JpdGVJbnQxNih1LDQsYSk7Y29uc3QgZD1PcGVuVHlwZUZpbGVCdWlsZGVyLmdldFNlYXJjaFBhcmFtcyhhLDE2KTt3cml0ZUludDE2KHUsNixkLnJhbmdlKTt3cml0ZUludDE2KHUsOCxkLmVudHJ5KTt3cml0ZUludDE2KHUsMTAsZC5yYW5nZVNoaWZ0KTtsPTEyO2ZvcihuPTA7bjxhO24rKyl7Yz1yW25dO3VbbF09MjU1JmMuY2hhckNvZGVBdCgwKTt1W2wrMV09MjU1JmMuY2hhckNvZGVBdCgxKTt1W2wrMl09MjU1JmMuY2hhckNvZGVBdCgyKTt1W2wrM109MjU1JmMuY2hhckNvZGVBdCgzKTtsZXQgZT0wO2ZvcihpPWhbbl0scz1oW24rMV07aTxzO2krPTQpe2U9ZStyZWFkVWludDMyKHUsaSk+Pj4wfXdyaXRlSW50MzIodSxsKzQsZSk7d3JpdGVJbnQzMih1LGwrOCxoW25dKTt3cml0ZUludDMyKHUsbCsxMix0W2NdLmxlbmd0aCk7bCs9MTZ9cmV0dXJuIHV9YWRkVGFibGUoZSx0KXtpZihlIGluIHRoaXMudGFibGVzKXRocm93IG5ldyBFcnJvcigiVGFibGUgIitlKyIgYWxyZWFkeSBleGlzdHMiKTt0aGlzLnRhYmxlc1tlXT10fX1jb25zdCAkYT1bNF0sVmE9WzVdLEthPVs2XSxKYT1bN10sWWE9WzhdLFphPVsxMiwzNV0sUWE9WzE0XSxlbj1bMjFdLHRuPVsyMl0scm49WzMwXSxhbj1bMzFdO2NsYXNzIFR5cGUxQ2hhclN0cmluZ3tjb25zdHJ1Y3Rvcigpe3RoaXMud2lkdGg9MDt0aGlzLmxzYj0wO3RoaXMuZmxleGluZz0hMTt0aGlzLm91dHB1dD1bXTt0aGlzLnN0YWNrPVtdfWNvbnZlcnQoZSx0LHIpe2NvbnN0IGE9ZS5sZW5ndGg7bGV0IG4saSxzLG89ITE7Zm9yKGxldCBjPTA7YzxhO2MrKyl7bGV0IGE9ZVtjXTtpZihhPDMyKXsxMj09PWEmJihhPShhPDw4KStlWysrY10pO3N3aXRjaChhKXtjYXNlIDE6Y2FzZSAzOmNhc2UgOTpjYXNlIDMwNzI6Y2FzZSAzMDczOmNhc2UgMzA3NDpjYXNlIDMxMDU6dGhpcy5zdGFjaz1bXTticmVhaztjYXNlIDQ6aWYodGhpcy5mbGV4aW5nKXtpZih0aGlzLnN0YWNrLmxlbmd0aDwxKXtvPSEwO2JyZWFrfWNvbnN0IGU9dGhpcy5zdGFjay5wb3AoKTt0aGlzLnN0YWNrLnB1c2goMCxlKTticmVha31vPXRoaXMuZXhlY3V0ZUNvbW1hbmQoMSwkYSk7YnJlYWs7Y2FzZSA1Om89dGhpcy5leGVjdXRlQ29tbWFuZCgyLFZhKTticmVhaztjYXNlIDY6bz10aGlzLmV4ZWN1dGVDb21tYW5kKDEsS2EpO2JyZWFrO2Nhc2UgNzpvPXRoaXMuZXhlY3V0ZUNvbW1hbmQoMSxKYSk7YnJlYWs7Y2FzZSA4Om89dGhpcy5leGVjdXRlQ29tbWFuZCg2LFlhKTticmVhaztjYXNlIDEwOmlmKHRoaXMuc3RhY2subGVuZ3RoPDEpe289ITA7YnJlYWt9cz10aGlzLnN0YWNrLnBvcCgpO2lmKCF0W3NdKXtvPSEwO2JyZWFrfW89dGhpcy5jb252ZXJ0KHRbc10sdCxyKTticmVhaztjYXNlIDExOnJldHVybiBvO2Nhc2UgMTM6aWYodGhpcy5zdGFjay5sZW5ndGg8Mil7bz0hMDticmVha31uPXRoaXMuc3RhY2sucG9wKCk7aT10aGlzLnN0YWNrLnBvcCgpO3RoaXMubHNiPWk7dGhpcy53aWR0aD1uO3RoaXMuc3RhY2sucHVzaChuLGkpO289dGhpcy5leGVjdXRlQ29tbWFuZCgyLHRuKTticmVhaztjYXNlIDE0OnRoaXMub3V0cHV0LnB1c2goUWFbMF0pO2JyZWFrO2Nhc2UgMjE6aWYodGhpcy5mbGV4aW5nKWJyZWFrO289dGhpcy5leGVjdXRlQ29tbWFuZCgyLGVuKTticmVhaztjYXNlIDIyOmlmKHRoaXMuZmxleGluZyl7dGhpcy5zdGFjay5wdXNoKDApO2JyZWFrfW89dGhpcy5leGVjdXRlQ29tbWFuZCgxLHRuKTticmVhaztjYXNlIDMwOm89dGhpcy5leGVjdXRlQ29tbWFuZCg0LHJuKTticmVhaztjYXNlIDMxOm89dGhpcy5leGVjdXRlQ29tbWFuZCg0LGFuKTticmVhaztjYXNlIDMwNzg6aWYocil7Y29uc3QgZT10aGlzLnN0YWNrLmF0KC01KTt0aGlzLnNlYWM9dGhpcy5zdGFjay5zcGxpY2UoLTQsNCk7dGhpcy5zZWFjWzBdKz10aGlzLmxzYi1lO289dGhpcy5leGVjdXRlQ29tbWFuZCgwLFFhKX1lbHNlIG89dGhpcy5leGVjdXRlQ29tbWFuZCg0LFFhKTticmVhaztjYXNlIDMwNzk6aWYodGhpcy5zdGFjay5sZW5ndGg8NCl7bz0hMDticmVha310aGlzLnN0YWNrLnBvcCgpO249dGhpcy5zdGFjay5wb3AoKTtjb25zdCBlPXRoaXMuc3RhY2sucG9wKCk7aT10aGlzLnN0YWNrLnBvcCgpO3RoaXMubHNiPWk7dGhpcy53aWR0aD1uO3RoaXMuc3RhY2sucHVzaChuLGksZSk7bz10aGlzLmV4ZWN1dGVDb21tYW5kKDMsZW4pO2JyZWFrO2Nhc2UgMzA4NDppZih0aGlzLnN0YWNrLmxlbmd0aDwyKXtvPSEwO2JyZWFrfWNvbnN0IGM9dGhpcy5zdGFjay5wb3AoKSxsPXRoaXMuc3RhY2sucG9wKCk7dGhpcy5zdGFjay5wdXNoKGwvYyk7YnJlYWs7Y2FzZSAzMDg4OmlmKHRoaXMuc3RhY2subGVuZ3RoPDIpe289ITA7YnJlYWt9cz10aGlzLnN0YWNrLnBvcCgpO2NvbnN0IGg9dGhpcy5zdGFjay5wb3AoKTtpZigwPT09cyYmMz09PWgpe2NvbnN0IGU9dGhpcy5zdGFjay5zcGxpY2UoLTE3LDE3KTt0aGlzLnN0YWNrLnB1c2goZVsyXStlWzBdLGVbM10rZVsxXSxlWzRdLGVbNV0sZVs2XSxlWzddLGVbOF0sZVs5XSxlWzEwXSxlWzExXSxlWzEyXSxlWzEzXSxlWzE0XSk7bz10aGlzLmV4ZWN1dGVDb21tYW5kKDEzLFphLCEwKTt0aGlzLmZsZXhpbmc9ITE7dGhpcy5zdGFjay5wdXNoKGVbMTVdLGVbMTZdKX1lbHNlIDE9PT1zJiYwPT09aCYmKHRoaXMuZmxleGluZz0hMCk7YnJlYWs7Y2FzZSAzMDg5OmJyZWFrO2RlZmF1bHQ6d2FybignVW5rbm93biB0eXBlIDEgY2hhcnN0cmluZyBjb21tYW5kIG9mICInK2ErJyInKX1pZihvKWJyZWFrfWVsc2V7YTw9MjQ2P2EtPTEzOTphPWE8PTI1MD8yNTYqKGEtMjQ3KStlWysrY10rMTA4OmE8PTI1ND8tMjU2KihhLTI1MSktZVsrK2NdLTEwODooMjU1JmVbKytjXSk8PDI0fCgyNTUmZVsrK2NdKTw8MTZ8KDI1NSZlWysrY10pPDw4fDI1NSZlWysrY107dGhpcy5zdGFjay5wdXNoKGEpfX1yZXR1cm4gb31leGVjdXRlQ29tbWFuZChlLHQscil7Y29uc3QgYT10aGlzLnN0YWNrLmxlbmd0aDtpZihlPmEpcmV0dXJuITA7Y29uc3Qgbj1hLWU7Zm9yKGxldCBlPW47ZTxhO2UrKyl7bGV0IHQ9dGhpcy5zdGFja1tlXTtpZihOdW1iZXIuaXNJbnRlZ2VyKHQpKXRoaXMub3V0cHV0LnB1c2goMjgsdD4+OCYyNTUsMjU1JnQpO2Vsc2V7dD02NTUzNip0fDA7dGhpcy5vdXRwdXQucHVzaCgyNTUsdD4+MjQmMjU1LHQ+PjE2JjI1NSx0Pj44JjI1NSwyNTUmdCl9fXRoaXMub3V0cHV0LnB1c2goLi4udCk7cj90aGlzLnN0YWNrLnNwbGljZShuLGUpOnRoaXMuc3RhY2subGVuZ3RoPTA7cmV0dXJuITF9fWZ1bmN0aW9uIGlzSGV4RGlnaXQoZSl7cmV0dXJuIGU+PTQ4JiZlPD01N3x8ZT49NjUmJmU8PTcwfHxlPj05NyYmZTw9MTAyfWZ1bmN0aW9uIGRlY3J5cHQoZSx0LHIpe2lmKHI+PWUubGVuZ3RoKXJldHVybiBuZXcgVWludDhBcnJheSgwKTtsZXQgYSxuLGk9MHx0O2ZvcihhPTA7YTxyO2ErKylpPTUyODQ1KihlW2FdK2kpKzIyNzE5JjY1NTM1O2NvbnN0IHM9ZS5sZW5ndGgtcixvPW5ldyBVaW50OEFycmF5KHMpO2ZvcihhPXIsbj0wO248czthKyssbisrKXtjb25zdCB0PWVbYV07b1tuXT10Xmk+Pjg7aT01Mjg0NSoodCtpKSsyMjcxOSY2NTUzNX1yZXR1cm4gb31mdW5jdGlvbiBpc1NwZWNpYWwoZSl7cmV0dXJuIDQ3PT09ZXx8OTE9PT1lfHw5Mz09PWV8fDEyMz09PWV8fDEyNT09PWV8fDQwPT09ZXx8NDE9PT1lfWNsYXNzIFR5cGUxUGFyc2Vye2NvbnN0cnVjdG9yKGUsdCxyKXtpZih0KXtjb25zdCB0PWUuZ2V0Qnl0ZXMoKSxyPSEoKGlzSGV4RGlnaXQodFswXSl8fGlzV2hpdGVTcGFjZSh0WzBdKSkmJmlzSGV4RGlnaXQodFsxXSkmJmlzSGV4RGlnaXQodFsyXSkmJmlzSGV4RGlnaXQodFszXSkmJmlzSGV4RGlnaXQodFs0XSkmJmlzSGV4RGlnaXQodFs1XSkmJmlzSGV4RGlnaXQodFs2XSkmJmlzSGV4RGlnaXQodFs3XSkpO2U9bmV3IFN0cmVhbShyP2RlY3J5cHQodCw1NTY2NSw0KTpmdW5jdGlvbiBkZWNyeXB0QXNjaWkoZSx0LHIpe2xldCBhPTB8dDtjb25zdCBuPWUubGVuZ3RoLGk9bmV3IFVpbnQ4QXJyYXkobj4+PjEpO2xldCBzLG87Zm9yKHM9MCxvPTA7czxuO3MrKyl7Y29uc3QgdD1lW3NdO2lmKCFpc0hleERpZ2l0KHQpKWNvbnRpbnVlO3MrKztsZXQgcjtmb3IoO3M8biYmIWlzSGV4RGlnaXQocj1lW3NdKTspcysrO2lmKHM8bil7Y29uc3QgZT1wYXJzZUludChTdHJpbmcuZnJvbUNoYXJDb2RlKHQsciksMTYpO2lbbysrXT1lXmE+Pjg7YT01Mjg0NSooZSthKSsyMjcxOSY2NTUzNX19cmV0dXJuIGkuc2xpY2UocixvKX0odCw1NTY2NSw0KSl9dGhpcy5zZWFjQW5hbHlzaXNFbmFibGVkPSEhcjt0aGlzLnN0cmVhbT1lO3RoaXMubmV4dENoYXIoKX1yZWFkTnVtYmVyQXJyYXkoKXt0aGlzLmdldFRva2VuKCk7Y29uc3QgZT1bXTtmb3IoOzspe2NvbnN0IHQ9dGhpcy5nZXRUb2tlbigpO2lmKG51bGw9PT10fHwiXSI9PT10fHwifSI9PT10KWJyZWFrO2UucHVzaChwYXJzZUZsb2F0KHR8fDApKX1yZXR1cm4gZX1yZWFkTnVtYmVyKCl7Y29uc3QgZT10aGlzLmdldFRva2VuKCk7cmV0dXJuIHBhcnNlRmxvYXQoZXx8MCl9cmVhZEludCgpe2NvbnN0IGU9dGhpcy5nZXRUb2tlbigpO3JldHVybiAwfHBhcnNlSW50KGV8fDAsMTApfXJlYWRCb29sZWFuKCl7cmV0dXJuInRydWUiPT09dGhpcy5nZXRUb2tlbigpPzE6MH1uZXh0Q2hhcigpe3JldHVybiB0aGlzLmN1cnJlbnRDaGFyPXRoaXMuc3RyZWFtLmdldEJ5dGUoKX1wcmV2Q2hhcigpe3RoaXMuc3RyZWFtLnNraXAoLTIpO3JldHVybiB0aGlzLmN1cnJlbnRDaGFyPXRoaXMuc3RyZWFtLmdldEJ5dGUoKX1nZXRUb2tlbigpe2xldCBlPSExLHQ9dGhpcy5jdXJyZW50Q2hhcjtmb3IoOzspe2lmKC0xPT09dClyZXR1cm4gbnVsbDtpZihlKTEwIT09dCYmMTMhPT10fHwoZT0hMSk7ZWxzZSBpZigzNz09PXQpZT0hMDtlbHNlIGlmKCFpc1doaXRlU3BhY2UodCkpYnJlYWs7dD10aGlzLm5leHRDaGFyKCl9aWYoaXNTcGVjaWFsKHQpKXt0aGlzLm5leHRDaGFyKCk7cmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodCl9bGV0IHI9IiI7ZG97cis9U3RyaW5nLmZyb21DaGFyQ29kZSh0KTt0PXRoaXMubmV4dENoYXIoKX13aGlsZSh0Pj0wJiYhaXNXaGl0ZVNwYWNlKHQpJiYhaXNTcGVjaWFsKHQpKTtyZXR1cm4gcn1yZWFkQ2hhclN0cmluZ3MoZSx0KXtyZXR1cm4tMT09PXQ/ZTpkZWNyeXB0KGUsNDMzMCx0KX1leHRyYWN0Rm9udFByb2dyYW0oZSl7Y29uc3QgdD10aGlzLnN0cmVhbSxyPVtdLGE9W10sbj1PYmplY3QuY3JlYXRlKG51bGwpO24ubGVuSVY9NDtjb25zdCBpPXtzdWJyczpbXSxjaGFyc3RyaW5nczpbXSxwcm9wZXJ0aWVzOntwcml2YXRlRGF0YTpufX07bGV0IHMsbyxjLGw7Zm9yKDtudWxsIT09KHM9dGhpcy5nZXRUb2tlbigpKTspaWYoIi8iPT09cyl7cz10aGlzLmdldFRva2VuKCk7c3dpdGNoKHMpe2Nhc2UiQ2hhclN0cmluZ3MiOnRoaXMuZ2V0VG9rZW4oKTt0aGlzLmdldFRva2VuKCk7dGhpcy5nZXRUb2tlbigpO3RoaXMuZ2V0VG9rZW4oKTtmb3IoOzspe3M9dGhpcy5nZXRUb2tlbigpO2lmKG51bGw9PT1zfHwiZW5kIj09PXMpYnJlYWs7aWYoIi8iIT09cyljb250aW51ZTtjb25zdCBlPXRoaXMuZ2V0VG9rZW4oKTtvPXRoaXMucmVhZEludCgpO3RoaXMuZ2V0VG9rZW4oKTtjPW8+MD90LmdldEJ5dGVzKG8pOm5ldyBVaW50OEFycmF5KDApO2w9aS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhLmxlbklWO2NvbnN0IHI9dGhpcy5yZWFkQ2hhclN0cmluZ3MoYyxsKTt0aGlzLm5leHRDaGFyKCk7cz10aGlzLmdldFRva2VuKCk7Im5vYWNjZXNzIj09PXM/dGhpcy5nZXRUb2tlbigpOiIvIj09PXMmJnRoaXMucHJldkNoYXIoKTthLnB1c2goe2dseXBoOmUsZW5jb2RlZDpyfSl9YnJlYWs7Y2FzZSJTdWJycyI6dGhpcy5yZWFkSW50KCk7dGhpcy5nZXRUb2tlbigpO2Zvcig7ImR1cCI9PT10aGlzLmdldFRva2VuKCk7KXtjb25zdCBlPXRoaXMucmVhZEludCgpO289dGhpcy5yZWFkSW50KCk7dGhpcy5nZXRUb2tlbigpO2M9bz4wP3QuZ2V0Qnl0ZXMobyk6bmV3IFVpbnQ4QXJyYXkoMCk7bD1pLnByb3BlcnRpZXMucHJpdmF0ZURhdGEubGVuSVY7Y29uc3QgYT10aGlzLnJlYWRDaGFyU3RyaW5ncyhjLGwpO3RoaXMubmV4dENoYXIoKTtzPXRoaXMuZ2V0VG9rZW4oKTsibm9hY2Nlc3MiPT09cyYmdGhpcy5nZXRUb2tlbigpO3JbZV09YX1icmVhaztjYXNlIkJsdWVWYWx1ZXMiOmNhc2UiT3RoZXJCbHVlcyI6Y2FzZSJGYW1pbHlCbHVlcyI6Y2FzZSJGYW1pbHlPdGhlckJsdWVzIjpjb25zdCBlPXRoaXMucmVhZE51bWJlckFycmF5KCk7ZS5sZW5ndGg+MCYmZS5sZW5ndGgsMDticmVhaztjYXNlIlN0ZW1TbmFwSCI6Y2FzZSJTdGVtU25hcFYiOmkucHJvcGVydGllcy5wcml2YXRlRGF0YVtzXT10aGlzLnJlYWROdW1iZXJBcnJheSgpO2JyZWFrO2Nhc2UiU3RkSFciOmNhc2UiU3RkVlciOmkucHJvcGVydGllcy5wcml2YXRlRGF0YVtzXT10aGlzLnJlYWROdW1iZXJBcnJheSgpWzBdO2JyZWFrO2Nhc2UiQmx1ZVNoaWZ0IjpjYXNlImxlbklWIjpjYXNlIkJsdWVGdXp6IjpjYXNlIkJsdWVTY2FsZSI6Y2FzZSJMYW5ndWFnZUdyb3VwIjppLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbc109dGhpcy5yZWFkTnVtYmVyKCk7YnJlYWs7Y2FzZSJFeHBhbnNpb25GYWN0b3IiOmkucHJvcGVydGllcy5wcml2YXRlRGF0YVtzXT10aGlzLnJlYWROdW1iZXIoKXx8LjA2O2JyZWFrO2Nhc2UiRm9yY2VCb2xkIjppLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbc109dGhpcy5yZWFkQm9vbGVhbigpfX1mb3IoY29uc3R7ZW5jb2RlZDp0LGdseXBoOm59b2YgYSl7Y29uc3QgYT1uZXcgVHlwZTFDaGFyU3RyaW5nLHM9YS5jb252ZXJ0KHQscix0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQpO2xldCBvPWEub3V0cHV0O3MmJihvPVsxNF0pO2NvbnN0IGM9e2dseXBoTmFtZTpuLGNoYXJzdHJpbmc6byx3aWR0aDphLndpZHRoLGxzYjphLmxzYixzZWFjOmEuc2VhY307Ii5ub3RkZWYiPT09bj9pLmNoYXJzdHJpbmdzLnVuc2hpZnQoYyk6aS5jaGFyc3RyaW5ncy5wdXNoKGMpO2lmKGUuYnVpbHRJbkVuY29kaW5nKXtjb25zdCB0PWUuYnVpbHRJbkVuY29kaW5nLmluZGV4T2Yobik7dD4tMSYmdm9pZCAwPT09ZS53aWR0aHNbdF0mJnQ+PWUuZmlyc3RDaGFyJiZ0PD1lLmxhc3RDaGFyJiYoZS53aWR0aHNbdF09YS53aWR0aCl9fXJldHVybiBpfWV4dHJhY3RGb250SGVhZGVyKGUpe2xldCB0O2Zvcig7bnVsbCE9PSh0PXRoaXMuZ2V0VG9rZW4oKSk7KWlmKCIvIj09PXQpe3Q9dGhpcy5nZXRUb2tlbigpO3N3aXRjaCh0KXtjYXNlIkZvbnRNYXRyaXgiOmNvbnN0IHI9dGhpcy5yZWFkTnVtYmVyQXJyYXkoKTtlLmZvbnRNYXRyaXg9cjticmVhaztjYXNlIkVuY29kaW5nIjpjb25zdCBhPXRoaXMuZ2V0VG9rZW4oKTtsZXQgbjtpZigvXlxkKyQvLnRlc3QoYSkpe249W107Y29uc3QgZT0wfHBhcnNlSW50KGEsMTApO3RoaXMuZ2V0VG9rZW4oKTtmb3IobGV0IHI9MDtyPGU7cisrKXt0PXRoaXMuZ2V0VG9rZW4oKTtmb3IoOyJkdXAiIT09dCYmImRlZiIhPT10Oyl7dD10aGlzLmdldFRva2VuKCk7aWYobnVsbD09PXQpcmV0dXJufWlmKCJkZWYiPT09dClicmVhaztjb25zdCBlPXRoaXMucmVhZEludCgpO3RoaXMuZ2V0VG9rZW4oKTtjb25zdCByPXRoaXMuZ2V0VG9rZW4oKTtuW2VdPXI7dGhpcy5nZXRUb2tlbigpfX1lbHNlIG49Z2V0RW5jb2RpbmcoYSk7ZS5idWlsdEluRW5jb2Rpbmc9bjticmVhaztjYXNlIkZvbnRCQm94Ijpjb25zdCBpPXRoaXMucmVhZE51bWJlckFycmF5KCk7ZS5hc2NlbnQ9TWF0aC5tYXgoaVszXSxpWzFdKTtlLmRlc2NlbnQ9TWF0aC5taW4oaVsxXSxpWzNdKTtlLmFzY2VudFNjYWxlZD0hMH19fX1mdW5jdGlvbiBmaW5kQmxvY2soZSx0LHIpe2NvbnN0IGE9ZS5sZW5ndGgsbj10Lmxlbmd0aCxpPWEtbjtsZXQgcz1yLG89ITE7Zm9yKDtzPGk7KXtsZXQgcj0wO2Zvcig7cjxuJiZlW3Mrcl09PT10W3JdOylyKys7aWYocj49bil7cys9cjtmb3IoO3M8YSYmaXNXaGl0ZVNwYWNlKGVbc10pOylzKys7bz0hMDticmVha31zKyt9cmV0dXJue2ZvdW5kOm8sbGVuZ3RoOnN9fWNsYXNzIFR5cGUxRm9udHtjb25zdHJ1Y3RvcihlLHQscil7bGV0IGE9ci5sZW5ndGgxLG49ci5sZW5ndGgyLGk9dC5wZWVrQnl0ZXMoNik7Y29uc3Qgcz0xMjg9PT1pWzBdJiYxPT09aVsxXTtpZihzKXt0LnNraXAoNik7YT1pWzVdPDwyNHxpWzRdPDwxNnxpWzNdPDw4fGlbMl19Y29uc3Qgbz1mdW5jdGlvbiBnZXRIZWFkZXJCbG9jayhlLHQpe2NvbnN0IHI9WzEwMSwxMDEsMTIwLDEwMSw5OV0sYT1lLnBvcztsZXQgbixpLHMsbzt0cnl7bj1lLmdldEJ5dGVzKHQpO2k9bi5sZW5ndGh9Y2F0Y2h7fWlmKGk9PT10KXtzPWZpbmRCbG9jayhuLHIsdC0yKnIubGVuZ3RoKTtpZihzLmZvdW5kJiZzLmxlbmd0aD09PXQpcmV0dXJue3N0cmVhbTpuZXcgU3RyZWFtKG4pLGxlbmd0aDp0fX13YXJuKCdJbnZhbGlkICJMZW5ndGgxIiBwcm9wZXJ0eSBpbiBUeXBlMSBmb250IC0tIHRyeWluZyB0byByZWNvdmVyLicpO2UucG9zPWE7Zm9yKDs7KXtzPWZpbmRCbG9jayhlLnBlZWtCeXRlcygyMDQ4KSxyLDApO2lmKDA9PT1zLmxlbmd0aClicmVhaztlLnBvcys9cy5sZW5ndGg7aWYocy5mb3VuZCl7bz1lLnBvcy1hO2JyZWFrfX1lLnBvcz1hO2lmKG8pcmV0dXJue3N0cmVhbTpuZXcgU3RyZWFtKGUuZ2V0Qnl0ZXMobykpLGxlbmd0aDpvfTt3YXJuKCdVbmFibGUgdG8gcmVjb3ZlciAiTGVuZ3RoMSIgcHJvcGVydHkgaW4gVHlwZTEgZm9udCAtLSB1c2luZyBhcyBpcy4nKTtyZXR1cm57c3RyZWFtOm5ldyBTdHJlYW0oZS5nZXRCeXRlcyh0KSksbGVuZ3RoOnR9fSh0LGEpO25ldyBUeXBlMVBhcnNlcihvLnN0cmVhbSwhMSx4YSkuZXh0cmFjdEZvbnRIZWFkZXIocik7aWYocyl7aT10LmdldEJ5dGVzKDYpO249aVs1XTw8MjR8aVs0XTw8MTZ8aVszXTw8OHxpWzJdfWNvbnN0IGM9ZnVuY3Rpb24gZ2V0RWV4ZWNCbG9jayhlLHQpe2NvbnN0IHI9ZS5nZXRCeXRlcygpO2lmKDA9PT1yLmxlbmd0aCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImdldEVleGVjQmxvY2sgLSBubyBmb250IHByb2dyYW0gZm91bmQuIik7cmV0dXJue3N0cmVhbTpuZXcgU3RyZWFtKHIpLGxlbmd0aDpyLmxlbmd0aH19KHQpLGw9bmV3IFR5cGUxUGFyc2VyKGMuc3RyZWFtLCEwLHhhKS5leHRyYWN0Rm9udFByb2dyYW0ocik7Zm9yKGNvbnN0IGUgaW4gbC5wcm9wZXJ0aWVzKXJbZV09bC5wcm9wZXJ0aWVzW2VdO2NvbnN0IGg9bC5jaGFyc3RyaW5ncyx1PXRoaXMuZ2V0VHlwZTJDaGFyc3RyaW5ncyhoKSxkPXRoaXMuZ2V0VHlwZTJTdWJycyhsLnN1YnJzKTt0aGlzLmNoYXJzdHJpbmdzPWg7dGhpcy5kYXRhPXRoaXMud3JhcChlLHUsdGhpcy5jaGFyc3RyaW5ncyxkLHIpO3RoaXMuc2VhY3M9dGhpcy5nZXRTZWFjcyhsLmNoYXJzdHJpbmdzKX1nZXQgbnVtR2x5cGhzKCl7cmV0dXJuIHRoaXMuY2hhcnN0cmluZ3MubGVuZ3RoKzF9Z2V0Q2hhcnNldCgpe2NvbnN0IGU9WyIubm90ZGVmIl07Zm9yKGNvbnN0e2dseXBoTmFtZTp0fW9mIHRoaXMuY2hhcnN0cmluZ3MpZS5wdXNoKHQpO3JldHVybiBlfWdldEdseXBoTWFwcGluZyhlKXtjb25zdCB0PXRoaXMuY2hhcnN0cmluZ3M7aWYoZS5jb21wb3NpdGUpe2NvbnN0IHI9T2JqZWN0LmNyZWF0ZShudWxsKTtmb3IobGV0IGE9MCxuPXQubGVuZ3RoO2E8bjthKyspe3JbZS5jTWFwLmNoYXJDb2RlT2YoYSldPWErMX1yZXR1cm4gcn1jb25zdCByPVsiLm5vdGRlZiJdO2xldCBhLG47Zm9yKG49MDtuPHQubGVuZ3RoO24rKylyLnB1c2godFtuXS5nbHlwaE5hbWUpO2NvbnN0IGk9ZS5idWlsdEluRW5jb2Rpbmc7aWYoaSl7YT1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcihjb25zdCBlIGluIGkpe249ci5pbmRleE9mKGlbZV0pO24+PTAmJihhW2VdPW4pfX1yZXR1cm4gdHlwZTFGb250R2x5cGhNYXBwaW5nKGUsYSxyKX1oYXNHbHlwaElkKGUpe2lmKGU8MHx8ZT49dGhpcy5udW1HbHlwaHMpcmV0dXJuITE7aWYoMD09PWUpcmV0dXJuITA7cmV0dXJuIHRoaXMuY2hhcnN0cmluZ3NbZS0xXS5jaGFyc3RyaW5nLmxlbmd0aD4wfWdldFNlYWNzKGUpe2NvbnN0IHQ9W107Zm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7cisrKXtjb25zdCBhPWVbcl07YS5zZWFjJiYodFtyKzFdPWEuc2VhYyl9cmV0dXJuIHR9Z2V0VHlwZTJDaGFyc3RyaW5ncyhlKXtjb25zdCB0PVtdO2Zvcihjb25zdCByIG9mIGUpdC5wdXNoKHIuY2hhcnN0cmluZyk7cmV0dXJuIHR9Z2V0VHlwZTJTdWJycyhlKXtsZXQgdD0wO2NvbnN0IHI9ZS5sZW5ndGg7dD1yPDExMzM/MTA3OnI8MzM3Njk/MTEzMTozMjc2ODtjb25zdCBhPVtdO2xldCBuO2ZvcihuPTA7bjx0O24rKylhLnB1c2goWzExXSk7Zm9yKG49MDtuPHI7bisrKWEucHVzaChlW25dKTtyZXR1cm4gYX13cmFwKGUsdCxyLGEsbil7Y29uc3QgaT1uZXcgQ0ZGO2kuaGVhZGVyPW5ldyBDRkZIZWFkZXIoMSwwLDQsNCk7aS5uYW1lcz1bZV07Y29uc3Qgcz1uZXcgQ0ZGVG9wRGljdDtzLnNldEJ5TmFtZSgidmVyc2lvbiIsMzkxKTtzLnNldEJ5TmFtZSgiTm90aWNlIiwzOTIpO3Muc2V0QnlOYW1lKCJGdWxsTmFtZSIsMzkzKTtzLnNldEJ5TmFtZSgiRmFtaWx5TmFtZSIsMzk0KTtzLnNldEJ5TmFtZSgiV2VpZ2h0IiwzOTUpO3Muc2V0QnlOYW1lKCJFbmNvZGluZyIsbnVsbCk7cy5zZXRCeU5hbWUoIkZvbnRNYXRyaXgiLG4uZm9udE1hdHJpeCk7cy5zZXRCeU5hbWUoIkZvbnRCQm94IixuLmJib3gpO3Muc2V0QnlOYW1lKCJjaGFyc2V0IixudWxsKTtzLnNldEJ5TmFtZSgiQ2hhclN0cmluZ3MiLG51bGwpO3Muc2V0QnlOYW1lKCJQcml2YXRlIixudWxsKTtpLnRvcERpY3Q9cztjb25zdCBvPW5ldyBDRkZTdHJpbmdzO28uYWRkKCJWZXJzaW9uIDAuMTEiKTtvLmFkZCgiU2VlIG9yaWdpbmFsIG5vdGljZSIpO28uYWRkKGUpO28uYWRkKGUpO28uYWRkKCJNZWRpdW0iKTtpLnN0cmluZ3M9bztpLmdsb2JhbFN1YnJJbmRleD1uZXcgQ0ZGSW5kZXg7Y29uc3QgYz10Lmxlbmd0aCxsPVsiLm5vdGRlZiJdO2xldCBoLHU7Zm9yKGg9MDtoPGM7aCsrKXtjb25zdCBlPXJbaF0uZ2x5cGhOYW1lOy0xPT09TWEuaW5kZXhPZihlKSYmby5hZGQoZSk7bC5wdXNoKGUpfWkuY2hhcnNldD1uZXcgQ0ZGQ2hhcnNldCghMSwwLGwpO2NvbnN0IGQ9bmV3IENGRkluZGV4O2QuYWRkKFsxMzksMTRdKTtmb3IoaD0wO2g8YztoKyspZC5hZGQodFtoXSk7aS5jaGFyU3RyaW5ncz1kO2NvbnN0IGY9bmV3IENGRlByaXZhdGVEaWN0O2Yuc2V0QnlOYW1lKCJTdWJycyIsbnVsbCk7Y29uc3QgZz1bIkJsdWVWYWx1ZXMiLCJPdGhlckJsdWVzIiwiRmFtaWx5Qmx1ZXMiLCJGYW1pbHlPdGhlckJsdWVzIiwiU3RlbVNuYXBIIiwiU3RlbVNuYXBWIiwiQmx1ZVNoaWZ0IiwiQmx1ZUZ1enoiLCJCbHVlU2NhbGUiLCJMYW5ndWFnZUdyb3VwIiwiRXhwYW5zaW9uRmFjdG9yIiwiRm9yY2VCb2xkIiwiU3RkSFciLCJTdGRWVyJdO2ZvcihoPTAsdT1nLmxlbmd0aDtoPHU7aCsrKXtjb25zdCBlPWdbaF07aWYoIShlIGluIG4ucHJpdmF0ZURhdGEpKWNvbnRpbnVlO2NvbnN0IHQ9bi5wcml2YXRlRGF0YVtlXTtpZihBcnJheS5pc0FycmF5KHQpKWZvcihsZXQgZT10Lmxlbmd0aC0xO2U+MDtlLS0pdFtlXS09dFtlLTFdO2Yuc2V0QnlOYW1lKGUsdCl9aS50b3BEaWN0LnByaXZhdGVEaWN0PWY7Y29uc3QgcD1uZXcgQ0ZGSW5kZXg7Zm9yKGg9MCx1PWEubGVuZ3RoO2g8dTtoKyspcC5hZGQoYVtoXSk7Zi5zdWJyc0luZGV4PXA7cmV0dXJuIG5ldyBDRkZDb21waWxlcihpKS5jb21waWxlKCl9fWNvbnN0IG5uPVtbNTczNDQsNjM3NDNdLFsxMDQ4NTc2LDExMTQxMDldXSxzbj0xZTMsb249WyJhc2NlbnQiLCJiYm94IiwiYmxhY2siLCJib2xkIiwiY2hhclByb2NPcGVyYXRvckxpc3QiLCJjc3NGb250SW5mbyIsImRhdGEiLCJkZWZhdWx0Vk1ldHJpY3MiLCJkZWZhdWx0V2lkdGgiLCJkZXNjZW50IiwiZGlzYWJsZUZvbnRGYWNlIiwiZmFsbGJhY2tOYW1lIiwiZm9udEV4dHJhUHJvcGVydGllcyIsImZvbnRNYXRyaXgiLCJpc0ludmFsaWRQREZqc0ZvbnQiLCJpc1R5cGUzRm9udCIsIml0YWxpYyIsImxvYWRlZE5hbWUiLCJtaW1ldHlwZSIsIm1pc3NpbmdGaWxlIiwibmFtZSIsInJlbWVhc3VyZSIsInN5c3RlbUZvbnRJbmZvIiwidmVydGljYWwiXSxjbj1bImNNYXAiLCJjb21wb3NpdGUiLCJkZWZhdWx0RW5jb2RpbmciLCJkaWZmZXJlbmNlcyIsImlzTW9ub3NwYWNlIiwiaXNTZXJpZkZvbnQiLCJpc1N5bWJvbGljRm9udCIsInNlYWNNYXAiLCJzdWJ0eXBlIiwidG9Gb250Q2hhciIsInRvVW5pY29kZSIsInR5cGUiLCJ2bWV0cmljcyIsIndpZHRocyJdO2Z1bmN0aW9uIGFkanVzdFdpZHRocyhlKXtpZighZS5mb250TWF0cml4KXJldHVybjtpZihlLmZvbnRNYXRyaXhbMF09PT1hWzBdKXJldHVybjtjb25zdCB0PS4wMDEvZS5mb250TWF0cml4WzBdLHI9ZS53aWR0aHM7Zm9yKGNvbnN0IGUgaW4gcilyW2VdKj10O2UuZGVmYXVsdFdpZHRoKj10fWZ1bmN0aW9uIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUoZSl7aWYoIWUuZmFsbGJhY2tUb1VuaWNvZGUpcmV0dXJuO2lmKGUudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApcmV0dXJuO2NvbnN0IHQ9W107Zm9yKGNvbnN0IHIgaW4gZS5mYWxsYmFja1RvVW5pY29kZSllLnRvVW5pY29kZS5oYXMocil8fCh0W3JdPWUuZmFsbGJhY2tUb1VuaWNvZGVbcl0pO3QubGVuZ3RoPjAmJmUudG9Vbmljb2RlLmFtZW5kKHQpfWNsYXNzIGZvbnRzX0dseXBoe2NvbnN0cnVjdG9yKGUsdCxyLGEsbixpLHMsbyxjKXt0aGlzLm9yaWdpbmFsQ2hhckNvZGU9ZTt0aGlzLmZvbnRDaGFyPXQ7dGhpcy51bmljb2RlPXI7dGhpcy5hY2NlbnQ9YTt0aGlzLndpZHRoPW47dGhpcy52bWV0cmljPWk7dGhpcy5vcGVyYXRvckxpc3RJZD1zO3RoaXMuaXNTcGFjZT1vO3RoaXMuaXNJbkZvbnQ9Y31nZXQgY2F0ZWdvcnkoKXtyZXR1cm4gc2hhZG93KHRoaXMsImNhdGVnb3J5IixmdW5jdGlvbiBnZXRDaGFyVW5pY29kZUNhdGVnb3J5KGUpe2NvbnN0IHQ9d2EuZ2V0KGUpO2lmKHQpcmV0dXJuIHQ7Y29uc3Qgcj1lLm1hdGNoKHlhKSxhPXtpc1doaXRlc3BhY2U6ISFyPy5bMV0saXNaZXJvV2lkdGhEaWFjcml0aWM6ISFyPy5bMl0saXNJbnZpc2libGVGb3JtYXRNYXJrOiEhcj8uWzNdfTt3YS5zZXQoZSxhKTtyZXR1cm4gYX0odGhpcy51bmljb2RlKSwhMCl9fWZ1bmN0aW9uIGludDE2KGUsdCl7cmV0dXJuKGU8PDgpK3R9ZnVuY3Rpb24gd3JpdGVTaWduZWRJbnQxNihlLHQscil7ZVt0KzFdPXI7ZVt0XT1yPj4+OH1mdW5jdGlvbiBzaWduZWRJbnQxNihlLHQpe2NvbnN0IHI9KGU8PDgpK3Q7cmV0dXJuIDMyNzY4JnI/ci02NTUzNjpyfWZ1bmN0aW9uIHN0cmluZzE2KGUpe3JldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGU+PjgmMjU1LDI1NSZlKX1mdW5jdGlvbiBzYWZlU3RyaW5nMTYoZSl7ZT4zMjc2Nz9lPTMyNzY3OmU8LTMyNzY4JiYoZT0tMzI3NjgpO3JldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGU+PjgmMjU1LDI1NSZlKX1mdW5jdGlvbiBpc1RydWVUeXBlQ29sbGVjdGlvbkZpbGUoZSl7cmV0dXJuInR0Y2YiPT09Ynl0ZXNUb1N0cmluZyhlLnBlZWtCeXRlcyg0KSl9ZnVuY3Rpb24gZ2V0Rm9udEZpbGVUeXBlKGUse3R5cGU6dCxzdWJ0eXBlOnIsY29tcG9zaXRlOmF9KXtsZXQgbixpO2lmKGZ1bmN0aW9uIGlzVHJ1ZVR5cGVGaWxlKGUpe2NvbnN0IHQ9ZS5wZWVrQnl0ZXMoNCk7cmV0dXJuIDY1NTM2PT09cmVhZFVpbnQzMih0LDApfHwidHJ1ZSI9PT1ieXRlc1RvU3RyaW5nKHQpfShlKXx8aXNUcnVlVHlwZUNvbGxlY3Rpb25GaWxlKGUpKW49YT8iQ0lERm9udFR5cGUyIjoiVHJ1ZVR5cGUiO2Vsc2UgaWYoZnVuY3Rpb24gaXNPcGVuVHlwZUZpbGUoZSl7cmV0dXJuIk9UVE8iPT09Ynl0ZXNUb1N0cmluZyhlLnBlZWtCeXRlcyg0KSl9KGUpKW49YT8iQ0lERm9udFR5cGUyIjoiT3BlblR5cGUiO2Vsc2UgaWYoZnVuY3Rpb24gaXNUeXBlMUZpbGUoZSl7Y29uc3QgdD1lLnBlZWtCeXRlcygyKTtyZXR1cm4gMzc9PT10WzBdJiYzMz09PXRbMV18fDEyOD09PXRbMF0mJjE9PT10WzFdfShlKSluPWE/IkNJREZvbnRUeXBlMCI6Ik1NVHlwZTEiPT09dD8iTU1UeXBlMSI6IlR5cGUxIjtlbHNlIGlmKGZ1bmN0aW9uIGlzQ0ZGRmlsZShlKXtjb25zdCB0PWUucGVla0J5dGVzKDQpO3JldHVybiB0WzBdPj0xJiZ0WzNdPj0xJiZ0WzNdPD00fShlKSlpZihhKXtuPSJDSURGb250VHlwZTAiO2k9IkNJREZvbnRUeXBlMEMifWVsc2V7bj0iTU1UeXBlMSI9PT10PyJNTVR5cGUxIjoiVHlwZTEiO2k9IlR5cGUxQyJ9ZWxzZXt3YXJuKCJnZXRGb250RmlsZVR5cGU6IFVuYWJsZSB0byBkZXRlY3QgY29ycmVjdCBmb250IGZpbGUgVHlwZS9TdWJ0eXBlLiIpO249dDtpPXJ9cmV0dXJuW24saV19ZnVuY3Rpb24gYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChlLHQpe2Zvcihjb25zdCByIGluIHQpZVsrcl09dFtyXX1mdW5jdGlvbiBidWlsZFRvRm9udENoYXIoZSx0LHIpe2NvbnN0IGE9W107bGV0IG47Zm9yKGxldCByPTAsaT1lLmxlbmd0aDtyPGk7cisrKXtuPWdldFVuaWNvZGVGb3JHbHlwaChlW3JdLHQpOy0xIT09biYmKGFbcl09bil9Zm9yKGNvbnN0IGUgaW4gcil7bj1nZXRVbmljb2RlRm9yR2x5cGgocltlXSx0KTstMSE9PW4mJihhWytlXT1uKX1yZXR1cm4gYX1mdW5jdGlvbiBpc01hY05hbWVSZWNvcmQoZSl7cmV0dXJuIDE9PT1lLnBsYXRmb3JtJiYwPT09ZS5lbmNvZGluZyYmMD09PWUubGFuZ3VhZ2V9ZnVuY3Rpb24gaXNXaW5OYW1lUmVjb3JkKGUpe3JldHVybiAzPT09ZS5wbGF0Zm9ybSYmMT09PWUuZW5jb2RpbmcmJjEwMzM9PT1lLmxhbmd1YWdlfWZ1bmN0aW9uIGNvbnZlcnRDaWRTdHJpbmcoZSx0LHI9ITEpe3N3aXRjaCh0Lmxlbmd0aCl7Y2FzZSAxOnJldHVybiB0LmNoYXJDb2RlQXQoMCk7Y2FzZSAyOnJldHVybiB0LmNoYXJDb2RlQXQoMCk8PDh8dC5jaGFyQ29kZUF0KDEpfWNvbnN0IGE9YFVuc3VwcG9ydGVkIENJRCBzdHJpbmcgKGNoYXJDb2RlICR7ZX0pOiAiJHt0fSIuYDtpZihyKXRocm93IG5ldyBGb3JtYXRFcnJvcihhKTt3YXJuKGEpO3JldHVybiB0fWZ1bmN0aW9uIGFkanVzdE1hcHBpbmcoZSx0LHIsYSl7Y29uc3Qgbj1PYmplY3QuY3JlYXRlKG51bGwpLGk9bmV3IE1hcCxzPVtdLG89bmV3IFNldDtsZXQgYz0wO2xldCBsPW5uW2NdWzBdLGg9bm5bY11bMV07Y29uc3QgaXNJblByaXZhdGVBcmVhPWU9Pm5uWzBdWzBdPD1lJiZlPD1ublswXVsxXXx8bm5bMV1bMF08PWUmJmU8PW5uWzFdWzFdO2xldCB1PW51bGw7Zm9yKGNvbnN0IGQgaW4gZSl7bGV0IGY9ZVtkXTtpZighdChmKSljb250aW51ZTtpZihsPmgpe2MrKztpZihjPj1ubi5sZW5ndGgpe3dhcm4oIlJhbiBvdXQgb2Ygc3BhY2UgaW4gZm9udCBwcml2YXRlIHVzZSBhcmVhLiIpO2JyZWFrfWw9bm5bY11bMF07aD1ubltjXVsxXX1jb25zdCBnPWwrKzswPT09ZiYmKGY9cik7bGV0IHA9YS5nZXQoZCk7aWYoInN0cmluZyI9PXR5cGVvZiBwKWlmKDE9PT1wLmxlbmd0aClwPXAuY29kZVBvaW50QXQoMCk7ZWxzZXtpZighdSl7dT1uZXcgTWFwO2ZvcihsZXQgZT02NDI1NjtlPD02NDMzNTtlKyspe2NvbnN0IHQ9U3RyaW5nLmZyb21DaGFyQ29kZShlKS5ub3JtYWxpemUoIk5GS0QiKTt0Lmxlbmd0aD4xJiZ1LnNldCh0LGUpfX1wPXUuZ2V0KHApfHxwLmNvZGVQb2ludEF0KDApfWlmKHAmJiFpc0luUHJpdmF0ZUFyZWEocCkmJiFvLmhhcyhmKSl7aS5zZXQocCxmKTtvLmFkZChmKX1uW2ddPWY7c1tkXT1nfXJldHVybnt0b0ZvbnRDaGFyOnMsY2hhckNvZGVUb0dseXBoSWQ6bix0b1VuaWNvZGVFeHRyYU1hcDppLG5leHRBdmFpbGFibGVGb250Q2hhckNvZGU6bH19ZnVuY3Rpb24gY3JlYXRlQ21hcFRhYmxlKGUsdCxyKXtjb25zdCBhPWZ1bmN0aW9uIGdldFJhbmdlcyhlLHQscil7Y29uc3QgYT1bXTtmb3IoY29uc3QgdCBpbiBlKWVbdF0+PXJ8fGEucHVzaCh7Zm9udENoYXJDb2RlOjB8dCxnbHlwaElkOmVbdF19KTtpZih0KWZvcihjb25zdFtlLG5db2YgdCluPj1yfHxhLnB1c2goe2ZvbnRDaGFyQ29kZTplLGdseXBoSWQ6bn0pOzA9PT1hLmxlbmd0aCYmYS5wdXNoKHtmb250Q2hhckNvZGU6MCxnbHlwaElkOjB9KTthLnNvcnQoKGUsdCk9PmUuZm9udENoYXJDb2RlLXQuZm9udENoYXJDb2RlKTtjb25zdCBuPVtdLGk9YS5sZW5ndGg7Zm9yKGxldCBlPTA7ZTxpOyl7Y29uc3QgdD1hW2VdLmZvbnRDaGFyQ29kZSxyPVthW2VdLmdseXBoSWRdOysrZTtsZXQgcz10O2Zvcig7ZTxpJiZzKzE9PT1hW2VdLmZvbnRDaGFyQ29kZTspe3IucHVzaChhW2VdLmdseXBoSWQpOysrczsrK2U7aWYoNjU1MzU9PT1zKWJyZWFrfW4ucHVzaChbdCxzLHJdKX1yZXR1cm4gbn0oZSx0LHIpLG49YS5hdCgtMSlbMV0+NjU1MzU/MjoxO2xldCBpLHMsbyxjLGw9IlwwXDAiK3N0cmluZzE2KG4pKyJcMANcMAEiK3N0cmluZzMyKDQrOCpuKTtmb3IoaT1hLmxlbmd0aC0xO2k+PTAmJiEoYVtpXVswXTw9NjU1MzUpOy0taSk7Y29uc3QgaD1pKzE7YVtpXVswXTw2NTUzNSYmNjU1MzU9PT1hW2ldWzFdJiYoYVtpXVsxXT02NTUzNCk7Y29uc3QgdT1hW2ldWzFdPDY1NTM1PzE6MCxkPWgrdSxmPU9wZW5UeXBlRmlsZUJ1aWxkZXIuZ2V0U2VhcmNoUGFyYW1zKGQsMik7bGV0IGcscCxtLGIseT0iIix3PSIiLHg9IiIsUz0iIixrPSIiLEM9MDtmb3IoaT0wLHM9aDtpPHM7aSsrKXtnPWFbaV07cD1nWzBdO209Z1sxXTt5Kz1zdHJpbmcxNihwKTt3Kz1zdHJpbmcxNihtKTtiPWdbMl07bGV0IGU9ITA7Zm9yKG89MSxjPWIubGVuZ3RoO288YzsrK28paWYoYltvXSE9PWJbby0xXSsxKXtlPSExO2JyZWFrfWlmKGUpe3grPXN0cmluZzE2KGJbMF0tcCY2NTUzNSk7Uys9c3RyaW5nMTYoMCl9ZWxzZXtjb25zdCBlPTIqKGQtaSkrMipDO0MrPW0tcCsxO3grPXN0cmluZzE2KDApO1MrPXN0cmluZzE2KGUpO2ZvcihvPTAsYz1iLmxlbmd0aDtvPGM7KytvKWsrPXN0cmluZzE2KGJbb10pfX1pZih1PjApe3crPSLDv8O/Ijt5Kz0iw7/DvyI7eCs9IlwwASI7Uys9IlwwXDAifWNvbnN0IHY9IlwwXDAiK3N0cmluZzE2KDIqZCkrc3RyaW5nMTYoZi5yYW5nZSkrc3RyaW5nMTYoZi5lbnRyeSkrc3RyaW5nMTYoZi5yYW5nZVNoaWZ0KSt3KyJcMFwwIit5K3grUytrO2xldCBUPSIiLE89IiI7aWYobj4xKXtsKz0iXDADXDBcbiIrc3RyaW5nMzIoNCs4Km4rNCt2Lmxlbmd0aCk7VD0iIjtmb3IoaT0wLHM9YS5sZW5ndGg7aTxzO2krKyl7Zz1hW2ldO3A9Z1swXTtiPWdbMl07bGV0IGU9YlswXTtmb3Iobz0xLGM9Yi5sZW5ndGg7bzxjOysrbylpZihiW29dIT09YltvLTFdKzEpe209Z1swXStvLTE7VCs9c3RyaW5nMzIocCkrc3RyaW5nMzIobSkrc3RyaW5nMzIoZSk7cD1tKzE7ZT1iW29dfVQrPXN0cmluZzMyKHApK3N0cmluZzMyKGdbMV0pK3N0cmluZzMyKGUpfU89IlwwXGZcMFwwIitzdHJpbmczMihULmxlbmd0aCsxNikrIlwwXDBcMFwwIitzdHJpbmczMihULmxlbmd0aC8xMil9cmV0dXJuIGwrIlwwBCIrc3RyaW5nMTYodi5sZW5ndGgrNCkrditPK1R9ZnVuY3Rpb24gY3JlYXRlT1MyVGFibGUoZSx0LHIpe3J8fD17dW5pdHNQZXJFbTowLHlNYXg6MCx5TWluOjAsYXNjZW50OjAsZGVzY2VudDowfTtsZXQgYT0wLG49MCxpPTAscz0wLG89bnVsbCxjPTAsbD0tMTtpZih0KXtmb3IobGV0IGUgaW4gdCl7ZXw9MDsobz5lfHwhbykmJihvPWUpO2M8ZSYmKGM9ZSk7bD1nZXRVbmljb2RlUmFuZ2VGb3IoZSxsKTtpZihsPDMyKWF8PTE8PGw7ZWxzZSBpZihsPDY0KW58PTE8PGwtMzI7ZWxzZSBpZihsPDk2KWl8PTE8PGwtNjQ7ZWxzZXtpZighKGw8MTIzKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVuaWNvZGUgcmFuZ2VzIEJpdHMgPiAxMjMgYXJlIHJlc2VydmVkIGZvciBpbnRlcm5hbCB1c2FnZSIpO3N8PTE8PGwtOTZ9fWM+NjU1MzUmJihjPTY1NTM1KX1lbHNle289MDtjPTI1NX1jb25zdCBoPWUuYmJveHx8WzAsMCwwLDBdLHU9ci51bml0c1BlckVtfHwoZS5mb250TWF0cml4PzEvTWF0aC5tYXgoLi4uZS5mb250TWF0cml4LnNsaWNlKDAsNCkubWFwKE1hdGguYWJzKSk6MWUzKSxkPWUuYXNjZW50U2NhbGVkPzE6dS9zbixmPXIuYXNjZW50fHxNYXRoLnJvdW5kKGQqKGUuYXNjZW50fHxoWzNdKSk7bGV0IGc9ci5kZXNjZW50fHxNYXRoLnJvdW5kKGQqKGUuZGVzY2VudHx8aFsxXSkpO2c+MCYmZS5kZXNjZW50PjAmJmhbMV08MCYmKGc9LWcpO2NvbnN0IHA9ci55TWF4fHxmLG09LXIueU1pbnx8LWc7cmV0dXJuIlwwAwIkAcO0XDAFXDBcMALCigLCu1wwXDBcMMKMAsKKAsK7XDBcMAHDn1x4MDAxAQJcMFwwXDBcMAYiK1N0cmluZy5mcm9tQ2hhckNvZGUoZS5maXhlZFBpdGNoPzk6MCkrIlwwXDBcMFwwXDBcMCIrc3RyaW5nMzIoYSkrc3RyaW5nMzIobikrc3RyaW5nMzIoaSkrc3RyaW5nMzIocykrIioyMSoiK3N0cmluZzE2KGUuaXRhbGljQW5nbGU/MTowKStzdHJpbmcxNihvfHxlLmZpcnN0Q2hhcikrc3RyaW5nMTYoY3x8ZS5sYXN0Q2hhcikrc3RyaW5nMTYoZikrc3RyaW5nMTYoZykrIlwwZCIrc3RyaW5nMTYocCkrc3RyaW5nMTYobSkrIlwwXDBcMFwwXDBcMFwwXDAiK3N0cmluZzE2KGUueEhlaWdodCkrc3RyaW5nMTYoZS5jYXBIZWlnaHQpK3N0cmluZzE2KDApK3N0cmluZzE2KG98fGUuZmlyc3RDaGFyKSsiXDADIn1mdW5jdGlvbiBjcmVhdGVQb3N0VGFibGUoZSl7cmV0dXJuIlwwA1wwXDAiK3N0cmluZzMyKE1hdGguZmxvb3IoNjU1MzYqZS5pdGFsaWNBbmdsZSkpKyJcMFwwXDBcMCIrc3RyaW5nMzIoZS5maXhlZFBpdGNoPzE6MCkrIlwwXDBcMFwwXDBcMFwwXDBcMFwwXDBcMFwwXDBcMFwwIn1mdW5jdGlvbiBjcmVhdGVQb3N0c2NyaXB0TmFtZShlKXtyZXR1cm4gZS5yZXBsYWNlQWxsKC9bXlx4MjEtXHg3RV18W1tcXSgpe308Pi8lXS9nLCIiKS5zbGljZSgwLDYzKX1mdW5jdGlvbiBjcmVhdGVOYW1lVGFibGUoZSx0KXt0fHwodD1bW10sW11dKTtjb25zdCByPVt0WzBdWzBdfHwiT3JpZ2luYWwgbGljZW5jZSIsdFswXVsxXXx8ZSx0WzBdWzJdfHwiVW5rbm93biIsdFswXVszXXx8InVuaXF1ZUlEIix0WzBdWzRdfHxlLHRbMF1bNV18fCJWZXJzaW9uIDAuMTEiLHRbMF1bNl18fGNyZWF0ZVBvc3RzY3JpcHROYW1lKGUpLHRbMF1bN118fCJVbmtub3duIix0WzBdWzhdfHwiVW5rbm93biIsdFswXVs5XXx8IlVua25vd24iXSxhPVtdO2xldCBuLGkscyxvLGM7Zm9yKG49MCxpPXIubGVuZ3RoO248aTtuKyspe2M9dFsxXVtuXXx8cltuXTtjb25zdCBlPVtdO2ZvcihzPTAsbz1jLmxlbmd0aDtzPG87cysrKWUucHVzaChzdHJpbmcxNihjLmNoYXJDb2RlQXQocykpKTthLnB1c2goZS5qb2luKCIiKSl9Y29uc3QgbD1bcixhXSxoPVsiXDABIiwiXDADIl0sdT1bIlwwXDAiLCJcMAEiXSxkPVsiXDBcMCIsIgRcdCJdLGY9ci5sZW5ndGgqaC5sZW5ndGg7bGV0IGc9IlwwXDAiK3N0cmluZzE2KGYpK3N0cmluZzE2KDEyKmYrNikscD0wO2ZvcihuPTAsaT1oLmxlbmd0aDtuPGk7bisrKXtjb25zdCBlPWxbbl07Zm9yKHM9MCxvPWUubGVuZ3RoO3M8bztzKyspe2M9ZVtzXTtnKz1oW25dK3Vbbl0rZFtuXStzdHJpbmcxNihzKStzdHJpbmcxNihjLmxlbmd0aCkrc3RyaW5nMTYocCk7cCs9Yy5sZW5ndGh9fWcrPXIuam9pbigiIikrYS5qb2luKCIiKTtyZXR1cm4gZ31jbGFzcyBGb250e2NvbnN0cnVjdG9yKGUsdCxyLGEpe3RoaXMubmFtZT1lO3RoaXMucHNOYW1lPW51bGw7dGhpcy5taW1ldHlwZT1udWxsO3RoaXMuZGlzYWJsZUZvbnRGYWNlPWEuZGlzYWJsZUZvbnRGYWNlO3RoaXMuZm9udEV4dHJhUHJvcGVydGllcz1hLmZvbnRFeHRyYVByb3BlcnRpZXM7dGhpcy5sb2FkZWROYW1lPXIubG9hZGVkTmFtZTt0aGlzLmlzVHlwZTNGb250PXIuaXNUeXBlM0ZvbnQ7dGhpcy5taXNzaW5nRmlsZT0hMTt0aGlzLmNzc0ZvbnRJbmZvPXIuY3NzRm9udEluZm87dGhpcy5fY2hhcnNDYWNoZT1PYmplY3QuY3JlYXRlKG51bGwpO3RoaXMuX2dseXBoQ2FjaGU9T2JqZWN0LmNyZWF0ZShudWxsKTtsZXQgbj0hIShyLmZsYWdzJkFhKTtpZighbiYmIXIuaXNTaW11bGF0ZWRGbGFncyl7Y29uc3QgdD1fYSgpLHI9amEoKSxhPVVhKCk7Zm9yKGNvbnN0IGkgb2YgZS5zcGxpdCgiKyIpKXtsZXQgZT1pLnJlcGxhY2VBbGwoL1ssX10vZywiLSIpO2U9dFtlXXx8cltlXXx8ZTtlPWUuc3BsaXQoIi0iLDEpWzBdO2lmKGFbZV0pe249ITA7YnJlYWt9fX10aGlzLmlzU2VyaWZGb250PW47dGhpcy5pc1N5bWJvbGljRm9udD0hIShyLmZsYWdzJmthKTt0aGlzLmlzTW9ub3NwYWNlPSEhKHIuZmxhZ3MmU2EpO2xldHt0eXBlOmksc3VidHlwZTpzfT1yO3RoaXMudHlwZT1pO3RoaXMuc3VidHlwZT1zO3RoaXMuc3lzdGVtRm9udEluZm89ci5zeXN0ZW1Gb250SW5mbztjb25zdCBvPWUubWF0Y2goL15JbnZhbGlkUERGanNGb250XyguKilfXGQrJC8pO3RoaXMuaXNJbnZhbGlkUERGanNGb250PSEhbzt0aGlzLmlzSW52YWxpZFBERmpzRm9udD90aGlzLmZhbGxiYWNrTmFtZT1vWzFdOnRoaXMuaXNNb25vc3BhY2U/dGhpcy5mYWxsYmFja05hbWU9Im1vbm9zcGFjZSI6dGhpcy5pc1NlcmlmRm9udD90aGlzLmZhbGxiYWNrTmFtZT0ic2VyaWYiOnRoaXMuZmFsbGJhY2tOYW1lPSJzYW5zLXNlcmlmIjtpZih0aGlzLnN5c3RlbUZvbnRJbmZvPy5ndWVzc0ZhbGxiYWNrKXt0aGlzLnN5c3RlbUZvbnRJbmZvLmd1ZXNzRmFsbGJhY2s9ITE7dGhpcy5zeXN0ZW1Gb250SW5mby5jc3MrPWAsJHt0aGlzLmZhbGxiYWNrTmFtZX1gfXRoaXMuZGlmZmVyZW5jZXM9ci5kaWZmZXJlbmNlczt0aGlzLndpZHRocz1yLndpZHRoczt0aGlzLmRlZmF1bHRXaWR0aD1yLmRlZmF1bHRXaWR0aDt0aGlzLmNvbXBvc2l0ZT1yLmNvbXBvc2l0ZTt0aGlzLmNNYXA9ci5jTWFwO3RoaXMuY2FwSGVpZ2h0PXIuY2FwSGVpZ2h0L3NuO3RoaXMuYXNjZW50PXIuYXNjZW50L3NuO3RoaXMuZGVzY2VudD1yLmRlc2NlbnQvc247dGhpcy5saW5lSGVpZ2h0PXRoaXMuYXNjZW50LXRoaXMuZGVzY2VudDt0aGlzLmZvbnRNYXRyaXg9ci5mb250TWF0cml4O3RoaXMuYmJveD1yLmJib3g7dGhpcy5kZWZhdWx0RW5jb2Rpbmc9ci5kZWZhdWx0RW5jb2Rpbmc7dGhpcy50b1VuaWNvZGU9ci50b1VuaWNvZGU7dGhpcy50b0ZvbnRDaGFyPVtdO2lmKCJUeXBlMyI9PT1yLnR5cGUpe2ZvcihsZXQgZT0wO2U8MjU2O2UrKyl0aGlzLnRvRm9udENoYXJbZV09dGhpcy5kaWZmZXJlbmNlc1tlXXx8ci5kZWZhdWx0RW5jb2RpbmdbZV07cmV0dXJufXRoaXMuY2lkRW5jb2Rpbmc9ci5jaWRFbmNvZGluZ3x8IiI7dGhpcy52ZXJ0aWNhbD0hIXIudmVydGljYWw7aWYodGhpcy52ZXJ0aWNhbCl7dGhpcy52bWV0cmljcz1yLnZtZXRyaWNzO3RoaXMuZGVmYXVsdFZNZXRyaWNzPXIuZGVmYXVsdFZNZXRyaWNzfWlmKCF0fHx0LmlzRW1wdHkpe3QmJndhcm4oJ0ZvbnQgZmlsZSBpcyBlbXB0eSBpbiAiJytlKyciICgnK3RoaXMubG9hZGVkTmFtZSsiKSIpO3RoaXMuZmFsbGJhY2tUb1N5c3RlbUZvbnQocik7cmV0dXJufVtpLHNdPWdldEZvbnRGaWxlVHlwZSh0LHIpO2k9PT10aGlzLnR5cGUmJnM9PT10aGlzLnN1YnR5cGV8fGluZm8oYEluY29uc2lzdGVudCBmb250IGZpbGUgVHlwZS9TdWJUeXBlLCBleHBlY3RlZDogJHt0aGlzLnR5cGV9LyR7dGhpcy5zdWJ0eXBlfSBidXQgZm91bmQ6ICR7aX0vJHtzfS5gKTtsZXQgYzt0cnl7c3dpdGNoKGkpe2Nhc2UiTU1UeXBlMSI6aW5mbygiTU1UeXBlMSBmb250ICgiK2UrIiksIGZhbGxpbmcgYmFjayB0byBUeXBlMS4iKTtjYXNlIlR5cGUxIjpjYXNlIkNJREZvbnRUeXBlMCI6dGhpcy5taW1ldHlwZT0iZm9udC9vcGVudHlwZSI7Y29uc3QgYT0iVHlwZTFDIj09PXN8fCJDSURGb250VHlwZTBDIj09PXM/bmV3IENGRkZvbnQodCxyKTpuZXcgVHlwZTFGb250KGUsdCxyKTthZGp1c3RXaWR0aHMocik7Yz10aGlzLmNvbnZlcnQoZSxhLHIpO2JyZWFrO2Nhc2UiT3BlblR5cGUiOmNhc2UiVHJ1ZVR5cGUiOmNhc2UiQ0lERm9udFR5cGUyIjp0aGlzLm1pbWV0eXBlPSJmb250L29wZW50eXBlIjtjPXRoaXMuY2hlY2tBbmRSZXBhaXIoZSx0LHIpO2FkanVzdFdpZHRocyhyKTt0aGlzLmlzT3BlblR5cGUmJihpPSJPcGVuVHlwZSIpO2JyZWFrO2RlZmF1bHQ6dGhyb3cgbmV3IEZvcm1hdEVycm9yKGBGb250ICR7aX0gaXMgbm90IHN1cHBvcnRlZGApfX1jYXRjaChlKXt3YXJuKGUpO3RoaXMuZmFsbGJhY2tUb1N5c3RlbUZvbnQocik7cmV0dXJufWFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocik7dGhpcy5kYXRhPWM7dGhpcy50eXBlPWk7dGhpcy5zdWJ0eXBlPXM7dGhpcy5mb250TWF0cml4PXIuZm9udE1hdHJpeDt0aGlzLndpZHRocz1yLndpZHRoczt0aGlzLmRlZmF1bHRXaWR0aD1yLmRlZmF1bHRXaWR0aDt0aGlzLnRvVW5pY29kZT1yLnRvVW5pY29kZTt0aGlzLnNlYWNNYXA9ci5zZWFjTWFwfWdldCByZW5kZXJlcigpe3JldHVybiBzaGFkb3codGhpcywicmVuZGVyZXIiLEZvbnRSZW5kZXJlckZhY3RvcnkuY3JlYXRlKHRoaXMseGEpKX1leHBvcnREYXRhKCl7Y29uc3QgZT1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcihjb25zdCB0IG9mIG9uKXtjb25zdCByPXRoaXNbdF07dm9pZCAwIT09ciYmKGVbdF09cil9aWYoIXRoaXMuZm9udEV4dHJhUHJvcGVydGllcylyZXR1cm57ZGF0YTplfTtjb25zdCB0PU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGNvbnN0IGUgb2YgY24pe2NvbnN0IHI9dGhpc1tlXTt2b2lkIDAhPT1yJiYodFtlXT1yKX1yZXR1cm57ZGF0YTplLGV4dHJhOnR9fWZhbGxiYWNrVG9TeXN0ZW1Gb250KGUpe3RoaXMubWlzc2luZ0ZpbGU9ITA7Y29uc3R7bmFtZTp0LHR5cGU6cn09dGhpcztsZXQgYT1ub3JtYWxpemVGb250TmFtZSh0KTtjb25zdCBuPV9hKCksaT1qYSgpLHM9ISFuW2FdLG89ISghaVthXXx8IW5baVthXV0pO2E9blthXXx8aVthXXx8YTtjb25zdCBjPUdhKClbYV07aWYoYyl7aXNOYU4odGhpcy5hc2NlbnQpJiYodGhpcy5hc2NlbnQ9Yy5hc2NlbnQvc24pO2lzTmFOKHRoaXMuZGVzY2VudCkmJih0aGlzLmRlc2NlbnQ9Yy5kZXNjZW50L3NuKTtpc05hTih0aGlzLmNhcEhlaWdodCkmJih0aGlzLmNhcEhlaWdodD1jLmNhcEhlaWdodC9zbil9dGhpcy5ib2xkPS9ib2xkL2dpLnRlc3QoYSk7dGhpcy5pdGFsaWM9L29ibGlxdWV8aXRhbGljL2dpLnRlc3QoYSk7dGhpcy5ibGFjaz0vQmxhY2svZy50ZXN0KHQpO2NvbnN0IGw9L05hcnJvdy9nLnRlc3QodCk7dGhpcy5yZW1lYXN1cmU9KCFzfHxsKSYmT2JqZWN0LmtleXModGhpcy53aWR0aHMpLmxlbmd0aD4wO2lmKChzfHxvKSYmIkNJREZvbnRUeXBlMiI9PT1yJiZ0aGlzLmNpZEVuY29kaW5nLnN0YXJ0c1dpdGgoIklkZW50aXR5LSIpKXtjb25zdCByPWUuY2lkVG9HaWRNYXAsYT1bXTthcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKGEsWGEoKSk7L0FyaWFsLT9CbGFjay9pLnRlc3QodCk/YXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChhLEhhKCkpOi9DYWxpYnJpL2kudGVzdCh0KSYmYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChhLFdhKCkpO2lmKHIpe2Zvcihjb25zdCBlIGluIGEpe2NvbnN0IHQ9YVtlXTt2b2lkIDAhPT1yW3RdJiYoYVsrZV09clt0XSl9ci5sZW5ndGghPT10aGlzLnRvVW5pY29kZS5sZW5ndGgmJmUuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAmJnRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXAmJnRoaXMudG9Vbmljb2RlLmZvckVhY2goZnVuY3Rpb24oZSx0KXtjb25zdCBuPWFbZV07dm9pZCAwPT09cltuXSYmKGFbK2VdPXQpfSl9dGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcHx8dGhpcy50b1VuaWNvZGUuZm9yRWFjaChmdW5jdGlvbihlLHQpe2FbK2VdPXR9KTt0aGlzLnRvRm9udENoYXI9YTt0aGlzLnRvVW5pY29kZT1uZXcgVG9Vbmljb2RlTWFwKGEpfWVsc2UgaWYoL1N5bWJvbC9pLnRlc3QoYSkpdGhpcy50b0ZvbnRDaGFyPWJ1aWxkVG9Gb250Q2hhcihkYSxnYSgpLHRoaXMuZGlmZmVyZW5jZXMpO2Vsc2UgaWYoL0RpbmdiYXRzL2kudGVzdChhKSl0aGlzLnRvRm9udENoYXI9YnVpbGRUb0ZvbnRDaGFyKGZhLHBhKCksdGhpcy5kaWZmZXJlbmNlcyk7ZWxzZSBpZihzfHxvKXtjb25zdCBlPWJ1aWxkVG9Gb250Q2hhcih0aGlzLmRlZmF1bHRFbmNvZGluZyxnYSgpLHRoaXMuZGlmZmVyZW5jZXMpOyJDSURGb250VHlwZTIiIT09cnx8dGhpcy5jaWRFbmNvZGluZy5zdGFydHNXaXRoKCJJZGVudGl0eS0iKXx8dGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcHx8dGhpcy50b1VuaWNvZGUuZm9yRWFjaChmdW5jdGlvbih0LHIpe2VbK3RdPXJ9KTt0aGlzLnRvRm9udENoYXI9ZX1lbHNle2NvbnN0IGU9Z2EoKSxyPVtdO3RoaXMudG9Vbmljb2RlLmZvckVhY2goKHQsYSk9PntpZighdGhpcy5jb21wb3NpdGUpe2NvbnN0IHI9Z2V0VW5pY29kZUZvckdseXBoKHRoaXMuZGlmZmVyZW5jZXNbdF18fHRoaXMuZGVmYXVsdEVuY29kaW5nW3RdLGUpOy0xIT09ciYmKGE9cil9clsrdF09YX0pO3RoaXMuY29tcG9zaXRlJiZ0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwJiYvVGFob21hfFZlcmRhbmEvaS50ZXN0KHQpJiZhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKHIsWGEoKSk7dGhpcy50b0ZvbnRDaGFyPXJ9YW1lbmRGYWxsYmFja1RvVW5pY29kZShlKTt0aGlzLmxvYWRlZE5hbWU9YS5zcGxpdCgiLSIsMSlbMF19Y2hlY2tBbmRSZXBhaXIoZSx0LHIpe2NvbnN0IGE9WyJPUy8yIiwiY21hcCIsImhlYWQiLCJoaGVhIiwiaG10eCIsIm1heHAiLCJuYW1lIiwicG9zdCIsImxvY2EiLCJnbHlmIiwiZnBnbSIsInByZXAiLCJjdnQgIiwiQ0ZGICJdO2Z1bmN0aW9uIHJlYWRUYWJsZXMoZSx0KXtjb25zdCByPU9iamVjdC5jcmVhdGUobnVsbCk7clsiT1MvMiJdPW51bGw7ci5jbWFwPW51bGw7ci5oZWFkPW51bGw7ci5oaGVhPW51bGw7ci5obXR4PW51bGw7ci5tYXhwPW51bGw7ci5uYW1lPW51bGw7ci5wb3N0PW51bGw7Zm9yKGxldCBuPTA7bjx0O24rKyl7Y29uc3QgdD1yZWFkVGFibGVFbnRyeShlKTthLmluY2x1ZGVzKHQudGFnKSYmKDAhPT10Lmxlbmd0aCYmKHJbdC50YWddPXQpKX1yZXR1cm4gcn1mdW5jdGlvbiByZWFkVGFibGVFbnRyeShlKXtjb25zdCB0PWUuZ2V0U3RyaW5nKDQpLHI9ZS5nZXRJbnQzMigpPj4+MCxhPWUuZ2V0SW50MzIoKT4+PjAsbj1lLmdldEludDMyKCk+Pj4wLGk9ZS5wb3M7ZS5wb3M9ZS5zdGFydHx8MDtlLnNraXAoYSk7Y29uc3Qgcz1lLmdldEJ5dGVzKG4pO2UucG9zPWk7aWYoImhlYWQiPT09dCl7c1s4XT1zWzldPXNbMTBdPXNbMTFdPTA7c1sxN118PTMyfXJldHVybnt0YWc6dCxjaGVja3N1bTpyLGxlbmd0aDpuLG9mZnNldDphLGRhdGE6c319ZnVuY3Rpb24gcmVhZE9wZW5UeXBlSGVhZGVyKGUpe3JldHVybnt2ZXJzaW9uOmUuZ2V0U3RyaW5nKDQpLG51bVRhYmxlczplLmdldFVpbnQxNigpLHNlYXJjaFJhbmdlOmUuZ2V0VWludDE2KCksZW50cnlTZWxlY3RvcjplLmdldFVpbnQxNigpLHJhbmdlU2hpZnQ6ZS5nZXRVaW50MTYoKX19ZnVuY3Rpb24gc2FuaXRpemVHbHlwaChlLHQscixhLG4saSl7Y29uc3Qgcz17bGVuZ3RoOjAsc2l6ZU9mSW5zdHJ1Y3Rpb25zOjB9O2lmKHQ8MHx8dD49ZS5sZW5ndGh8fHI+ZS5sZW5ndGh8fHItdDw9MTIpcmV0dXJuIHM7Y29uc3Qgbz1lLnN1YmFycmF5KHQsciksYz1zaWduZWRJbnQxNihvWzJdLG9bM10pLGw9c2lnbmVkSW50MTYob1s0XSxvWzVdKSxoPXNpZ25lZEludDE2KG9bNl0sb1s3XSksdT1zaWduZWRJbnQxNihvWzhdLG9bOV0pO2lmKGM+aCl7d3JpdGVTaWduZWRJbnQxNihvLDIsaCk7d3JpdGVTaWduZWRJbnQxNihvLDYsYyl9aWYobD51KXt3cml0ZVNpZ25lZEludDE2KG8sNCx1KTt3cml0ZVNpZ25lZEludDE2KG8sOCxsKX1jb25zdCBkPXNpZ25lZEludDE2KG9bMF0sb1sxXSk7aWYoZDwwKXtpZihkPC0xKXJldHVybiBzO2Euc2V0KG8sbik7cy5sZW5ndGg9by5sZW5ndGg7cmV0dXJuIHN9bGV0IGYsZz0xMCxwPTA7Zm9yKGY9MDtmPGQ7ZisrKXtwPShvW2ddPDw4fG9bZysxXSkrMTtnKz0yfWNvbnN0IG09ZyxiPW9bZ108PDh8b1tnKzFdO3Muc2l6ZU9mSW5zdHJ1Y3Rpb25zPWI7Zys9MitiO2NvbnN0IHk9ZztsZXQgdz0wO2ZvcihmPTA7ZjxwO2YrKyl7Y29uc3QgZT1vW2crK107MTkyJmUmJihvW2ctMV09NjMmZSk7bGV0IHQ9MjsyJmU/dD0xOjE2JmUmJih0PTApO2xldCByPTI7NCZlP3I9MTozMiZlJiYocj0wKTtjb25zdCBhPXQrcjt3Kz1hO2lmKDgmZSl7Y29uc3QgZT1vW2crK107MD09PWUmJihvW2ctMV1ePTgpO2YrPWU7dys9ZSphfX1pZigwPT09dylyZXR1cm4gcztsZXQgeD1nK3c7aWYoeD5vLmxlbmd0aClyZXR1cm4gcztpZighaSYmYj4wKXthLnNldChvLnN1YmFycmF5KDAsbSksbik7YS5zZXQoWzAsMF0sbittKTthLnNldChvLnN1YmFycmF5KHkseCksbittKzIpO3gtPWI7by5sZW5ndGgteD4zJiYoeD14KzMmLTQpO3MubGVuZ3RoPXg7cmV0dXJuIHN9aWYoby5sZW5ndGgteD4zKXt4PXgrMyYtNDthLnNldChvLnN1YmFycmF5KDAseCksbik7cy5sZW5ndGg9eDtyZXR1cm4gc31hLnNldChvLG4pO3MubGVuZ3RoPW8ubGVuZ3RoO3JldHVybiBzfWZ1bmN0aW9uIHJlYWROYW1lVGFibGUoZSl7Y29uc3Qgcj0odC5zdGFydHx8MCkrZS5vZmZzZXQ7dC5wb3M9cjtjb25zdCBhPVtbXSxbXV0sbj1bXSxpPWUubGVuZ3RoLHM9citpO2lmKDAhPT10LmdldFVpbnQxNigpfHxpPDYpcmV0dXJuW2Esbl07Y29uc3Qgbz10LmdldFVpbnQxNigpLGM9dC5nZXRVaW50MTYoKTtsZXQgbCxoO2ZvcihsPTA7bDxvJiZ0LnBvcysxMjw9cztsKyspe2NvbnN0IGU9e3BsYXRmb3JtOnQuZ2V0VWludDE2KCksZW5jb2Rpbmc6dC5nZXRVaW50MTYoKSxsYW5ndWFnZTp0LmdldFVpbnQxNigpLG5hbWU6dC5nZXRVaW50MTYoKSxsZW5ndGg6dC5nZXRVaW50MTYoKSxvZmZzZXQ6dC5nZXRVaW50MTYoKX07KGlzTWFjTmFtZVJlY29yZChlKXx8aXNXaW5OYW1lUmVjb3JkKGUpKSYmbi5wdXNoKGUpfWZvcihsPTAsaD1uLmxlbmd0aDtsPGg7bCsrKXtjb25zdCBlPW5bbF07aWYoZS5sZW5ndGg8PTApY29udGludWU7Y29uc3QgaT1yK2MrZS5vZmZzZXQ7aWYoaStlLmxlbmd0aD5zKWNvbnRpbnVlO3QucG9zPWk7Y29uc3Qgbz1lLm5hbWU7aWYoZS5lbmNvZGluZyl7bGV0IHI9IiI7Zm9yKGxldCBhPTAsbj1lLmxlbmd0aDthPG47YSs9MilyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHQuZ2V0VWludDE2KCkpO2FbMV1bb109cn1lbHNlIGFbMF1bb109dC5nZXRTdHJpbmcoZS5sZW5ndGgpfXJldHVyblthLG5dfWNvbnN0IG49WzAsMCwwLDAsMCwwLDAsMCwtMiwtMiwtMiwtMiwwLDAsLTIsLTUsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsMCwwLC0xLDAsLTEsLTEsLTEsLTEsMSwtMSwtOTk5LDAsMSwwLC0xLC0yLDAsLTEsLTIsLTEsLTEsMCwtMSwtMSwwLDAsLTk5OSwtOTk5LC0xLC0xLC0xLC0xLC0yLC05OTksLTIsLTIsLTk5OSwwLC0yLC0yLDAsMCwtMiwwLC0yLDAsMCwwLC0yLC0xLC0xLDEsMSwwLDAsLTEsLTEsLTEsLTEsLTEsLTEsLTEsMCwwLC0xLDAsLTEsLTEsMCwtOTk5LC0xLC0xLC0xLC0xLC0xLC0xLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLC0yLC05OTksLTk5OSwtOTk5LC05OTksLTk5OSwtMSwtMSwtMiwtMiwwLDAsMCwwLC0xLC0xLC05OTksLTIsLTIsMCwwLC0xLC0yLC0yLDAsMCwwLC0xLC0xLC0xLC0yXTtmdW5jdGlvbiBzYW5pdGl6ZVRUUHJvZ3JhbShlLHQpe2xldCByLGEsaSxzLG8sYz1lLmRhdGEsbD0wLGg9MCx1PTA7Y29uc3QgZD1bXSxmPVtdLGc9W107bGV0IHA9dC50b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMsbT0hMSxiPTAseT0wO2ZvcihsZXQgZT1jLmxlbmd0aDtsPGU7KXtjb25zdCBlPWNbbCsrXTtpZig2ND09PWUpe2E9Y1tsKytdO2lmKG18fHkpbCs9YTtlbHNlIGZvcihyPTA7cjxhO3IrKylkLnB1c2goY1tsKytdKX1lbHNlIGlmKDY1PT09ZSl7YT1jW2wrK107aWYobXx8eSlsKz0yKmE7ZWxzZSBmb3Iocj0wO3I8YTtyKyspe2k9Y1tsKytdO2QucHVzaChpPDw4fGNbbCsrXSl9fWVsc2UgaWYoMTc2PT0oMjQ4JmUpKXthPWUtMTc2KzE7aWYobXx8eSlsKz1hO2Vsc2UgZm9yKHI9MDtyPGE7cisrKWQucHVzaChjW2wrK10pfWVsc2UgaWYoMTg0PT0oMjQ4JmUpKXthPWUtMTg0KzE7aWYobXx8eSlsKz0yKmE7ZWxzZSBmb3Iocj0wO3I8YTtyKyspe2k9Y1tsKytdO2QucHVzaChzaWduZWRJbnQxNihpLGNbbCsrXSkpfX1lbHNlIGlmKDQzIT09ZXx8cClpZig0NCE9PWV8fHApe2lmKDQ1PT09ZSlpZihtKXttPSExO2g9bH1lbHNle289Zi5wb3AoKTtpZighbyl7d2FybigiVFQ6IEVOREYgYmFkIHN0YWNrIik7dC5oaW50c1ZhbGlkPSExO3JldHVybn1zPWcucG9wKCk7Yz1vLmRhdGE7bD1vLmk7dC5mdW5jdGlvbnNTdGFja0RlbHRhc1tzXT1kLmxlbmd0aC1vLnN0YWNrVG9wfWVsc2UgaWYoMTM3PT09ZSl7aWYobXx8eSl7d2FybigiVFQ6IG5lc3RlZCBJREVGcyBub3QgYWxsb3dlZCIpO3A9ITB9bT0hMDt1PWx9ZWxzZSBpZig4OD09PWUpKytiO2Vsc2UgaWYoMjc9PT1lKXk9YjtlbHNlIGlmKDg5PT09ZSl7eT09PWImJih5PTApOy0tYn1lbHNlIGlmKDI4PT09ZSYmIW0mJiF5KXtjb25zdCBlPWQuYXQoLTEpO2U+MCYmKGwrPWUtMSl9fWVsc2V7aWYobXx8eSl7d2FybigiVFQ6IG5lc3RlZCBGREVGcyBub3QgYWxsb3dlZCIpO3A9ITB9bT0hMDt1PWw7cz1kLnBvcCgpO3QuZnVuY3Rpb25zRGVmaW5lZFtzXT17ZGF0YTpjLGk6bH19ZWxzZSBpZighbSYmIXkpe3M9ZC5hdCgtMSk7aWYoaXNOYU4ocykpaW5mbygiVFQ6IENBTEwgZW1wdHkgc3RhY2sgKG9yIGludmFsaWQgZW50cnkpLiIpO2Vsc2V7dC5mdW5jdGlvbnNVc2VkW3NdPSEwO2lmKHMgaW4gdC5mdW5jdGlvbnNTdGFja0RlbHRhcyl7Y29uc3QgZT1kLmxlbmd0aCt0LmZ1bmN0aW9uc1N0YWNrRGVsdGFzW3NdO2lmKGU8MCl7d2FybigiVFQ6IENBTEwgaW52YWxpZCBmdW5jdGlvbnMgc3RhY2sgZGVsdGEuIik7dC5oaW50c1ZhbGlkPSExO3JldHVybn1kLmxlbmd0aD1lfWVsc2UgaWYocyBpbiB0LmZ1bmN0aW9uc0RlZmluZWQmJiFnLmluY2x1ZGVzKHMpKXtmLnB1c2goe2RhdGE6YyxpOmwsc3RhY2tUb3A6ZC5sZW5ndGgtMX0pO2cucHVzaChzKTtvPXQuZnVuY3Rpb25zRGVmaW5lZFtzXTtpZighbyl7d2FybigiVFQ6IENBTEwgbm9uLWV4aXN0ZW50IGZ1bmN0aW9uIik7dC5oaW50c1ZhbGlkPSExO3JldHVybn1jPW8uZGF0YTtsPW8uaX19fWlmKCFtJiYheSl7bGV0IHQ9MDtlPD0xNDI/dD1uW2VdOmU+PTE5MiYmZTw9MjIzP3Q9LTE6ZT49MjI0JiYodD0tMik7aWYoZT49MTEzJiZlPD0xMTcpe2E9ZC5wb3AoKTtpc05hTihhKXx8KHQ9MiotYSl9Zm9yKDt0PDAmJmQubGVuZ3RoPjA7KXtkLnBvcCgpO3QrK31mb3IoO3Q+MDspe2QucHVzaChOYU4pO3QtLX19fXQudG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zPXA7Y29uc3Qgdz1bY107bD5jLmxlbmd0aCYmdy5wdXNoKG5ldyBVaW50OEFycmF5KGwtYy5sZW5ndGgpKTtpZih1Pmgpe3dhcm4oIlRUOiBjb21wbGVtZW50aW5nIGEgbWlzc2luZyBmdW5jdGlvbiB0YWlsIik7dy5wdXNoKG5ldyBVaW50OEFycmF5KFszNCw0NV0pKX0hZnVuY3Rpb24gZm9sZFRUVGFibGUoZSx0KXtpZih0Lmxlbmd0aD4xKXtsZXQgcixhLG49MDtmb3Iocj0wLGE9dC5sZW5ndGg7cjxhO3IrKyluKz10W3JdLmxlbmd0aDtuPW4rMyYtNDtjb25zdCBpPW5ldyBVaW50OEFycmF5KG4pO2xldCBzPTA7Zm9yKHI9MCxhPXQubGVuZ3RoO3I8YTtyKyspe2kuc2V0KHRbcl0scyk7cys9dFtyXS5sZW5ndGh9ZS5kYXRhPWk7ZS5sZW5ndGg9bn19KGUsdyl9bGV0IGkscyxvLGM7aWYoaXNUcnVlVHlwZUNvbGxlY3Rpb25GaWxlKHQ9bmV3IFN0cmVhbShuZXcgVWludDhBcnJheSh0LmdldEJ5dGVzKCkpKSkpe2NvbnN0IGU9ZnVuY3Rpb24gcmVhZFRydWVUeXBlQ29sbGVjdGlvbkRhdGEoZSx0KXtjb25zdHtudW1Gb250czpyLG9mZnNldFRhYmxlOmF9PWZ1bmN0aW9uIHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25IZWFkZXIoZSl7Y29uc3QgdD1lLmdldFN0cmluZyg0KTthc3NlcnQoInR0Y2YiPT09dCwiTXVzdCBiZSBhIFRydWVUeXBlIENvbGxlY3Rpb24gZm9udC4iKTtjb25zdCByPWUuZ2V0VWludDE2KCksYT1lLmdldFVpbnQxNigpLG49ZS5nZXRJbnQzMigpPj4+MCxpPVtdO2ZvcihsZXQgdD0wO3Q8bjt0KyspaS5wdXNoKGUuZ2V0SW50MzIoKT4+PjApO2NvbnN0IHM9e3R0Y1RhZzp0LG1ham9yVmVyc2lvbjpyLG1pbm9yVmVyc2lvbjphLG51bUZvbnRzOm4sb2Zmc2V0VGFibGU6aX07c3dpdGNoKHIpe2Nhc2UgMTpyZXR1cm4gcztjYXNlIDI6cy5kc2lnVGFnPWUuZ2V0SW50MzIoKT4+PjA7cy5kc2lnTGVuZ3RoPWUuZ2V0SW50MzIoKT4+PjA7cy5kc2lnT2Zmc2V0PWUuZ2V0SW50MzIoKT4+PjA7cmV0dXJuIHN9dGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFRydWVUeXBlIENvbGxlY3Rpb24gbWFqb3JWZXJzaW9uOiAke3J9LmApfShlKSxuPXQuc3BsaXQoIisiKTtsZXQgaTtmb3IobGV0IHM9MDtzPHI7cysrKXtlLnBvcz0oZS5zdGFydHx8MCkrYVtzXTtjb25zdCByPXJlYWRPcGVuVHlwZUhlYWRlcihlKSxvPXJlYWRUYWJsZXMoZSxyLm51bVRhYmxlcyk7aWYoIW8ubmFtZSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1RydWVUeXBlIENvbGxlY3Rpb24gZm9udCBtdXN0IGNvbnRhaW4gYSAibmFtZSIgdGFibGUuJyk7Y29uc3RbY109cmVhZE5hbWVUYWJsZShvLm5hbWUpO2ZvcihsZXQgZT0wLGE9Yy5sZW5ndGg7ZTxhO2UrKylmb3IobGV0IGE9MCxzPWNbZV0ubGVuZ3RoO2E8czthKyspe2NvbnN0IHM9Y1tlXVthXT8ucmVwbGFjZUFsbCgvXHMvZywiIik7aWYocyl7aWYocz09PXQpcmV0dXJue2hlYWRlcjpyLHRhYmxlczpvfTtpZighKG4ubGVuZ3RoPDIpKWZvcihjb25zdCBlIG9mIG4pcz09PWUmJihpPXtuYW1lOmUsaGVhZGVyOnIsdGFibGVzOm99KX19fWlmKGkpe3dhcm4oYFRydWVUeXBlIENvbGxlY3Rpb24gZG9lcyBub3QgY29udGFpbiAiJHt0fSIgZm9udCwgZmFsbGluZyBiYWNrIHRvICIke2kubmFtZX0iIGZvbnQgaW5zdGVhZC5gKTtyZXR1cm57aGVhZGVyOmkuaGVhZGVyLHRhYmxlczppLnRhYmxlc319dGhyb3cgbmV3IEZvcm1hdEVycm9yKGBUcnVlVHlwZSBDb2xsZWN0aW9uIGRvZXMgbm90IGNvbnRhaW4gIiR7dH0iIGZvbnQuYCl9KHQsdGhpcy5uYW1lKTtpPWUuaGVhZGVyO3M9ZS50YWJsZXN9ZWxzZXtpPXJlYWRPcGVuVHlwZUhlYWRlcih0KTtzPXJlYWRUYWJsZXModCxpLm51bVRhYmxlcyl9Y29uc3QgbD0hc1siQ0ZGICJdO2lmKGwpe2lmKCFzLmxvY2EpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdSZXF1aXJlZCAibG9jYSIgdGFibGUgaXMgbm90IGZvdW5kJyk7aWYoIXMuZ2x5Zil7d2FybignUmVxdWlyZWQgImdseWYiIHRhYmxlIGlzIG5vdCBmb3VuZCAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTtzLmdseWY9e3RhZzoiZ2x5ZiIsZGF0YTpuZXcgVWludDhBcnJheSgwKX19dGhpcy5pc09wZW5UeXBlPSExfWVsc2V7Y29uc3QgdD1yLmNvbXBvc2l0ZSYmKHIuY2lkVG9HaWRNYXA/Lmxlbmd0aD4wfHwhKHIuY01hcCBpbnN0YW5jZW9mIElkZW50aXR5Q01hcCkpO2lmKCJPVFRPIj09PWkudmVyc2lvbiYmIXR8fCFzLmhlYWR8fCFzLmhoZWF8fCFzLm1heHB8fCFzLnBvc3Qpe2M9bmV3IFN0cmVhbShzWyJDRkYgIl0uZGF0YSk7bz1uZXcgQ0ZGRm9udChjLHIpO3JldHVybiB0aGlzLmNvbnZlcnQoZSxvLHIpfWRlbGV0ZSBzLmdseWY7ZGVsZXRlIHMubG9jYTtkZWxldGUgcy5mcGdtO2RlbGV0ZSBzLnByZXA7ZGVsZXRlIHNbImN2dCAiXTt0aGlzLmlzT3BlblR5cGU9ITB9aWYoIXMubWF4cCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJtYXhwIiB0YWJsZSBpcyBub3QgZm91bmQnKTt0LnBvcz0odC5zdGFydHx8MCkrcy5tYXhwLm9mZnNldDtsZXQgaD10LmdldEludDMyKCk7Y29uc3QgdT10LmdldFVpbnQxNigpO2lmKDY1NTM2IT09aCYmMjA0ODAhPT1oKXtpZig2PT09cy5tYXhwLmxlbmd0aCloPTIwNDgwO2Vsc2V7aWYoIShzLm1heHAubGVuZ3RoPj0zMikpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCcibWF4cCIgdGFibGUgaGFzIGEgd3JvbmcgdmVyc2lvbiBudW1iZXInKTtoPTY1NTM2fSFmdW5jdGlvbiB3cml0ZVVpbnQzMihlLHQscil7ZVt0KzNdPTI1NSZyO2VbdCsyXT1yPj4+ODtlW3QrMV09cj4+PjE2O2VbdF09cj4+PjI0fShzLm1heHAuZGF0YSwwLGgpfWlmKHIuc2NhbGVGYWN0b3JzPy5sZW5ndGg9PT11JiZsKXtjb25zdHtzY2FsZUZhY3RvcnM6ZX09cix0PWludDE2KHMuaGVhZC5kYXRhWzUwXSxzLmhlYWQuZGF0YVs1MV0pLGE9bmV3IEdseWZUYWJsZSh7Z2x5ZlRhYmxlOnMuZ2x5Zi5kYXRhLGlzR2x5cGhMb2NhdGlvbnNMb25nOnQsbG9jYVRhYmxlOnMubG9jYS5kYXRhLG51bUdseXBoczp1fSk7YS5zY2FsZShlKTtjb25zdHtnbHlmOm4sbG9jYTppLGlzTG9jYXRpb25Mb25nOm99PWEud3JpdGUoKTtzLmdseWYuZGF0YT1uO3MubG9jYS5kYXRhPWk7aWYobyE9PSEhdCl7cy5oZWFkLmRhdGFbNTBdPTA7cy5oZWFkLmRhdGFbNTFdPW8/MTowfWNvbnN0IGM9cy5obXR4LmRhdGE7Zm9yKGxldCB0PTA7dDx1O3QrKyl7Y29uc3Qgcj00KnQsYT1NYXRoLnJvdW5kKGVbdF0qaW50MTYoY1tyXSxjW3IrMV0pKTtjW3JdPWE+PjgmMjU1O2NbcisxXT0yNTUmYTt3cml0ZVNpZ25lZEludDE2KGMscisyLE1hdGgucm91bmQoZVt0XSpzaWduZWRJbnQxNihjW3IrMl0sY1tyKzNdKSkpfX1sZXQgZD11KzEsZj0hMDtpZihkPjY1NTM1KXtmPSExO2Q9dTt3YXJuKCJOb3QgZW5vdWdoIHNwYWNlIGluIGdseWZzIHRvIGR1cGxpY2F0ZSBmaXJzdCBnbHlwaC4iKX1sZXQgZz0wLHA9MDtpZihoPj02NTUzNiYmcy5tYXhwLmxlbmd0aD49MzIpe3QucG9zKz04O2lmKHQuZ2V0VWludDE2KCk+Mil7cy5tYXhwLmRhdGFbMTRdPTA7cy5tYXhwLmRhdGFbMTVdPTJ9dC5wb3MrPTQ7Zz10LmdldFVpbnQxNigpO3QucG9zKz00O3A9dC5nZXRVaW50MTYoKX1zLm1heHAuZGF0YVs0XT1kPj44O3MubWF4cC5kYXRhWzVdPTI1NSZkO2NvbnN0IG09ZnVuY3Rpb24gc2FuaXRpemVUVFByb2dyYW1zKGUsdCxyLGEpe2NvbnN0IG49e2Z1bmN0aW9uc0RlZmluZWQ6W10sZnVuY3Rpb25zVXNlZDpbXSxmdW5jdGlvbnNTdGFja0RlbHRhczpbXSx0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnM6ITEsaGludHNWYWxpZDohMH07ZSYmc2FuaXRpemVUVFByb2dyYW0oZSxuKTt0JiZzYW5pdGl6ZVRUUHJvZ3JhbSh0LG4pO2UmJmZ1bmN0aW9uIGNoZWNrSW52YWxpZEZ1bmN0aW9ucyhlLHQpe2lmKCFlLnRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucylpZihlLmZ1bmN0aW9uc0RlZmluZWQubGVuZ3RoPnQpe3dhcm4oIlRUOiBtb3JlIGZ1bmN0aW9ucyBkZWZpbmVkIHRoYW4gZXhwZWN0ZWQiKTtlLmhpbnRzVmFsaWQ9ITF9ZWxzZSBmb3IobGV0IHI9MCxhPWUuZnVuY3Rpb25zVXNlZC5sZW5ndGg7cjxhO3IrKyl7aWYocj50KXt3YXJuKCJUVDogaW52YWxpZCBmdW5jdGlvbiBpZDogIityKTtlLmhpbnRzVmFsaWQ9ITE7cmV0dXJufWlmKGUuZnVuY3Rpb25zVXNlZFtyXSYmIWUuZnVuY3Rpb25zRGVmaW5lZFtyXSl7d2FybigiVFQ6IHVuZGVmaW5lZCBmdW5jdGlvbjogIityKTtlLmhpbnRzVmFsaWQ9ITE7cmV0dXJufX19KG4sYSk7aWYociYmMSZyLmxlbmd0aCl7Y29uc3QgZT1uZXcgVWludDhBcnJheShyLmxlbmd0aCsxKTtlLnNldChyLmRhdGEpO3IuZGF0YT1lfXJldHVybiBuLmhpbnRzVmFsaWR9KHMuZnBnbSxzLnByZXAsc1siY3Z0ICJdLGcpO2lmKCFtKXtkZWxldGUgcy5mcGdtO2RlbGV0ZSBzLnByZXA7ZGVsZXRlIHNbImN2dCAiXX0hZnVuY3Rpb24gc2FuaXRpemVNZXRyaWNzKGUsdCxyLGEsbixpKXtpZighdCl7ciYmKHIuZGF0YT1udWxsKTtyZXR1cm59ZS5wb3M9KGUuc3RhcnR8fDApK3Qub2Zmc2V0O2UucG9zKz00O2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2UucG9zKz0yO2NvbnN0IHM9ZS5nZXRVaW50MTYoKTtlLnBvcys9ODtlLnBvcys9MjtsZXQgbz1lLmdldFVpbnQxNigpO2lmKDAhPT1zKXtpZighKDImaW50MTYoYS5kYXRhWzQ0XSxhLmRhdGFbNDVdKSkpe3QuZGF0YVsyMl09MDt0LmRhdGFbMjNdPTB9fWlmKG8+bil7aW5mbyhgVGhlIG51bU9mTWV0cmljcyAoJHtvfSkgc2hvdWxkIG5vdCBiZSBncmVhdGVyIHRoYW4gdGhlIG51bUdseXBocyAoJHtufSkuYCk7bz1uO3QuZGF0YVszNF09KDY1MjgwJm8pPj44O3QuZGF0YVszNV09MjU1Jm99Y29uc3QgYz1uLW8tKHIubGVuZ3RoLTQqbz4+MSk7aWYoYz4wKXtjb25zdCBlPW5ldyBVaW50OEFycmF5KHIubGVuZ3RoKzIqYyk7ZS5zZXQoci5kYXRhKTtpZihpKXtlW3IubGVuZ3RoXT1yLmRhdGFbMl07ZVtyLmxlbmd0aCsxXT1yLmRhdGFbM119ci5kYXRhPWV9fSh0LHMuaGhlYSxzLmhtdHgscy5oZWFkLGQsZik7aWYoIXMuaGVhZCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJoZWFkIiB0YWJsZSBpcyBub3QgZm91bmQnKTshZnVuY3Rpb24gc2FuaXRpemVIZWFkKGUsdCxyKXtjb25zdCBhPWUuZGF0YSxuPWZ1bmN0aW9uIGludDMyKGUsdCxyLGEpe3JldHVybihlPDwyNCkrKHQ8PDE2KSsocjw8OCkrYX0oYVswXSxhWzFdLGFbMl0sYVszXSk7aWYobj4+MTYhPTEpe2luZm8oIkF0dGVtcHRpbmcgdG8gZml4IGludmFsaWQgdmVyc2lvbiBpbiBoZWFkIHRhYmxlOiAiK24pO2FbMF09MDthWzFdPTE7YVsyXT0wO2FbM109MH1jb25zdCBpPWludDE2KGFbNTBdLGFbNTFdKTtpZihpPDB8fGk+MSl7aW5mbygiQXR0ZW1wdGluZyB0byBmaXggaW52YWxpZCBpbmRleFRvTG9jRm9ybWF0IGluIGhlYWQgdGFibGU6ICIraSk7Y29uc3QgZT10KzE7aWYocj09PWU8PDEpe2FbNTBdPTA7YVs1MV09MH1lbHNle2lmKHIhPT1lPDwyKXRocm93IG5ldyBGb3JtYXRFcnJvcigiQ291bGQgbm90IGZpeCBpbmRleFRvTG9jRm9ybWF0OiAiK2kpO2FbNTBdPTA7YVs1MV09MX19fShzLmhlYWQsdSxsP3MubG9jYS5sZW5ndGg6MCk7bGV0IGI9T2JqZWN0LmNyZWF0ZShudWxsKTtpZihsKXtjb25zdCBlPWludDE2KHMuaGVhZC5kYXRhWzUwXSxzLmhlYWQuZGF0YVs1MV0pLHQ9ZnVuY3Rpb24gc2FuaXRpemVHbHlwaExvY2F0aW9ucyhlLHQscixhLG4saSxzKXtsZXQgbyxjLGw7aWYoYSl7bz00O2M9ZnVuY3Rpb24gZm9udEl0ZW1EZWNvZGVMb25nKGUsdCl7cmV0dXJuIGVbdF08PDI0fGVbdCsxXTw8MTZ8ZVt0KzJdPDw4fGVbdCszXX07bD1mdW5jdGlvbiBmb250SXRlbUVuY29kZUxvbmcoZSx0LHIpe2VbdF09cj4+PjI0JjI1NTtlW3QrMV09cj4+MTYmMjU1O2VbdCsyXT1yPj44JjI1NTtlW3QrM109MjU1JnJ9fWVsc2V7bz0yO2M9ZnVuY3Rpb24gZm9udEl0ZW1EZWNvZGUoZSx0KXtyZXR1cm4gZVt0XTw8OXxlW3QrMV08PDF9O2w9ZnVuY3Rpb24gZm9udEl0ZW1FbmNvZGUoZSx0LHIpe2VbdF09cj4+OSYyNTU7ZVt0KzFdPXI+PjEmMjU1fX1jb25zdCBoPWk/cisxOnIsdT1vKigxK2gpLGQ9bmV3IFVpbnQ4QXJyYXkodSk7ZC5zZXQoZS5kYXRhLnN1YmFycmF5KDAsdSkpO2UuZGF0YT1kO2NvbnN0IGY9dC5kYXRhLGc9Zi5sZW5ndGgscD1uZXcgVWludDhBcnJheShnKTtsZXQgbSxiO2NvbnN0IHk9W107Zm9yKG09MCxiPTA7bTxyKzE7bSsrLGIrPW8pe2xldCBlPWMoZCxiKTtlPmcmJihlPWcpO3kucHVzaCh7aW5kZXg6bSxvZmZzZXQ6ZSxlbmRPZmZzZXQ6MH0pfXkuc29ydCgoZSx0KT0+ZS5vZmZzZXQtdC5vZmZzZXQpO2ZvcihtPTA7bTxyO20rKyl5W21dLmVuZE9mZnNldD15W20rMV0ub2Zmc2V0O3kuc29ydCgoZSx0KT0+ZS5pbmRleC10LmluZGV4KTtmb3IobT0wO208cjttKyspe2NvbnN0e29mZnNldDplLGVuZE9mZnNldDp0fT15W21dO2lmKDAhPT1lfHwwIT09dClicmVhaztjb25zdCByPXlbbSsxXS5vZmZzZXQ7aWYoMCE9PXIpe3lbbV0uZW5kT2Zmc2V0PXI7YnJlYWt9fWNvbnN0IHc9eS5hdCgtMik7MCE9PXcub2Zmc2V0JiYwPT09dy5lbmRPZmZzZXQmJih3LmVuZE9mZnNldD1nKTtjb25zdCB4PU9iamVjdC5jcmVhdGUobnVsbCk7bGV0IFM9MDtsKGQsMCxTKTtmb3IobT0wLGI9bzttPHI7bSsrLGIrPW8pe2NvbnN0IGU9c2FuaXRpemVHbHlwaChmLHlbbV0ub2Zmc2V0LHlbbV0uZW5kT2Zmc2V0LHAsUyxuKSx0PWUubGVuZ3RoOzA9PT10JiYoeFttXT0hMCk7ZS5zaXplT2ZJbnN0cnVjdGlvbnM+cyYmKHM9ZS5zaXplT2ZJbnN0cnVjdGlvbnMpO1MrPXQ7bChkLGIsUyl9aWYoMD09PVMpe2NvbnN0IGU9bmV3IFVpbnQ4QXJyYXkoWzAsMSwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCw0OSwwXSk7Zm9yKG09MCxiPW87bTxoO20rKyxiKz1vKWwoZCxiLGUubGVuZ3RoKTt0LmRhdGE9ZX1lbHNlIGlmKGkpe2NvbnN0IHI9YyhkLG8pO2lmKHAubGVuZ3RoPnIrUyl0LmRhdGE9cC5zdWJhcnJheSgwLHIrUyk7ZWxzZXt0LmRhdGE9bmV3IFVpbnQ4QXJyYXkocitTKTt0LmRhdGEuc2V0KHAuc3ViYXJyYXkoMCxTKSl9dC5kYXRhLnNldChwLnN1YmFycmF5KDAsciksUyk7bChlLmRhdGEsZC5sZW5ndGgtbyxTK3IpfWVsc2UgdC5kYXRhPXAuc3ViYXJyYXkoMCxTKTtyZXR1cm57bWlzc2luZ0dseXBoczp4LG1heFNpemVPZkluc3RydWN0aW9uczpzfX0ocy5sb2NhLHMuZ2x5Zix1LGUsbSxmLHApO2I9dC5taXNzaW5nR2x5cGhzO2lmKGg+PTY1NTM2JiZzLm1heHAubGVuZ3RoPj0zMil7cy5tYXhwLmRhdGFbMjZdPXQubWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zPj44O3MubWF4cC5kYXRhWzI3XT0yNTUmdC5tYXhTaXplT2ZJbnN0cnVjdGlvbnN9fWlmKCFzLmhoZWEpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdSZXF1aXJlZCAiaGhlYSIgdGFibGUgaXMgbm90IGZvdW5kJyk7aWYoMD09PXMuaGhlYS5kYXRhWzEwXSYmMD09PXMuaGhlYS5kYXRhWzExXSl7cy5oaGVhLmRhdGFbMTBdPTI1NTtzLmhoZWEuZGF0YVsxMV09MjU1fWNvbnN0IHk9e3VuaXRzUGVyRW06aW50MTYocy5oZWFkLmRhdGFbMThdLHMuaGVhZC5kYXRhWzE5XSkseU1heDpzaWduZWRJbnQxNihzLmhlYWQuZGF0YVs0Ml0scy5oZWFkLmRhdGFbNDNdKSx5TWluOnNpZ25lZEludDE2KHMuaGVhZC5kYXRhWzM4XSxzLmhlYWQuZGF0YVszOV0pLGFzY2VudDpzaWduZWRJbnQxNihzLmhoZWEuZGF0YVs0XSxzLmhoZWEuZGF0YVs1XSksZGVzY2VudDpzaWduZWRJbnQxNihzLmhoZWEuZGF0YVs2XSxzLmhoZWEuZGF0YVs3XSksbGluZUdhcDpzaWduZWRJbnQxNihzLmhoZWEuZGF0YVs4XSxzLmhoZWEuZGF0YVs5XSl9O3RoaXMuYXNjZW50PXkuYXNjZW50L3kudW5pdHNQZXJFbTt0aGlzLmRlc2NlbnQ9eS5kZXNjZW50L3kudW5pdHNQZXJFbTt0aGlzLmxpbmVHYXA9eS5saW5lR2FwL3kudW5pdHNQZXJFbTtpZih0aGlzLmNzc0ZvbnRJbmZvPy5saW5lSGVpZ2h0KXt0aGlzLmxpbmVIZWlnaHQ9dGhpcy5jc3NGb250SW5mby5tZXRyaWNzLmxpbmVIZWlnaHQ7dGhpcy5saW5lR2FwPXRoaXMuY3NzRm9udEluZm8ubWV0cmljcy5saW5lR2FwfWVsc2UgdGhpcy5saW5lSGVpZ2h0PXRoaXMuYXNjZW50LXRoaXMuZGVzY2VudCt0aGlzLmxpbmVHYXA7cy5wb3N0JiZmdW5jdGlvbiByZWFkUG9zdFNjcmlwdFRhYmxlKGUscixhKXtjb25zdCBuPSh0LnN0YXJ0fHwwKStlLm9mZnNldDt0LnBvcz1uO2NvbnN0IGk9bitlLmxlbmd0aCxzPXQuZ2V0SW50MzIoKTt0LnNraXAoMjgpO2xldCBvLGMsbD0hMDtzd2l0Y2gocyl7Y2FzZSA2NTUzNjpvPXZhO2JyZWFrO2Nhc2UgMTMxMDcyOmNvbnN0IGU9dC5nZXRVaW50MTYoKTtpZihlIT09YSl7bD0hMTticmVha31jb25zdCBuPVtdO2ZvcihjPTA7YzxlOysrYyl7Y29uc3QgZT10LmdldFVpbnQxNigpO2lmKGU+PTMyNzY4KXtsPSExO2JyZWFrfW4ucHVzaChlKX1pZighbClicmVhaztjb25zdCBoPVtdLHU9W107Zm9yKDt0LnBvczxpOyl7Y29uc3QgZT10LmdldEJ5dGUoKTt1Lmxlbmd0aD1lO2ZvcihjPTA7YzxlOysrYyl1W2NdPVN0cmluZy5mcm9tQ2hhckNvZGUodC5nZXRCeXRlKCkpO2gucHVzaCh1LmpvaW4oIiIpKX1vPVtdO2ZvcihjPTA7YzxlOysrYyl7Y29uc3QgZT1uW2NdO2U8MjU4P28ucHVzaCh2YVtlXSk6by5wdXNoKGhbZS0yNThdKX1icmVhaztjYXNlIDE5NjYwODpicmVhaztkZWZhdWx0Ondhcm4oIlVua25vd24vdW5zdXBwb3J0ZWQgcG9zdCB0YWJsZSB2ZXJzaW9uICIrcyk7bD0hMTtyLmRlZmF1bHRFbmNvZGluZyYmKG89ci5kZWZhdWx0RW5jb2RpbmcpfXIuZ2x5cGhOYW1lcz1vO3JldHVybiBsfShzLnBvc3Qscix1KTtzLnBvc3Q9e3RhZzoicG9zdCIsZGF0YTpjcmVhdGVQb3N0VGFibGUocil9O2NvbnN0IHc9T2JqZWN0LmNyZWF0ZShudWxsKTtmdW5jdGlvbiBoYXNHbHlwaChlKXtyZXR1cm4hYltlXX1pZihyLmNvbXBvc2l0ZSl7Y29uc3QgZT1yLmNpZFRvR2lkTWFwfHxbXSx0PTA9PT1lLmxlbmd0aDtyLmNNYXAuZm9yRWFjaChmdW5jdGlvbihyLGEpeyJzdHJpbmciPT10eXBlb2YgYSYmKGE9Y29udmVydENpZFN0cmluZyhyLGEsITApKTtpZihhPjY1NTM1KXRocm93IG5ldyBGb3JtYXRFcnJvcigiTWF4IHNpemUgb2YgQ0lEIGlzIDY1LDUzNSIpO2xldCBuPS0xO3Q/bj1hOnZvaWQgMCE9PWVbYV0mJihuPWVbYV0pO24+PTAmJm48dSYmaGFzR2x5cGgobikmJih3W3JdPW4pfSl9ZWxzZXtjb25zdCBlPWZ1bmN0aW9uIHJlYWRDbWFwVGFibGUoZSx0LHIsYSl7aWYoIWUpe3dhcm4oIk5vIGNtYXAgdGFibGUgYXZhaWxhYmxlLiIpO3JldHVybntwbGF0Zm9ybUlkOi0xLGVuY29kaW5nSWQ6LTEsbWFwcGluZ3M6W10saGFzU2hvcnRDbWFwOiExfX1sZXQgbixpPSh0LnN0YXJ0fHwwKStlLm9mZnNldDt0LnBvcz1pO3Quc2tpcCgyKTtjb25zdCBzPXQuZ2V0VWludDE2KCk7bGV0IG8sYz0hMTtmb3IobGV0IGU9MDtlPHM7ZSsrKXtjb25zdCBuPXQuZ2V0VWludDE2KCksaT10LmdldFVpbnQxNigpLGw9dC5nZXRJbnQzMigpPj4+MDtsZXQgaD0hMTtpZihvPy5wbGF0Zm9ybUlkIT09bnx8bz8uZW5jb2RpbmdJZCE9PWkpe2lmKDAhPT1ufHwwIT09aSYmMSE9PWkmJjMhPT1pKWlmKDE9PT1uJiYwPT09aSloPSEwO2Vsc2UgaWYoMyE9PW58fDEhPT1pfHwhYSYmbyl7aWYociYmMz09PW4mJjA9PT1pKXtoPSEwO2xldCByPSEwO2lmKGU8cy0xKXtjb25zdCBlPXQucGVla0J5dGVzKDIpO2ludDE2KGVbMF0sZVsxXSk8biYmKHI9ITEpfXImJihjPSEwKX19ZWxzZXtoPSEwO3J8fChjPSEwKX1lbHNlIGg9ITA7aCYmKG89e3BsYXRmb3JtSWQ6bixlbmNvZGluZ0lkOmksb2Zmc2V0Omx9KTtpZihjKWJyZWFrfX1vJiYodC5wb3M9aStvLm9mZnNldCk7aWYoIW98fC0xPT09dC5wZWVrQnl0ZSgpKXt3YXJuKCJDb3VsZCBub3QgZmluZCBhIHByZWZlcnJlZCBjbWFwIHRhYmxlLiIpO3JldHVybntwbGF0Zm9ybUlkOi0xLGVuY29kaW5nSWQ6LTEsbWFwcGluZ3M6W10saGFzU2hvcnRDbWFwOiExfX1jb25zdCBsPXQuZ2V0VWludDE2KCk7bGV0IGg9ITE7Y29uc3QgdT1bXTtsZXQgZCxmO2lmKDA9PT1sKXt0LnNraXAoNCk7Zm9yKGQ9MDtkPDI1NjtkKyspe2NvbnN0IGU9dC5nZXRCeXRlKCk7ZSYmdS5wdXNoKHtjaGFyQ29kZTpkLGdseXBoSWQ6ZX0pfWg9ITB9ZWxzZSBpZigyPT09bCl7dC5za2lwKDQpO2NvbnN0IGU9W107bGV0IHI9MDtmb3IobGV0IGE9MDthPDI1NjthKyspe2NvbnN0IGE9dC5nZXRVaW50MTYoKT4+MztlLnB1c2goYSk7cj1NYXRoLm1heChhLHIpfWNvbnN0IGE9W107Zm9yKGxldCBlPTA7ZTw9cjtlKyspYS5wdXNoKHtmaXJzdENvZGU6dC5nZXRVaW50MTYoKSxlbnRyeUNvdW50OnQuZ2V0VWludDE2KCksaWREZWx0YTpzaWduZWRJbnQxNih0LmdldEJ5dGUoKSx0LmdldEJ5dGUoKSksaWRSYW5nZVBvczp0LnBvcyt0LmdldFVpbnQxNigpfSk7Zm9yKGxldCByPTA7cjwyNTY7cisrKWlmKDA9PT1lW3JdKXt0LnBvcz1hWzBdLmlkUmFuZ2VQb3MrMipyO2Y9dC5nZXRVaW50MTYoKTt1LnB1c2goe2NoYXJDb2RlOnIsZ2x5cGhJZDpmfSl9ZWxzZXtjb25zdCBuPWFbZVtyXV07Zm9yKGQ9MDtkPG4uZW50cnlDb3VudDtkKyspe2NvbnN0IGU9KHI8PDgpK2Qrbi5maXJzdENvZGU7dC5wb3M9bi5pZFJhbmdlUG9zKzIqZDtmPXQuZ2V0VWludDE2KCk7MCE9PWYmJihmPShmK24uaWREZWx0YSklNjU1MzYpO3UucHVzaCh7Y2hhckNvZGU6ZSxnbHlwaElkOmZ9KX19fWVsc2UgaWYoND09PWwpe3Quc2tpcCg0KTtjb25zdCBlPXQuZ2V0VWludDE2KCk+PjE7dC5za2lwKDYpO2NvbnN0IHI9W107bGV0IGE7Zm9yKGE9MDthPGU7YSsrKXIucHVzaCh7ZW5kOnQuZ2V0VWludDE2KCl9KTt0LnNraXAoMik7Zm9yKGE9MDthPGU7YSsrKXJbYV0uc3RhcnQ9dC5nZXRVaW50MTYoKTtmb3IoYT0wO2E8ZTthKyspclthXS5kZWx0YT10LmdldFVpbnQxNigpO2xldCBzLG89MDtmb3IoYT0wO2E8ZTthKyspe249clthXTtjb25zdCBpPXQuZ2V0VWludDE2KCk7aWYoaSl7cz0oaT4+MSktKGUtYSk7bi5vZmZzZXRJbmRleD1zO289TWF0aC5tYXgobyxzK24uZW5kLW4uc3RhcnQrMSl9ZWxzZSBuLm9mZnNldEluZGV4PS0xfWNvbnN0IGM9W107Zm9yKGQ9MDtkPG87ZCsrKWMucHVzaCh0LmdldFVpbnQxNigpKTtmb3IoYT0wO2E8ZTthKyspe249clthXTtpPW4uc3RhcnQ7Y29uc3QgZT1uLmVuZCx0PW4uZGVsdGE7cz1uLm9mZnNldEluZGV4O2ZvcihkPWk7ZDw9ZTtkKyspaWYoNjU1MzUhPT1kKXtmPXM8MD9kOmNbcytkLWldO2Y9Zit0JjY1NTM1O3UucHVzaCh7Y2hhckNvZGU6ZCxnbHlwaElkOmZ9KX19fWVsc2UgaWYoNj09PWwpe3Quc2tpcCg0KTtjb25zdCBlPXQuZ2V0VWludDE2KCkscj10LmdldFVpbnQxNigpO2ZvcihkPTA7ZDxyO2QrKyl7Zj10LmdldFVpbnQxNigpO2NvbnN0IHI9ZStkO3UucHVzaCh7Y2hhckNvZGU6cixnbHlwaElkOmZ9KX19ZWxzZXtpZigxMiE9PWwpe3dhcm4oImNtYXAgdGFibGUgaGFzIHVuc3VwcG9ydGVkIGZvcm1hdDogIitsKTtyZXR1cm57cGxhdGZvcm1JZDotMSxlbmNvZGluZ0lkOi0xLG1hcHBpbmdzOltdLGhhc1Nob3J0Q21hcDohMX19e3Quc2tpcCgxMCk7Y29uc3QgZT10LmdldEludDMyKCk+Pj4wO2ZvcihkPTA7ZDxlO2QrKyl7Y29uc3QgZT10LmdldEludDMyKCk+Pj4wLHI9dC5nZXRJbnQzMigpPj4+MDtsZXQgYT10LmdldEludDMyKCk+Pj4wO2ZvcihsZXQgdD1lO3Q8PXI7dCsrKXUucHVzaCh7Y2hhckNvZGU6dCxnbHlwaElkOmErK30pfX19dS5zb3J0KChlLHQpPT5lLmNoYXJDb2RlLXQuY2hhckNvZGUpO2NvbnN0IGc9W10scD1uZXcgU2V0O2Zvcihjb25zdCBlIG9mIHUpe2NvbnN0e2NoYXJDb2RlOnR9PWU7aWYoIXAuaGFzKHQpKXtwLmFkZCh0KTtnLnB1c2goZSl9fXJldHVybntwbGF0Zm9ybUlkOm8ucGxhdGZvcm1JZCxlbmNvZGluZ0lkOm8uZW5jb2RpbmdJZCxtYXBwaW5nczpnLGhhc1Nob3J0Q21hcDpofX0ocy5jbWFwLHQsdGhpcy5pc1N5bWJvbGljRm9udCxyLmhhc0VuY29kaW5nKSxhPWUucGxhdGZvcm1JZCxuPWUuZW5jb2RpbmdJZCxpPWUubWFwcGluZ3M7bGV0IG89W10sYz0hMTshci5oYXNFbmNvZGluZ3x8Ik1hY1JvbWFuRW5jb2RpbmciIT09ci5iYXNlRW5jb2RpbmdOYW1lJiYiV2luQW5zaUVuY29kaW5nIiE9PXIuYmFzZUVuY29kaW5nTmFtZXx8KG89Z2V0RW5jb2Rpbmcoci5iYXNlRW5jb2RpbmdOYW1lKSk7aWYoci5oYXNFbmNvZGluZyYmIXRoaXMuaXNTeW1ib2xpY0ZvbnQmJigzPT09YSYmMT09PW58fDE9PT1hJiYwPT09bikpe2NvbnN0IGU9Z2EoKTtmb3IobGV0IHQ9MDt0PDI1Njt0Kyspe2xldCBzO3M9dm9pZCAwIT09dGhpcy5kaWZmZXJlbmNlc1t0XT90aGlzLmRpZmZlcmVuY2VzW3RdOm8ubGVuZ3RoJiYiIiE9PW9bdF0/b1t0XTpoYVt0XTtpZighcyljb250aW51ZTtjb25zdCBjPXJlY292ZXJHbHlwaE5hbWUocyxlKTtsZXQgbDszPT09YSYmMT09PW4/bD1lW2NdOjE9PT1hJiYwPT09biYmKGw9bGEuaW5kZXhPZihjKSk7aWYodm9pZCAwPT09bCl7aWYoIXIuZ2x5cGhOYW1lcyYmci5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCYmISh0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKSl7Y29uc3QgZT10aGlzLnRvVW5pY29kZS5nZXQodCk7ZSYmKGw9ZS5jb2RlUG9pbnRBdCgwKSl9aWYodm9pZCAwPT09bCljb250aW51ZX1mb3IoY29uc3QgZSBvZiBpKWlmKGUuY2hhckNvZGU9PT1sKXt3W3RdPWUuZ2x5cGhJZDticmVha319fWVsc2UgaWYoMD09PWEpe2Zvcihjb25zdCBlIG9mIGkpd1tlLmNoYXJDb2RlXT1lLmdseXBoSWQ7Yz0hMH1lbHNlIGlmKDM9PT1hJiYwPT09bilmb3IoY29uc3QgZSBvZiBpKXtsZXQgdD1lLmNoYXJDb2RlO3Q+PTYxNDQwJiZ0PD02MTY5NSYmKHQmPTI1NSk7d1t0XT1lLmdseXBoSWR9ZWxzZSBmb3IoY29uc3QgZSBvZiBpKXdbZS5jaGFyQ29kZV09ZS5nbHlwaElkO2lmKHIuZ2x5cGhOYW1lcyYmKG8ubGVuZ3RofHx0aGlzLmRpZmZlcmVuY2VzLmxlbmd0aCkpZm9yKGxldCBlPTA7ZTwyNTY7KytlKXtpZighYyYmdm9pZCAwIT09d1tlXSljb250aW51ZTtjb25zdCB0PXRoaXMuZGlmZmVyZW5jZXNbZV18fG9bZV07aWYoIXQpY29udGludWU7Y29uc3QgYT1yLmdseXBoTmFtZXMuaW5kZXhPZih0KTthPjAmJmhhc0dseXBoKGEpJiYod1tlXT1hKX19MD09PXcubGVuZ3RoJiYod1swXT0wKTtsZXQgeD1kLTE7Znx8KHg9MCk7aWYoIXIuY3NzRm9udEluZm8pe2NvbnN0IGU9YWRqdXN0TWFwcGluZyh3LGhhc0dseXBoLHgsdGhpcy50b1VuaWNvZGUpO3RoaXMudG9Gb250Q2hhcj1lLnRvRm9udENoYXI7cy5jbWFwPXt0YWc6ImNtYXAiLGRhdGE6Y3JlYXRlQ21hcFRhYmxlKGUuY2hhckNvZGVUb0dseXBoSWQsZS50b1VuaWNvZGVFeHRyYU1hcCxkKX07c1siT1MvMiJdJiZmdW5jdGlvbiB2YWxpZGF0ZU9TMlRhYmxlKGUsdCl7dC5wb3M9KHQuc3RhcnR8fDApK2Uub2Zmc2V0O2NvbnN0IHI9dC5nZXRVaW50MTYoKTt0LnNraXAoNjApO2NvbnN0IGE9dC5nZXRVaW50MTYoKTtpZihyPDQmJjc2OCZhKXJldHVybiExO2lmKHQuZ2V0VWludDE2KCk+dC5nZXRVaW50MTYoKSlyZXR1cm4hMTt0LnNraXAoNik7aWYoMD09PXQuZ2V0VWludDE2KCkpcmV0dXJuITE7ZS5kYXRhWzhdPWUuZGF0YVs5XT0wO3JldHVybiEwfShzWyJPUy8yIl0sdCl8fChzWyJPUy8yIl09e3RhZzoiT1MvMiIsZGF0YTpjcmVhdGVPUzJUYWJsZShyLGUuY2hhckNvZGVUb0dseXBoSWQseSl9KX1pZighbCl0cnl7Yz1uZXcgU3RyZWFtKHNbIkNGRiAiXS5kYXRhKTtvPW5ldyBDRkZQYXJzZXIoYyxyLHhhKS5wYXJzZSgpO28uZHVwbGljYXRlRmlyc3RHbHlwaCgpO2NvbnN0IGU9bmV3IENGRkNvbXBpbGVyKG8pO3NbIkNGRiAiXS5kYXRhPWUuY29tcGlsZSgpfWNhdGNoe3dhcm4oIkZhaWxlZCB0byBjb21waWxlIGZvbnQgIityLmxvYWRlZE5hbWUpfWlmKHMubmFtZSl7Y29uc3RbdCxhXT1yZWFkTmFtZVRhYmxlKHMubmFtZSk7cy5uYW1lLmRhdGE9Y3JlYXRlTmFtZVRhYmxlKGUsdCk7dGhpcy5wc05hbWU9dFswXVs2XXx8bnVsbDtyLmNvbXBvc2l0ZXx8ZnVuY3Rpb24gYWRqdXN0VHJ1ZVR5cGVUb1VuaWNvZGUoZSx0LHIpe2lmKGUuaXNJbnRlcm5hbEZvbnQpcmV0dXJuO2lmKGUuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXApcmV0dXJuO2lmKGUuaGFzRW5jb2RpbmcpcmV0dXJuO2lmKGUudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXApcmV0dXJuO2lmKCF0KXJldHVybjtpZigwPT09ci5sZW5ndGgpcmV0dXJuO2lmKGUuZGVmYXVsdEVuY29kaW5nPT09dWEpcmV0dXJuO2Zvcihjb25zdCBlIG9mIHIpaWYoIWlzV2luTmFtZVJlY29yZChlKSlyZXR1cm47Y29uc3QgYT11YSxuPVtdLGk9Z2EoKTtmb3IoY29uc3QgZSBpbiBhKXtjb25zdCB0PWFbZV07aWYoIiI9PT10KWNvbnRpbnVlO2NvbnN0IHI9aVt0XTt2b2lkIDAhPT1yJiYobltlXT1TdHJpbmcuZnJvbUNoYXJDb2RlKHIpKX1uLmxlbmd0aD4wJiZlLnRvVW5pY29kZS5hbWVuZChuKX0ocix0aGlzLmlzU3ltYm9saWNGb250LGEpfWVsc2Ugcy5uYW1lPXt0YWc6Im5hbWUiLGRhdGE6Y3JlYXRlTmFtZVRhYmxlKHRoaXMubmFtZSl9O2NvbnN0IFM9bmV3IE9wZW5UeXBlRmlsZUJ1aWxkZXIoaS52ZXJzaW9uKTtmb3IoY29uc3QgZSBpbiBzKVMuYWRkVGFibGUoZSxzW2VdLmRhdGEpO3JldHVybiBTLnRvQXJyYXkoKX1jb252ZXJ0KGUsdCxyKXtyLmZpeGVkUGl0Y2g9ITE7ci5idWlsdEluRW5jb2RpbmcmJmZ1bmN0aW9uIGFkanVzdFR5cGUxVG9Vbmljb2RlKGUsdCl7aWYoZS5pc0ludGVybmFsRm9udClyZXR1cm47aWYoZS5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcClyZXR1cm47aWYodD09PWUuZGVmYXVsdEVuY29kaW5nKXJldHVybjtpZihlLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKXJldHVybjtjb25zdCByPVtdLGE9Z2EoKTtmb3IoY29uc3QgbiBpbiB0KXtpZihlLmhhc0VuY29kaW5nJiYoZS5iYXNlRW5jb2RpbmdOYW1lfHx2b2lkIDAhPT1lLmRpZmZlcmVuY2VzW25dKSljb250aW51ZTtjb25zdCBpPWdldFVuaWNvZGVGb3JHbHlwaCh0W25dLGEpOy0xIT09aSYmKHJbbl09U3RyaW5nLmZyb21DaGFyQ29kZShpKSl9ci5sZW5ndGg+MCYmZS50b1VuaWNvZGUuYW1lbmQocil9KHIsci5idWlsdEluRW5jb2RpbmcpO2xldCBuPTE7dCBpbnN0YW5jZW9mIENGRkZvbnQmJihuPXQubnVtR2x5cGhzLTEpO2NvbnN0IGk9dC5nZXRHbHlwaE1hcHBpbmcocik7bGV0IHM9bnVsbCxvPWksYz1udWxsO2lmKCFyLmNzc0ZvbnRJbmZvKXtzPWFkanVzdE1hcHBpbmcoaSx0Lmhhc0dseXBoSWQuYmluZCh0KSxuLHRoaXMudG9Vbmljb2RlKTt0aGlzLnRvRm9udENoYXI9cy50b0ZvbnRDaGFyO289cy5jaGFyQ29kZVRvR2x5cGhJZDtjPXMudG9Vbmljb2RlRXh0cmFNYXB9Y29uc3QgbD10Lm51bUdseXBocztmdW5jdGlvbiBnZXRDaGFyQ29kZXMoZSx0KXtsZXQgcj1udWxsO2Zvcihjb25zdCBhIGluIGUpdD09PWVbYV0mJihyfHw9W10pLnB1c2goMHxhKTtyZXR1cm4gcn1mdW5jdGlvbiBjcmVhdGVDaGFyQ29kZShlLHQpe2Zvcihjb25zdCByIGluIGUpaWYodD09PWVbcl0pcmV0dXJuIDB8cjtzLmNoYXJDb2RlVG9HbHlwaElkW3MubmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZV09dDtyZXR1cm4gcy5uZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlKyt9Y29uc3QgaD10LnNlYWNzO2lmKHMmJmg/Lmxlbmd0aCl7Y29uc3QgZT1yLmZvbnRNYXRyaXh8fGEsbj10LmdldENoYXJzZXQoKSxvPU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGxldCB0IGluIGgpe3R8PTA7Y29uc3Qgcj1oW3RdLGE9aGFbclsyXV0sYz1oYVtyWzNdXSxsPW4uaW5kZXhPZihhKSx1PW4uaW5kZXhPZihjKTtpZihsPDB8fHU8MCljb250aW51ZTtjb25zdCBkPXt4OnJbMF0qZVswXStyWzFdKmVbMl0rZVs0XSx5OnJbMF0qZVsxXStyWzFdKmVbM10rZVs1XX0sZj1nZXRDaGFyQ29kZXMoaSx0KTtpZihmKWZvcihjb25zdCBlIG9mIGYpe2NvbnN0IHQ9cy5jaGFyQ29kZVRvR2x5cGhJZCxyPWNyZWF0ZUNoYXJDb2RlKHQsbCksYT1jcmVhdGVDaGFyQ29kZSh0LHUpO29bZV09e2Jhc2VGb250Q2hhckNvZGU6cixhY2NlbnRGb250Q2hhckNvZGU6YSxhY2NlbnRPZmZzZXQ6ZH19fXIuc2VhY01hcD1vfWNvbnN0IHU9ci5mb250TWF0cml4PzEvTWF0aC5tYXgoLi4uci5mb250TWF0cml4LnNsaWNlKDAsNCkubWFwKE1hdGguYWJzKSk6MWUzLGQ9bmV3IE9wZW5UeXBlRmlsZUJ1aWxkZXIoIk9UVE8iKTtkLmFkZFRhYmxlKCJDRkYgIix0LmRhdGEpO2QuYWRkVGFibGUoIk9TLzIiLGNyZWF0ZU9TMlRhYmxlKHIsbykpO2QuYWRkVGFibGUoImNtYXAiLGNyZWF0ZUNtYXBUYWJsZShvLGMsbCkpO2QuYWRkVGFibGUoImhlYWQiLCJcMAFcMFwwXDBcMBBcMFwwXDBcMFwwXw88w7VcMFwwIitzYWZlU3RyaW5nMTYodSkrIlwwXDBcMFwwwp5cdn4nXDBcMFwwXDDCnlx2fidcMFwwIitzYWZlU3RyaW5nMTYoci5kZXNjZW50KSsiD8O/IitzYWZlU3RyaW5nMTYoci5hc2NlbnQpK3N0cmluZzE2KHIuaXRhbGljQW5nbGU/MjowKSsiXDARXDBcMFwwXDBcMFwwIik7ZC5hZGRUYWJsZSgiaGhlYSIsIlwwAVwwXDAiK3NhZmVTdHJpbmcxNihyLmFzY2VudCkrc2FmZVN0cmluZzE2KHIuZGVzY2VudCkrIlwwXDDDv8O/XDBcMFwwXDBcMFwwIitzYWZlU3RyaW5nMTYoci5jYXBIZWlnaHQpK3NhZmVTdHJpbmcxNihNYXRoLnRhbihyLml0YWxpY0FuZ2xlKSpyLnhIZWlnaHQpKyJcMFwwXDBcMFwwXDBcMFwwXDBcMFwwXDAiK3N0cmluZzE2KGwpKTtkLmFkZFRhYmxlKCJobXR4IixmdW5jdGlvbiBmb250RmllbGRzSG10eCgpe2NvbnN0IGU9dC5jaGFyc3RyaW5ncyxyPXQuY2ZmP3QuY2ZmLndpZHRoczpudWxsO2xldCBhPSJcMFwwXDBcMCI7Zm9yKGxldCB0PTEsbj1sO3Q8bjt0Kyspe2xldCBuPTA7aWYoZSl7Y29uc3Qgcj1lW3QtMV07bj0id2lkdGgiaW4gcj9yLndpZHRoOjB9ZWxzZSByJiYobj1NYXRoLmNlaWwoclt0XXx8MCkpO2ErPXN0cmluZzE2KG4pK3N0cmluZzE2KDApfXJldHVybiBhfSgpKTtkLmFkZFRhYmxlKCJtYXhwIiwiXDBcMFBcMCIrc3RyaW5nMTYobCkpO2QuYWRkVGFibGUoIm5hbWUiLGNyZWF0ZU5hbWVUYWJsZShlKSk7ZC5hZGRUYWJsZSgicG9zdCIsY3JlYXRlUG9zdFRhYmxlKHIpKTtyZXR1cm4gZC50b0FycmF5KCl9Z2V0IF9zcGFjZVdpZHRoKCl7Y29uc3QgZT1bInNwYWNlIiwibWludXMiLCJvbmUiLCJpIiwiSSJdO2xldCB0O2Zvcihjb25zdCByIG9mIGUpe2lmKHIgaW4gdGhpcy53aWR0aHMpe3Q9dGhpcy53aWR0aHNbcl07YnJlYWt9Y29uc3QgZT1nYSgpW3JdO2xldCBhPTA7aWYodGhpcy5jb21wb3NpdGUmJnRoaXMuY01hcC5jb250YWlucyhlKSl7YT10aGlzLmNNYXAubG9va3VwKGUpOyJzdHJpbmciPT10eXBlb2YgYSYmKGE9Y29udmVydENpZFN0cmluZyhlLGEpKX0hYSYmdGhpcy50b1VuaWNvZGUmJihhPXRoaXMudG9Vbmljb2RlLmNoYXJDb2RlT2YoZSkpO2E8PTAmJihhPWUpO3Q9dGhpcy53aWR0aHNbYV07aWYodClicmVha31yZXR1cm4gc2hhZG93KHRoaXMsIl9zcGFjZVdpZHRoIix0fHx0aGlzLmRlZmF1bHRXaWR0aCl9X2NoYXJUb0dseXBoKGUsdD0hMSl7bGV0IHIsYSxuLGk9dGhpcy5fZ2x5cGhDYWNoZVtlXTtpZihpPy5pc1NwYWNlPT09dClyZXR1cm4gaTtsZXQgcz1lO2lmKHRoaXMuY01hcD8uY29udGFpbnMoZSkpe3M9dGhpcy5jTWFwLmxvb2t1cChlKTsic3RyaW5nIj09dHlwZW9mIHMmJihzPWNvbnZlcnRDaWRTdHJpbmcoZSxzKSl9YT10aGlzLndpZHRoc1tzXTsibnVtYmVyIiE9dHlwZW9mIGEmJihhPXRoaXMuZGVmYXVsdFdpZHRoKTtjb25zdCBvPXRoaXMudm1ldHJpY3M/LltzXTtsZXQgYz10aGlzLnRvVW5pY29kZS5nZXQoZSl8fGU7Im51bWJlciI9PXR5cGVvZiBjJiYoYz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMpKTtsZXQgbD12b2lkIDAhPT10aGlzLnRvRm9udENoYXJbZV07cj10aGlzLnRvRm9udENoYXJbZV18fGU7aWYodGhpcy5taXNzaW5nRmlsZSl7Y29uc3QgdD10aGlzLmRpZmZlcmVuY2VzW2VdfHx0aGlzLmRlZmF1bHRFbmNvZGluZ1tlXTtpZigoIi5ub3RkZWYiPT09dHx8IiI9PT10KSYmIlR5cGUxIj09PXRoaXMudHlwZSl7cj0zMjtpZigiIj09PXQpe2F8fD10aGlzLl9zcGFjZVdpZHRoO2M9U3RyaW5nLmZyb21DaGFyQ29kZShyKX19cj1mdW5jdGlvbiBtYXBTcGVjaWFsVW5pY29kZVZhbHVlcyhlKXtyZXR1cm4gZT49NjU1MjAmJmU8PTY1NTM1PzA6ZT49NjI5NzYmJmU8PTYzNzQzP21hKClbZV18fGU6MTczPT09ZT80NTplfShyKX10aGlzLmlzVHlwZTNGb250JiYobj1yKTtsZXQgaD1udWxsO2lmKHRoaXMuc2VhY01hcD8uW2VdKXtsPSEwO2NvbnN0IHQ9dGhpcy5zZWFjTWFwW2VdO3I9dC5iYXNlRm9udENoYXJDb2RlO2g9e2ZvbnRDaGFyOlN0cmluZy5mcm9tQ29kZVBvaW50KHQuYWNjZW50Rm9udENoYXJDb2RlKSxvZmZzZXQ6dC5hY2NlbnRPZmZzZXR9fWxldCB1PSIiOyJudW1iZXIiPT10eXBlb2YgciYmKHI8PTExMTQxMTE/dT1TdHJpbmcuZnJvbUNvZGVQb2ludChyKTp3YXJuKGBjaGFyVG9HbHlwaCAtIGludmFsaWQgZm9udENoYXJDb2RlOiAke3J9YCkpO2lmKHRoaXMubWlzc2luZ0ZpbGUmJnRoaXMudmVydGljYWwmJjE9PT11Lmxlbmd0aCl7Y29uc3QgZT1GYSgpW3UuY2hhckNvZGVBdCgwKV07ZSYmKHU9Yz1TdHJpbmcuZnJvbUNoYXJDb2RlKGUpKX1pPW5ldyBmb250c19HbHlwaChlLHUsYyxoLGEsbyxuLHQsbCk7cmV0dXJuIHRoaXMuX2dseXBoQ2FjaGVbZV09aX1jaGFyc1RvR2x5cGhzKGUpe2xldCB0PXRoaXMuX2NoYXJzQ2FjaGVbZV07aWYodClyZXR1cm4gdDt0PVtdO2lmKHRoaXMuY01hcCl7Y29uc3Qgcj1PYmplY3QuY3JlYXRlKG51bGwpLGE9ZS5sZW5ndGg7bGV0IG49MDtmb3IoO248YTspe3RoaXMuY01hcC5yZWFkQ2hhckNvZGUoZSxuLHIpO2NvbnN0e2NoYXJjb2RlOmEsbGVuZ3RoOml9PXI7bis9aTtjb25zdCBzPXRoaXMuX2NoYXJUb0dseXBoKGEsMT09PWkmJjMyPT09ZS5jaGFyQ29kZUF0KG4tMSkpO3QucHVzaChzKX19ZWxzZSBmb3IobGV0IHI9MCxhPWUubGVuZ3RoO3I8YTsrK3Ipe2NvbnN0IGE9ZS5jaGFyQ29kZUF0KHIpLG49dGhpcy5fY2hhclRvR2x5cGgoYSwzMj09PWEpO3QucHVzaChuKX1yZXR1cm4gdGhpcy5fY2hhcnNDYWNoZVtlXT10fWdldENoYXJQb3NpdGlvbnMoZSl7Y29uc3QgdD1bXTtpZih0aGlzLmNNYXApe2NvbnN0IHI9T2JqZWN0LmNyZWF0ZShudWxsKTtsZXQgYT0wO2Zvcig7YTxlLmxlbmd0aDspe3RoaXMuY01hcC5yZWFkQ2hhckNvZGUoZSxhLHIpO2NvbnN0IG49ci5sZW5ndGg7dC5wdXNoKFthLGErbl0pO2ErPW59fWVsc2UgZm9yKGxldCByPTAsYT1lLmxlbmd0aDtyPGE7KytyKXQucHVzaChbcixyKzFdKTtyZXR1cm4gdH1nZXQgZ2x5cGhDYWNoZVZhbHVlcygpe3JldHVybiBPYmplY3QudmFsdWVzKHRoaXMuX2dseXBoQ2FjaGUpfWVuY29kZVN0cmluZyhlKXtjb25zdCB0PVtdLHI9W10saGFzQ3VycmVudEJ1ZkVycm9ycz0oKT0+dC5sZW5ndGglMj09MSxhPXRoaXMudG9Vbmljb2RlIGluc3RhbmNlb2YgSWRlbnRpdHlUb1VuaWNvZGVNYXA/ZT0+dGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZihlKTplPT50aGlzLnRvVW5pY29kZS5jaGFyQ29kZU9mKFN0cmluZy5mcm9tQ29kZVBvaW50KGUpKTtmb3IobGV0IG49MCxpPWUubGVuZ3RoO248aTtuKyspe2NvbnN0IGk9ZS5jb2RlUG9pbnRBdChuKTtpPjU1Mjk1JiYoaTw1NzM0NHx8aT42NTUzMykmJm4rKztpZih0aGlzLnRvVW5pY29kZSl7Y29uc3QgZT1hKGkpO2lmKC0xIT09ZSl7aWYoaGFzQ3VycmVudEJ1ZkVycm9ycygpKXt0LnB1c2goci5qb2luKCIiKSk7ci5sZW5ndGg9MH1mb3IobGV0IHQ9KHRoaXMuY01hcD90aGlzLmNNYXAuZ2V0Q2hhckNvZGVMZW5ndGgoZSk6MSktMTt0Pj0wO3QtLSlyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShlPj44KnQmMjU1KSk7Y29udGludWV9fWlmKCFoYXNDdXJyZW50QnVmRXJyb3JzKCkpe3QucHVzaChyLmpvaW4oIiIpKTtyLmxlbmd0aD0wfXIucHVzaChTdHJpbmcuZnJvbUNvZGVQb2ludChpKSl9dC5wdXNoKHIuam9pbigiIikpO3JldHVybiB0fX1jbGFzcyBFcnJvckZvbnR7Y29uc3RydWN0b3IoZSl7dGhpcy5lcnJvcj1lO3RoaXMubG9hZGVkTmFtZT0iZ19mb250X2Vycm9yIjt0aGlzLm1pc3NpbmdGaWxlPSEwfWNoYXJzVG9HbHlwaHMoKXtyZXR1cm5bXX1lbmNvZGVTdHJpbmcoZSl7cmV0dXJuW2VdfWV4cG9ydERhdGEoKXtyZXR1cm57ZXJyb3I6dGhpcy5lcnJvcn19fWNvbnN0IGxuPTIsaG49Myx1bj00LGRuPTUsZm49Nixnbj03O2NsYXNzIFBhdHRlcm57Y29uc3RydWN0b3IoKXt1bnJlYWNoYWJsZSgiQ2Fubm90IGluaXRpYWxpemUgUGF0dGVybi4iKX1zdGF0aWMgcGFyc2VTaGFkaW5nKGUsdCxyLGEsbixpKXtjb25zdCBzPWUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtP2UuZGljdDplLG89cy5nZXQoIlNoYWRpbmdUeXBlIik7dHJ5e3N3aXRjaChvKXtjYXNlIGxuOmNhc2UgaG46cmV0dXJuIG5ldyBSYWRpYWxBeGlhbFNoYWRpbmcocyx0LHIsYSxuLGkpO2Nhc2UgdW46Y2FzZSBkbjpjYXNlIGZuOmNhc2UgZ246cmV0dXJuIG5ldyBNZXNoU2hhZGluZyhlLHQscixhLG4saSk7ZGVmYXVsdDp0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVuc3VwcG9ydGVkIFNoYWRpbmdUeXBlOiAiK28pfX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKGUpO3JldHVybiBuZXcgRHVtbXlTaGFkaW5nfX19Y2xhc3MgQmFzZVNoYWRpbmd7c3RhdGljIFNNQUxMX05VTUJFUj0xZS02O2dldElSKCl7dW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgZ2V0SVJgIGNhbGxlZC4iKX19Y2xhc3MgUmFkaWFsQXhpYWxTaGFkaW5nIGV4dGVuZHMgQmFzZVNoYWRpbmd7Y29uc3RydWN0b3IoZSx0LHIsYSxuLGkpe3N1cGVyKCk7dGhpcy5zaGFkaW5nVHlwZT1lLmdldCgiU2hhZGluZ1R5cGUiKTtsZXQgcz0wO3RoaXMuc2hhZGluZ1R5cGU9PT1sbj9zPTQ6dGhpcy5zaGFkaW5nVHlwZT09PWhuJiYocz02KTt0aGlzLmNvb3Jkc0Fycj1lLmdldEFycmF5KCJDb29yZHMiKTtpZighaXNOdW1iZXJBcnJheSh0aGlzLmNvb3Jkc0FycixzKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlJhZGlhbEF4aWFsU2hhZGluZzogSW52YWxpZCAvQ29vcmRzIGFycmF5LiIpO2NvbnN0IG89Q29sb3JTcGFjZVV0aWxzLnBhcnNlKHtjczplLmdldFJhdygiQ1MiKXx8ZS5nZXRSYXcoIkNvbG9yU3BhY2UiKSx4cmVmOnQscmVzb3VyY2VzOnIscGRmRnVuY3Rpb25GYWN0b3J5OmEsZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOm4sbG9jYWxDb2xvclNwYWNlQ2FjaGU6aX0pO3RoaXMuYmJveD1sb29rdXBOb3JtYWxSZWN0KGUuZ2V0QXJyYXkoIkJCb3giKSxudWxsKTtsZXQgYz0wLGw9MTtjb25zdCBoPWUuZ2V0QXJyYXkoIkRvbWFpbiIpO2lzTnVtYmVyQXJyYXkoaCwyKSYmKFtjLGxdPWgpO2xldCB1PSExLGQ9ITE7Y29uc3QgZj1lLmdldEFycmF5KCJFeHRlbmQiKTsoZnVuY3Rpb24gaXNCb29sZWFuQXJyYXkoZSx0KXtyZXR1cm4gQXJyYXkuaXNBcnJheShlKSYmKG51bGw9PT10fHxlLmxlbmd0aD09PXQpJiZlLmV2ZXJ5KGU9PiJib29sZWFuIj09dHlwZW9mIGUpfSkoZiwyKSYmKFt1LGRdPWYpO2lmKCEodGhpcy5zaGFkaW5nVHlwZSE9PWhufHx1JiZkKSl7Y29uc3RbZSx0LHIsYSxuLGldPXRoaXMuY29vcmRzQXJyLHM9TWF0aC5oeXBvdChlLWEsdC1uKTtyPD1pK3MmJmk8PXIrcyYmd2FybigiVW5zdXBwb3J0ZWQgcmFkaWFsIGdyYWRpZW50LiIpfXRoaXMuZXh0ZW5kU3RhcnQ9dTt0aGlzLmV4dGVuZEVuZD1kO2NvbnN0IGc9ZS5nZXRSYXcoIkZ1bmN0aW9uIikscD1hLmNyZWF0ZShnLCEwKSxtPShsLWMpLzg0MCxiPXRoaXMuY29sb3JTdG9wcz1bXTtpZihjPj1sfHxtPD0wKXtpbmZvKCJCYWQgc2hhZGluZyBkb21haW4uIik7cmV0dXJufWNvbnN0IHk9bmV3IEZsb2F0MzJBcnJheShvLm51bUNvbXBzKSx3PW5ldyBGbG9hdDMyQXJyYXkoMSk7bGV0IHg9MDt3WzBdPWM7cCh3LDAseSwwKTtjb25zdCBTPW5ldyBVaW50OENsYW1wZWRBcnJheSgzKTtvLmdldFJnYih5LDAsUyk7bGV0W2ssQyx2XT1TO2IucHVzaChbMCxVdGlsLm1ha2VIZXhDb2xvcihrLEMsdildKTtsZXQgVD0xO3dbMF09YyttO3AodywwLHksMCk7by5nZXRSZ2IoeSwwLFMpO2xldFtPLE0sRF09UyxSPU8taysxLEU9TS1DKzEsTj1ELXYrMSxfPU8tay0xLEw9TS1DLTEsaj1ELXYtMTtmb3IobGV0IGU9MjtlPDg0MDtlKyspe3dbMF09YytlKm07cCh3LDAseSwwKTtvLmdldFJnYih5LDAsUyk7Y29uc3RbdCxyLGFdPVMsbj1lLXg7Uj1NYXRoLm1pbihSLCh0LWsrMSkvbik7RT1NYXRoLm1pbihFLChyLUMrMSkvbik7Tj1NYXRoLm1pbihOLChhLXYrMSkvbik7Xz1NYXRoLm1heChfLCh0LWstMSkvbik7TD1NYXRoLm1heChMLChyLUMtMSkvbik7aj1NYXRoLm1heChqLChhLXYtMSkvbik7aWYoIShfPD1SJiZMPD1FJiZqPD1OKSl7Y29uc3QgZT1VdGlsLm1ha2VIZXhDb2xvcihPLE0sRCk7Yi5wdXNoKFtULzg0MCxlXSk7Uj10LU8rMTtFPXItTSsxO049YS1EKzE7Xz10LU8tMTtMPXItTS0xO2o9YS1ELTE7eD1UO2s9TztDPU07dj1EfVQ9ZTtPPXQ7TT1yO0Q9YX1iLnB1c2goWzEsVXRpbC5tYWtlSGV4Q29sb3IoTyxNLEQpXSk7bGV0IFU9InRyYW5zcGFyZW50IjtlLmhhcygiQmFja2dyb3VuZCIpJiYoVT1vLmdldFJnYkhleChlLmdldCgiQmFja2dyb3VuZCIpLDApKTtpZighdSl7Yi51bnNoaWZ0KFswLFVdKTtiWzFdWzBdKz1CYXNlU2hhZGluZy5TTUFMTF9OVU1CRVJ9aWYoIWQpe2IuYXQoLTEpWzBdLT1CYXNlU2hhZGluZy5TTUFMTF9OVU1CRVI7Yi5wdXNoKFsxLFVdKX10aGlzLmNvbG9yU3RvcHM9Yn1nZXRJUigpe2NvbnN0e2Nvb3Jkc0FycjplLHNoYWRpbmdUeXBlOnR9PXRoaXM7bGV0IHIsYSxuLGkscztpZih0PT09bG4pe2E9W2VbMF0sZVsxXV07bj1bZVsyXSxlWzNdXTtpPW51bGw7cz1udWxsO3I9ImF4aWFsIn1lbHNlIGlmKHQ9PT1obil7YT1bZVswXSxlWzFdXTtuPVtlWzNdLGVbNF1dO2k9ZVsyXTtzPWVbNV07cj0icmFkaWFsIn1lbHNlIHVucmVhY2hhYmxlKGBnZXRQYXR0ZXJuIHR5cGUgdW5rbm93bjogJHt0fWApO3JldHVyblsiUmFkaWFsQXhpYWwiLHIsdGhpcy5iYm94LHRoaXMuY29sb3JTdG9wcyxhLG4saSxzXX19Y2xhc3MgTWVzaFN0cmVhbVJlYWRlcntjb25zdHJ1Y3RvcihlLHQpe3RoaXMuc3RyZWFtPWU7dGhpcy5jb250ZXh0PXQ7dGhpcy5idWZmZXI9MDt0aGlzLmJ1ZmZlckxlbmd0aD0wO2NvbnN0IHI9dC5udW1Db21wczt0aGlzLnRtcENvbXBzQnVmPW5ldyBGbG9hdDMyQXJyYXkocik7Y29uc3QgYT10LmNvbG9yU3BhY2UubnVtQ29tcHM7dGhpcy50bXBDc0NvbXBzQnVmPXQuY29sb3JGbj9uZXcgRmxvYXQzMkFycmF5KGEpOnRoaXMudG1wQ29tcHNCdWZ9Z2V0IGhhc0RhdGEoKXtpZih0aGlzLnN0cmVhbS5lbmQpcmV0dXJuIHRoaXMuc3RyZWFtLnBvczx0aGlzLnN0cmVhbS5lbmQ7aWYodGhpcy5idWZmZXJMZW5ndGg+MClyZXR1cm4hMDtjb25zdCBlPXRoaXMuc3RyZWFtLmdldEJ5dGUoKTtpZihlPDApcmV0dXJuITE7dGhpcy5idWZmZXI9ZTt0aGlzLmJ1ZmZlckxlbmd0aD04O3JldHVybiEwfXJlYWRCaXRzKGUpe2NvbnN0e3N0cmVhbTp0fT10aGlzO2xldHtidWZmZXI6cixidWZmZXJMZW5ndGg6YX09dGhpcztpZigzMj09PWUpe2lmKDA9PT1hKXJldHVybiB0LmdldEludDMyKCk+Pj4wO3I9cjw8MjR8dC5nZXRCeXRlKCk8PDE2fHQuZ2V0Qnl0ZSgpPDw4fHQuZ2V0Qnl0ZSgpO2NvbnN0IGU9dC5nZXRCeXRlKCk7dGhpcy5idWZmZXI9ZSYoMTw8YSktMTtyZXR1cm4ocjw8OC1hfCgyNTUmZSk+PmEpPj4+MH1pZig4PT09ZSYmMD09PWEpcmV0dXJuIHQuZ2V0Qnl0ZSgpO2Zvcig7YTxlOyl7cj1yPDw4fHQuZ2V0Qnl0ZSgpO2ErPTh9YS09ZTt0aGlzLmJ1ZmZlckxlbmd0aD1hO3RoaXMuYnVmZmVyPXImKDE8PGEpLTE7cmV0dXJuIHI+PmF9YWxpZ24oKXt0aGlzLmJ1ZmZlcj0wO3RoaXMuYnVmZmVyTGVuZ3RoPTB9cmVhZEZsYWcoKXtyZXR1cm4gdGhpcy5yZWFkQml0cyh0aGlzLmNvbnRleHQuYml0c1BlckZsYWcpfXJlYWRDb29yZGluYXRlKCl7Y29uc3R7Yml0c1BlckNvb3JkaW5hdGU6ZSxkZWNvZGU6dH09dGhpcy5jb250ZXh0LHI9dGhpcy5yZWFkQml0cyhlKSxhPXRoaXMucmVhZEJpdHMoZSksbj1lPDMyPzEvKCgxPDxlKS0xKToyLjMyODMwNjQzNjUzODY5NjNlLTEwO3JldHVybltyKm4qKHRbMV0tdFswXSkrdFswXSxhKm4qKHRbM10tdFsyXSkrdFsyXV19cmVhZENvbXBvbmVudHMoKXtjb25zdHtiaXRzUGVyQ29tcG9uZW50OmUsY29sb3JGbjp0LGNvbG9yU3BhY2U6cixkZWNvZGU6YSxudW1Db21wczpufT10aGlzLmNvbnRleHQsaT1lPDMyPzEvKCgxPDxlKS0xKToyLjMyODMwNjQzNjUzODY5NjNlLTEwLHM9dGhpcy50bXBDb21wc0J1Zjtmb3IobGV0IHQ9MCxyPTQ7dDxuO3QrKyxyKz0yKXtjb25zdCBuPXRoaXMucmVhZEJpdHMoZSk7c1t0XT1uKmkqKGFbcisxXS1hW3JdKSthW3JdfWNvbnN0IG89dGhpcy50bXBDc0NvbXBzQnVmO3Q/LihzLDAsbywwKTtyZXR1cm4gci5nZXRSZ2IobywwKX19bGV0IHBuPU9iamVjdC5jcmVhdGUobnVsbCk7ZnVuY3Rpb24gZ2V0QihlKXtyZXR1cm4gcG5bZV18fD1mdW5jdGlvbiBidWlsZEIoZSl7Y29uc3QgdD1bXTtmb3IobGV0IHI9MDtyPD1lO3IrKyl7Y29uc3QgYT1yL2Usbj0xLWE7dC5wdXNoKG5ldyBGbG9hdDMyQXJyYXkoW24qKjMsMyphKm4qKjIsMyphKioyKm4sYSoqM10pKX1yZXR1cm4gdH0oZSl9Y2xhc3MgTWVzaFNoYWRpbmcgZXh0ZW5kcyBCYXNlU2hhZGluZ3tzdGF0aWMgTUlOX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQ9MztzdGF0aWMgTUFYX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQ9MjA7c3RhdGljIFRSSUFOR0xFX0RFTlNJVFk9MjA7Y29uc3RydWN0b3IoZSx0LHIsYSxuLGkpe3N1cGVyKCk7aWYoIShlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNZXNoIGRhdGEgaXMgbm90IGEgc3RyZWFtIik7Y29uc3Qgcz1lLmRpY3Q7dGhpcy5zaGFkaW5nVHlwZT1zLmdldCgiU2hhZGluZ1R5cGUiKTt0aGlzLmJib3g9bG9va3VwTm9ybWFsUmVjdChzLmdldEFycmF5KCJCQm94IiksbnVsbCk7Y29uc3Qgbz1Db2xvclNwYWNlVXRpbHMucGFyc2Uoe2NzOnMuZ2V0UmF3KCJDUyIpfHxzLmdldFJhdygiQ29sb3JTcGFjZSIpLHhyZWY6dCxyZXNvdXJjZXM6cixwZGZGdW5jdGlvbkZhY3Rvcnk6YSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6bixsb2NhbENvbG9yU3BhY2VDYWNoZTppfSk7dGhpcy5iYWNrZ3JvdW5kPXMuaGFzKCJCYWNrZ3JvdW5kIik/by5nZXRSZ2Iocy5nZXQoIkJhY2tncm91bmQiKSwwKTpudWxsO2NvbnN0IGM9cy5nZXRSYXcoIkZ1bmN0aW9uIiksbD1jP2EuY3JlYXRlKGMsITApOm51bGw7dGhpcy5jb29yZHM9W107dGhpcy5jb2xvcnM9W107dGhpcy5maWd1cmVzPVtdO2NvbnN0IGg9e2JpdHNQZXJDb29yZGluYXRlOnMuZ2V0KCJCaXRzUGVyQ29vcmRpbmF0ZSIpLGJpdHNQZXJDb21wb25lbnQ6cy5nZXQoIkJpdHNQZXJDb21wb25lbnQiKSxiaXRzUGVyRmxhZzpzLmdldCgiQml0c1BlckZsYWciKSxkZWNvZGU6cy5nZXRBcnJheSgiRGVjb2RlIiksY29sb3JGbjpsLGNvbG9yU3BhY2U6byxudW1Db21wczpsPzE6by5udW1Db21wc30sdT1uZXcgTWVzaFN0cmVhbVJlYWRlcihlLGgpO2xldCBkPSExO3N3aXRjaCh0aGlzLnNoYWRpbmdUeXBlKXtjYXNlIHVuOnRoaXMuX2RlY29kZVR5cGU0U2hhZGluZyh1KTticmVhaztjYXNlIGRuOmNvbnN0IGU9MHxzLmdldCgiVmVydGljZXNQZXJSb3ciKTtpZihlPDIpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFZlcnRpY2VzUGVyUm93Iik7dGhpcy5fZGVjb2RlVHlwZTVTaGFkaW5nKHUsZSk7YnJlYWs7Y2FzZSBmbjp0aGlzLl9kZWNvZGVUeXBlNlNoYWRpbmcodSk7ZD0hMDticmVhaztjYXNlIGduOnRoaXMuX2RlY29kZVR5cGU3U2hhZGluZyh1KTtkPSEwO2JyZWFrO2RlZmF1bHQ6dW5yZWFjaGFibGUoIlVuc3VwcG9ydGVkIG1lc2ggdHlwZS4iKX1pZihkKXt0aGlzLl91cGRhdGVCb3VuZHMoKTtmb3IobGV0IGU9MCx0PXRoaXMuZmlndXJlcy5sZW5ndGg7ZTx0O2UrKyl0aGlzLl9idWlsZEZpZ3VyZUZyb21QYXRjaChlKX10aGlzLl91cGRhdGVCb3VuZHMoKTt0aGlzLl9wYWNrRGF0YSgpfV9kZWNvZGVUeXBlNFNoYWRpbmcoZSl7Y29uc3QgdD10aGlzLmNvb3JkcyxyPXRoaXMuY29sb3JzLGE9W10sbj1bXTtsZXQgaT0wO2Zvcig7ZS5oYXNEYXRhOyl7Y29uc3Qgcz1lLnJlYWRGbGFnKCksbz1lLnJlYWRDb29yZGluYXRlKCksYz1lLnJlYWRDb21wb25lbnRzKCk7aWYoMD09PWkpe2lmKCEoMDw9cyYmczw9MikpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbmtub3duIHR5cGU0IGZsYWciKTtzd2l0Y2gocyl7Y2FzZSAwOmk9MzticmVhaztjYXNlIDE6bi5wdXNoKG4uYXQoLTIpLG4uYXQoLTEpKTtpPTE7YnJlYWs7Y2FzZSAyOm4ucHVzaChuLmF0KC0zKSxuLmF0KC0xKSk7aT0xfWEucHVzaChzKX1uLnB1c2godC5sZW5ndGgpO3QucHVzaChvKTtyLnB1c2goYyk7aS0tO2UuYWxpZ24oKX10aGlzLmZpZ3VyZXMucHVzaCh7dHlwZToidHJpYW5nbGVzIixjb29yZHM6bmV3IEludDMyQXJyYXkobiksY29sb3JzOm5ldyBJbnQzMkFycmF5KG4pfSl9X2RlY29kZVR5cGU1U2hhZGluZyhlLHQpe2NvbnN0IHI9dGhpcy5jb29yZHMsYT10aGlzLmNvbG9ycyxuPVtdO2Zvcig7ZS5oYXNEYXRhOyl7Y29uc3QgdD1lLnJlYWRDb29yZGluYXRlKCksaT1lLnJlYWRDb21wb25lbnRzKCk7bi5wdXNoKHIubGVuZ3RoKTtyLnB1c2godCk7YS5wdXNoKGkpfXRoaXMuZmlndXJlcy5wdXNoKHt0eXBlOiJsYXR0aWNlIixjb29yZHM6bmV3IEludDMyQXJyYXkobiksY29sb3JzOm5ldyBJbnQzMkFycmF5KG4pLHZlcnRpY2VzUGVyUm93OnR9KX1fZGVjb2RlVHlwZTZTaGFkaW5nKGUpe2NvbnN0IHQ9dGhpcy5jb29yZHMscj10aGlzLmNvbG9ycyxhPW5ldyBJbnQzMkFycmF5KDE2KSxuPW5ldyBJbnQzMkFycmF5KDQpO2Zvcig7ZS5oYXNEYXRhOyl7Y29uc3QgaT1lLnJlYWRGbGFnKCk7aWYoISgwPD1pJiZpPD0zKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZTYgZmxhZyIpO2NvbnN0IHM9dC5sZW5ndGg7Zm9yKGxldCByPTAsYT0wIT09aT84OjEyO3I8YTtyKyspdC5wdXNoKGUucmVhZENvb3JkaW5hdGUoKSk7Y29uc3Qgbz1yLmxlbmd0aDtmb3IobGV0IHQ9MCxhPTAhPT1pPzI6NDt0PGE7dCsrKXIucHVzaChlLnJlYWRDb21wb25lbnRzKCkpO2xldCBjLGwsaCx1O3N3aXRjaChpKXtjYXNlIDA6YVsxMl09cyszO2FbMTNdPXMrNDthWzE0XT1zKzU7YVsxNV09cys2O2FbOF09cysyO2FbMTFdPXMrNzthWzRdPXMrMTthWzddPXMrODthWzBdPXM7YVsxXT1zKzExO2FbMl09cysxMDthWzNdPXMrOTtuWzJdPW8rMTtuWzNdPW8rMjtuWzBdPW87blsxXT1vKzM7YnJlYWs7Y2FzZSAxOmM9YVsxMl07bD1hWzEzXTtoPWFbMTRdO3U9YVsxNV07YVsxMl09dTthWzEzXT1zKzA7YVsxNF09cysxO2FbMTVdPXMrMjthWzhdPWg7YVsxMV09cyszO2FbNF09bDthWzddPXMrNDthWzBdPWM7YVsxXT1zKzc7YVsyXT1zKzY7YVszXT1zKzU7Yz1uWzJdO2w9blszXTtuWzJdPWw7blszXT1vO25bMF09YztuWzFdPW8rMTticmVhaztjYXNlIDI6Yz1hWzE1XTtsPWFbMTFdO2FbMTJdPWFbM107YVsxM109cyswO2FbMTRdPXMrMTthWzE1XT1zKzI7YVs4XT1hWzddO2FbMTFdPXMrMzthWzRdPWw7YVs3XT1zKzQ7YVswXT1jO2FbMV09cys3O2FbMl09cys2O2FbM109cys1O2M9blszXTtuWzJdPW5bMV07blszXT1vO25bMF09YztuWzFdPW8rMTticmVhaztjYXNlIDM6YVsxMl09YVswXTthWzEzXT1zKzA7YVsxNF09cysxO2FbMTVdPXMrMjthWzhdPWFbMV07YVsxMV09cyszO2FbNF09YVsyXTthWzddPXMrNDthWzBdPWFbM107YVsxXT1zKzc7YVsyXT1zKzY7YVszXT1zKzU7blsyXT1uWzBdO25bM109bztuWzBdPW5bMV07blsxXT1vKzF9YVs1XT10Lmxlbmd0aDt0LnB1c2goWygtNCp0W2FbMF1dWzBdLXRbYVsxNV1dWzBdKzYqKHRbYVs0XV1bMF0rdFthWzFdXVswXSktMioodFthWzEyXV1bMF0rdFthWzNdXVswXSkrMyoodFthWzEzXV1bMF0rdFthWzddXVswXSkpLzksKC00KnRbYVswXV1bMV0tdFthWzE1XV1bMV0rNioodFthWzRdXVsxXSt0W2FbMV1dWzFdKS0yKih0W2FbMTJdXVsxXSt0W2FbM11dWzFdKSszKih0W2FbMTNdXVsxXSt0W2FbN11dWzFdKSkvOV0pO2FbNl09dC5sZW5ndGg7dC5wdXNoKFsoLTQqdFthWzNdXVswXS10W2FbMTJdXVswXSs2Kih0W2FbMl1dWzBdK3RbYVs3XV1bMF0pLTIqKHRbYVswXV1bMF0rdFthWzE1XV1bMF0pKzMqKHRbYVs0XV1bMF0rdFthWzE0XV1bMF0pKS85LCgtNCp0W2FbM11dWzFdLXRbYVsxMl1dWzFdKzYqKHRbYVsyXV1bMV0rdFthWzddXVsxXSktMioodFthWzBdXVsxXSt0W2FbMTVdXVsxXSkrMyoodFthWzRdXVsxXSt0W2FbMTRdXVsxXSkpLzldKTthWzldPXQubGVuZ3RoO3QucHVzaChbKC00KnRbYVsxMl1dWzBdLXRbYVszXV1bMF0rNioodFthWzhdXVswXSt0W2FbMTNdXVswXSktMioodFthWzBdXVswXSt0W2FbMTVdXVswXSkrMyoodFthWzExXV1bMF0rdFthWzFdXVswXSkpLzksKC00KnRbYVsxMl1dWzFdLXRbYVszXV1bMV0rNioodFthWzhdXVsxXSt0W2FbMTNdXVsxXSktMioodFthWzBdXVsxXSt0W2FbMTVdXVsxXSkrMyoodFthWzExXV1bMV0rdFthWzFdXVsxXSkpLzldKTthWzEwXT10Lmxlbmd0aDt0LnB1c2goWygtNCp0W2FbMTVdXVswXS10W2FbMF1dWzBdKzYqKHRbYVsxMV1dWzBdK3RbYVsxNF1dWzBdKS0yKih0W2FbMTJdXVswXSt0W2FbM11dWzBdKSszKih0W2FbMl1dWzBdK3RbYVs4XV1bMF0pKS85LCgtNCp0W2FbMTVdXVsxXS10W2FbMF1dWzFdKzYqKHRbYVsxMV1dWzFdK3RbYVsxNF1dWzFdKS0yKih0W2FbMTJdXVsxXSt0W2FbM11dWzFdKSszKih0W2FbMl1dWzFdK3RbYVs4XV1bMV0pKS85XSk7dGhpcy5maWd1cmVzLnB1c2goe3R5cGU6InBhdGNoIixjb29yZHM6bmV3IEludDMyQXJyYXkoYSksY29sb3JzOm5ldyBJbnQzMkFycmF5KG4pfSl9fV9kZWNvZGVUeXBlN1NoYWRpbmcoZSl7Y29uc3QgdD10aGlzLmNvb3JkcyxyPXRoaXMuY29sb3JzLGE9bmV3IEludDMyQXJyYXkoMTYpLG49bmV3IEludDMyQXJyYXkoNCk7Zm9yKDtlLmhhc0RhdGE7KXtjb25zdCBpPWUucmVhZEZsYWcoKTtpZighKDA8PWkmJmk8PTMpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNyBmbGFnIik7Y29uc3Qgcz10Lmxlbmd0aDtmb3IobGV0IHI9MCxhPTAhPT1pPzEyOjE2O3I8YTtyKyspdC5wdXNoKGUucmVhZENvb3JkaW5hdGUoKSk7Y29uc3Qgbz1yLmxlbmd0aDtmb3IobGV0IHQ9MCxhPTAhPT1pPzI6NDt0PGE7dCsrKXIucHVzaChlLnJlYWRDb21wb25lbnRzKCkpO2xldCBjLGwsaCx1O3N3aXRjaChpKXtjYXNlIDA6YVsxMl09cyszO2FbMTNdPXMrNDthWzE0XT1zKzU7YVsxNV09cys2O2FbOF09cysyO2FbOV09cysxMzthWzEwXT1zKzE0O2FbMTFdPXMrNzthWzRdPXMrMTthWzVdPXMrMTI7YVs2XT1zKzE1O2FbN109cys4O2FbMF09czthWzFdPXMrMTE7YVsyXT1zKzEwO2FbM109cys5O25bMl09bysxO25bM109bysyO25bMF09bztuWzFdPW8rMzticmVhaztjYXNlIDE6Yz1hWzEyXTtsPWFbMTNdO2g9YVsxNF07dT1hWzE1XTthWzEyXT11O2FbMTNdPXMrMDthWzE0XT1zKzE7YVsxNV09cysyO2FbOF09aDthWzldPXMrOTthWzEwXT1zKzEwO2FbMTFdPXMrMzthWzRdPWw7YVs1XT1zKzg7YVs2XT1zKzExO2FbN109cys0O2FbMF09YzthWzFdPXMrNzthWzJdPXMrNjthWzNdPXMrNTtjPW5bMl07bD1uWzNdO25bMl09bDtuWzNdPW87blswXT1jO25bMV09bysxO2JyZWFrO2Nhc2UgMjpjPWFbMTVdO2w9YVsxMV07YVsxMl09YVszXTthWzEzXT1zKzA7YVsxNF09cysxO2FbMTVdPXMrMjthWzhdPWFbN107YVs5XT1zKzk7YVsxMF09cysxMDthWzExXT1zKzM7YVs0XT1sO2FbNV09cys4O2FbNl09cysxMTthWzddPXMrNDthWzBdPWM7YVsxXT1zKzc7YVsyXT1zKzY7YVszXT1zKzU7Yz1uWzNdO25bMl09blsxXTtuWzNdPW87blswXT1jO25bMV09bysxO2JyZWFrO2Nhc2UgMzphWzEyXT1hWzBdO2FbMTNdPXMrMDthWzE0XT1zKzE7YVsxNV09cysyO2FbOF09YVsxXTthWzldPXMrOTthWzEwXT1zKzEwO2FbMTFdPXMrMzthWzRdPWFbMl07YVs1XT1zKzg7YVs2XT1zKzExO2FbN109cys0O2FbMF09YVszXTthWzFdPXMrNzthWzJdPXMrNjthWzNdPXMrNTtuWzJdPW5bMF07blszXT1vO25bMF09blsxXTtuWzFdPW8rMX10aGlzLmZpZ3VyZXMucHVzaCh7dHlwZToicGF0Y2giLGNvb3JkczpuZXcgSW50MzJBcnJheShhKSxjb2xvcnM6bmV3IEludDMyQXJyYXkobil9KX19X2J1aWxkRmlndXJlRnJvbVBhdGNoKGUpe2NvbnN0IHQ9dGhpcy5maWd1cmVzW2VdO2Fzc2VydCgicGF0Y2giPT09dC50eXBlLCJVbmV4cGVjdGVkIHBhdGNoIG1lc2ggZmlndXJlIik7Y29uc3Qgcj10aGlzLmNvb3JkcyxhPXRoaXMuY29sb3JzLG49dC5jb29yZHMsaT10LmNvbG9ycyxzPU1hdGgubWluKHJbblswXV1bMF0scltuWzNdXVswXSxyW25bMTJdXVswXSxyW25bMTVdXVswXSksbz1NYXRoLm1pbihyW25bMF1dWzFdLHJbblszXV1bMV0scltuWzEyXV1bMV0scltuWzE1XV1bMV0pLGM9TWF0aC5tYXgocltuWzBdXVswXSxyW25bM11dWzBdLHJbblsxMl1dWzBdLHJbblsxNV1dWzBdKSxsPU1hdGgubWF4KHJbblswXV1bMV0scltuWzNdXVsxXSxyW25bMTJdXVsxXSxyW25bMTVdXVsxXSk7bGV0IGg9TWF0aC5jZWlsKChjLXMpKk1lc2hTaGFkaW5nLlRSSUFOR0xFX0RFTlNJVFkvKHRoaXMuYm91bmRzWzJdLXRoaXMuYm91bmRzWzBdKSk7aD1NYXRoQ2xhbXAoaCxNZXNoU2hhZGluZy5NSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCxNZXNoU2hhZGluZy5NQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCk7bGV0IHU9TWF0aC5jZWlsKChsLW8pKk1lc2hTaGFkaW5nLlRSSUFOR0xFX0RFTlNJVFkvKHRoaXMuYm91bmRzWzNdLXRoaXMuYm91bmRzWzFdKSk7dT1NYXRoQ2xhbXAodSxNZXNoU2hhZGluZy5NSU5fU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCxNZXNoU2hhZGluZy5NQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCk7Y29uc3QgZD1oKzEsZj1uZXcgSW50MzJBcnJheSgodSsxKSpkKSxnPW5ldyBJbnQzMkFycmF5KCh1KzEpKmQpO2xldCBwPTA7Y29uc3QgbT1uZXcgVWludDhBcnJheSgzKSxiPW5ldyBVaW50OEFycmF5KDMpLHk9YVtpWzBdXSx3PWFbaVsxXV0seD1hW2lbMl1dLFM9YVtpWzNdXSxrPWdldEIodSksQz1nZXRCKGgpO2ZvcihsZXQgZT0wO2U8PXU7ZSsrKXttWzBdPSh5WzBdKih1LWUpK3hbMF0qZSkvdXwwO21bMV09KHlbMV0qKHUtZSkreFsxXSplKS91fDA7bVsyXT0oeVsyXSoodS1lKSt4WzJdKmUpL3V8MDtiWzBdPSh3WzBdKih1LWUpK1NbMF0qZSkvdXwwO2JbMV09KHdbMV0qKHUtZSkrU1sxXSplKS91fDA7YlsyXT0od1syXSoodS1lKStTWzJdKmUpL3V8MDtmb3IobGV0IHQ9MDt0PD1oO3QrKyxwKyspe2lmKCEoMCE9PWUmJmUhPT11fHwwIT09dCYmdCE9PWgpKWNvbnRpbnVlO2xldCBpPTAscz0wLG89MDtmb3IobGV0IGE9MDthPD0zO2ErKylmb3IobGV0IGM9MDtjPD0zO2MrKyxvKyspe2NvbnN0IGw9a1tlXVthXSpDW3RdW2NdO2krPXJbbltvXV1bMF0qbDtzKz1yW25bb11dWzFdKmx9ZltwXT1yLmxlbmd0aDtyLnB1c2goW2ksc10pO2dbcF09YS5sZW5ndGg7Y29uc3QgYz1uZXcgVWludDhBcnJheSgzKTtjWzBdPShtWzBdKihoLXQpK2JbMF0qdCkvaHwwO2NbMV09KG1bMV0qKGgtdCkrYlsxXSp0KS9ofDA7Y1syXT0obVsyXSooaC10KStiWzJdKnQpL2h8MDthLnB1c2goYyl9fWZbMF09blswXTtnWzBdPWlbMF07ZltoXT1uWzNdO2dbaF09aVsxXTtmW2QqdV09blsxMl07Z1tkKnVdPWlbMl07ZltkKnUraF09blsxNV07Z1tkKnUraF09aVszXTt0aGlzLmZpZ3VyZXNbZV09e3R5cGU6ImxhdHRpY2UiLGNvb3JkczpmLGNvbG9yczpnLHZlcnRpY2VzUGVyUm93OmR9fV91cGRhdGVCb3VuZHMoKXtsZXQgZT10aGlzLmNvb3Jkc1swXVswXSx0PXRoaXMuY29vcmRzWzBdWzFdLHI9ZSxhPXQ7Zm9yKGxldCBuPTEsaT10aGlzLmNvb3Jkcy5sZW5ndGg7bjxpO24rKyl7Y29uc3QgaT10aGlzLmNvb3Jkc1tuXVswXSxzPXRoaXMuY29vcmRzW25dWzFdO2U9ZT5pP2k6ZTt0PXQ+cz9zOnQ7cj1yPGk/aTpyO2E9YTxzP3M6YX10aGlzLmJvdW5kcz1bZSx0LHIsYV19X3BhY2tEYXRhKCl7bGV0IGUsdCxyLGE7Y29uc3Qgbj10aGlzLmNvb3JkcyxpPW5ldyBGbG9hdDMyQXJyYXkoMipuLmxlbmd0aCk7Zm9yKGU9MCxyPTAsdD1uLmxlbmd0aDtlPHQ7ZSsrKXtjb25zdCB0PW5bZV07aVtyKytdPXRbMF07aVtyKytdPXRbMV19dGhpcy5jb29yZHM9aTtjb25zdCBzPXRoaXMuY29sb3JzLG89bmV3IFVpbnQ4QXJyYXkoMypzLmxlbmd0aCk7Zm9yKGU9MCxyPTAsdD1zLmxlbmd0aDtlPHQ7ZSsrKXtjb25zdCB0PXNbZV07b1tyKytdPXRbMF07b1tyKytdPXRbMV07b1tyKytdPXRbMl19dGhpcy5jb2xvcnM9bztjb25zdCBjPXRoaXMuZmlndXJlcztmb3IoZT0wLHQ9Yy5sZW5ndGg7ZTx0O2UrKyl7Y29uc3QgdD1jW2VdLG49dC5jb29yZHMsaT10LmNvbG9ycztmb3Iocj0wLGE9bi5sZW5ndGg7cjxhO3IrKyl7bltyXSo9MjtpW3JdKj0zfX19Z2V0SVIoKXtjb25zdHtib3VuZHM6ZX09dGhpcztpZihlWzJdLWVbMF09PT0wfHxlWzNdLWVbMV09PT0wKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBNZXNoU2hhZGluZyBib3VuZHM6IFske2V9XS5gKTtyZXR1cm5bIk1lc2giLHRoaXMuc2hhZGluZ1R5cGUsdGhpcy5jb29yZHMsdGhpcy5jb2xvcnMsdGhpcy5maWd1cmVzLGUsdGhpcy5iYm94LHRoaXMuYmFja2dyb3VuZF19fWNsYXNzIER1bW15U2hhZGluZyBleHRlbmRzIEJhc2VTaGFkaW5ne2dldElSKCl7cmV0dXJuWyJEdW1teSJdfX1mdW5jdGlvbiBnZXRUaWxpbmdQYXR0ZXJuSVIoZSx0LHIpe2NvbnN0IGE9bG9va3VwTWF0cml4KHQuZ2V0QXJyYXkoIk1hdHJpeCIpLGZyKSxuPWxvb2t1cE5vcm1hbFJlY3QodC5nZXRBcnJheSgiQkJveCIpLG51bGwpO2lmKCFufHxuWzJdLW5bMF09PT0wfHxuWzNdLW5bMV09PT0wKXRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBnZXRUaWxpbmdQYXR0ZXJuSVIgL0JCb3ggYXJyYXkuIik7Y29uc3QgaT10LmdldCgiWFN0ZXAiKTtpZigibnVtYmVyIiE9dHlwZW9mIGkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvWFN0ZXAgdmFsdWUuIik7Y29uc3Qgcz10LmdldCgiWVN0ZXAiKTtpZigibnVtYmVyIiE9dHlwZW9mIHMpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvWVN0ZXAgdmFsdWUuIik7Y29uc3Qgbz10LmdldCgiUGFpbnRUeXBlIik7aWYoIU51bWJlci5pc0ludGVnZXIobykpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvUGFpbnRUeXBlIHZhbHVlLiIpO2NvbnN0IGM9dC5nZXQoIlRpbGluZ1R5cGUiKTtpZighTnVtYmVyLmlzSW50ZWdlcihjKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgZ2V0VGlsaW5nUGF0dGVybklSIC9UaWxpbmdUeXBlIHZhbHVlLiIpO3JldHVyblsiVGlsaW5nUGF0dGVybiIscixlLGEsbixpLHMsbyxjXX1jb25zdCBtbj1bMS4zODc3LDEsMSwxLC45NzgwMSwuOTI0ODIsLjg5NTUyLC45MTEzMywuODE5ODgsLjk3NTY2LC45ODE1MiwuOTM1NDgsLjkzNTQ4LDEuMjc5OCwuODUyODQsLjkyNzk0LDEsLjk2MTM0LDEuNTQ2NTcsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC44Mjg0NSwuODI4NDUsLjg1Mjg0LC44NTI4NCwuODUyODQsLjc1ODU5LC45MjEzOCwuODM5MDgsLjc3NjIsLjczMjkzLC44NzI4OSwuNzMxMzMsLjc1MTQsLjgxOTIxLC44NzM1NiwuOTU5NTgsLjU5NTI2LC43NTcyNywuNjkyMjUsMS4wNDkyNCwuOTEyMSwuODY5NDMsLjc5Nzk1LC44ODE5OCwuNzc5NTgsLjcwODY0LC44MTA1NSwuOTAzOTksLjg4NjUzLC45NjAxNywuODI1NzcsLjc3ODkyLC43ODI1NywuOTc1MDcsMS41NDY1NywuOTc1MDcsLjg1Mjg0LC44OTU1MiwuOTAxNzYsLjg4NzYyLC44Nzg1LC43NTI0MSwuODc4NSwuOTA1MTgsLjk1MDE1LC43NzYxOCwuODc4NSwuODg0MDEsLjkxOTE2LC44NjMwNCwuODg0MDEsLjkxNDg4LC44Nzg1LC44ODAxLC44Nzg1LC44Nzg1LC45MTM0MywuNzE3MywxLjA0MTA2LC44Nzg1LC44NTA3NSwuOTU3OTQsLjgyNjE2LC44NTE2MiwuNzk0OTIsLjg4MzMxLDEuNjk4MDgsLjg4MzMxLC44NTI4NCwuOTc4MDEsLjg5NTUyLC45MTEzMywuODk1NTIsLjkxMTMzLDEuNzgwMSwuODk1NTIsMS4yNDQ4NywxLjEzMjU0LDEuMTI0MDEsLjk2ODM5LC44NTI4NCwuNjg3ODcsLjcwNjQ1LC44NTU5MiwuOTA3NDcsMS4wMTQ2NiwxLjAwODgsLjkwMzIzLDEsMS4wNzQ2MywxLC45MTA1NiwuNzU4MDYsMS4xOTExOCwuOTY4MzksLjc4ODY0LC44Mjg0NSwuODQxMzMsLjc1ODU5LC44MzkwOCwuODM5MDgsLjgzOTA4LC44MzkwOCwuODM5MDgsLjgzOTA4LC43NzUzOSwuNzMyOTMsLjczMTMzLC43MzEzMywuNzMxMzMsLjczMTMzLC45NTk1OCwuOTU5NTgsLjk1OTU4LC45NTk1OCwuODg1MDYsLjkxMjEsLjg2OTQzLC44Njk0MywuODY5NDMsLjg2OTQzLC44Njk0MywuODUyODQsLjg3NTA4LC45MDM5OSwuOTAzOTksLjkwMzk5LC45MDM5OSwuNzc4OTIsLjc5Nzk1LC45MDgwNywuODg3NjIsLjg4NzYyLC44ODc2MiwuODg3NjIsLjg4NzYyLC44ODc2MiwuODcxNSwuNzUyNDEsLjkwNTE4LC45MDUxOCwuOTA1MTgsLjkwNTE4LC44ODQwMSwuODg0MDEsLjg4NDAxLC44ODQwMSwuODc4NSwuODc4NSwuODgwMSwuODgwMSwuODgwMSwuODgwMSwuODgwMSwuOTA3NDcsLjg5MDQ5LC44Nzg1LC44Nzg1LC44Nzg1LC44Nzg1LC44NTE2MiwuODc4NSwuODUxNjIsLjgzOTA4LC44ODc2MiwuODM5MDgsLjg4NzYyLC44MzkwOCwuODg3NjIsLjczMjkzLC43NTI0MSwuNzMyOTMsLjc1MjQxLC43MzI5MywuNzUyNDEsLjczMjkzLC43NTI0MSwuODcyODksLjgzMDE2LC44ODUwNiwuOTMxMjUsLjczMTMzLC45MDUxOCwuNzMxMzMsLjkwNTE4LC43MzEzMywuOTA1MTgsLjczMTMzLC45MDUxOCwuNzMxMzMsLjkwNTE4LC44MTkyMSwuNzc2MTgsLjgxOTIxLC43NzYxOCwuODE5MjEsLjc3NjE4LDEsMSwuODczNTYsLjg3ODUsLjkxMDc1LC44OTYwOCwuOTU5NTgsLjg4NDAxLC45NTk1OCwuODg0MDEsLjk1OTU4LC44ODQwMSwuOTU5NTgsLjg4NDAxLC45NTk1OCwuODg0MDEsLjc2MjI5LC45MDE2NywuNTk1MjYsLjkxOTE2LDEsMSwuODYzMDQsLjY5MjI1LC44ODQwMSwxLDEsLjcwNDI0LC43OTQ2OCwuOTE5MjYsLjg4MTc1LC43MDgyMywuOTQ5MDMsLjkxMjEsLjg3ODUsMSwxLC45MTIxLC44Nzg1LC44NzgwMiwuODg2NTYsLjg3ODUsLjg2OTQzLC44ODAxLC44Njk0MywuODgwMSwuODY5NDMsLjg4MDEsLjg3NDAyLC44OTI5MSwuNzc5NTgsLjkxMzQzLDEsMSwuNzc5NTgsLjkxMzQzLC43MDg2NCwuNzE3MywuNzA4NjQsLjcxNzMsLjcwODY0LC43MTczLC43MDg2NCwuNzE3MywxLDEsLjgxMDU1LC43NTg0MSwuODEwNTUsMS4wNjQ1MiwuOTAzOTksLjg3ODUsLjkwMzk5LC44Nzg1LC45MDM5OSwuODc4NSwuOTAzOTksLjg3ODUsLjkwMzk5LC44Nzg1LC45MDM5OSwuODc4NSwuOTYwMTcsLjk1Nzk0LC43Nzg5MiwuODUxNjIsLjc3ODkyLC43ODI1NywuNzk0OTIsLjc4MjU3LC43OTQ5MiwuNzgyNTcsLjc5NDkyLC45Mjk3LC41Njg5MiwuODM5MDgsLjg4NzYyLC43NzUzOSwuODcxNSwuODc1MDgsLjg5MDQ5LDEsMSwuODEwNTUsMS4wNDEwNiwxLjIwNTI4LDEuMjA1MjgsMSwxLjE1NTQzLC43MDY3NCwuOTgzODcsLjk0NzIxLDEuMzM0MzEsMS40NTg5NCwuOTUxNjEsMS4wNjMwMywuODM5MDgsLjgwMzUyLC41NzE4NCwuNjk2NSwuNTYyODksLjgyMDAxLC41NjAyOSwuODEyMzUsMS4wMjk4OCwuODM5MDgsLjc3NjIsLjY4MTU2LC44MDM2NywuNzMxMzMsLjc4MjU3LC44NzM1NiwuODY5NDMsLjk1OTU4LC43NTcyNywuODkwMTksMS4wNDkyNCwuOTEyMSwuNzY0OCwuODY5NDMsLjg3MzU2LC43OTc5NSwuNzgyNzUsLjgxMDU1LC43Nzg5MiwuOTc2MiwuODI1NzcsLjk5ODE5LC44NDg5NiwuOTU5NTgsLjc3ODkyLC45NjEwOCwxLjAxNDA3LC44OTA0OSwxLjAyOTg4LC45NDIxMSwuOTYxMDgsLjg5MzYsLjg0MDIxLC44Nzg0MiwuOTYzOTksLjc5MTA5LC44OTA0OSwxLjAwODEzLDEuMDI5ODgsLjg2MDc3LC44NzQ0NSwuOTIwOTksLjg0NzIzLC44NjUxMywuODgwMSwuNzU2MzgsLjg1NzE0LC43ODIxNiwuNzk1ODYsLjg3OTY1LC45NDIxMSwuOTc3NDcsLjc4Mjg3LC45NzkyNiwuODQ5NzEsMS4wMjk4OCwuOTQyMTEsLjg4MDEsLjk0MjExLC44NDk3MSwuNzMxMzMsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjkwMjY0LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45MDUxOCwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTA1NDgsMSwxLDEsMSwxLDEsLjk2MDE3LC45NTc5NCwuOTYwMTcsLjk1Nzk0LC45NjAxNywuOTU3OTQsLjc3ODkyLC44NTE2MiwxLDEsLjg5NTUyLC45MDUyNywxLC45MDM2MywuOTI3OTQsLjkyNzk0LC45Mjc5NCwuOTI3OTQsLjg3MDEyLC44NzAxMiwuODcwMTIsLjg5NTUyLC44OTU1MiwxLjQyMjU5LC43MTE0MywxLjA2MTUyLDEsMSwxLjAzMzcyLDEuMDMzNzIsLjk3MTcxLDEuNDk1NiwyLjI4MDcsLjkzODM1LC44MzQwNiwuOTExMzMsLjg0MTA3LC45MTEzMywxLDEsMSwuNzIwMjEsMSwxLjIzMTA4LC44MzQ4OSwuODg1MjUsLjg4NTI1LC44MTQ5OSwuOTA1MjcsMS44MTA1NSwuOTA1MjcsMS44MTA1NSwxLjMxMDA2LDEuNTM3MTEsLjk0NDM0LDEuMDg2OTYsMSwuOTUwMTgsLjc3MTkyLC44NTI4NCwuOTA3NDcsMS4xNzUzNCwuNjk4MjUsLjk3MTYsMS4zNzA3NywuOTA3NDcsLjkwNzQ3LC44NTM1NiwuOTA3NDcsLjkwNzQ3LDEuNDQ5NDcsLjg1Mjg0LC44OTQxLC44OTQxLC43MDU3MiwuOCwuNzA1NzIsLjcwNTcyLC43MDU3MiwuNzA1NzIsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45OTg2MiwuOTk4NjIsMSwxLDEsMSwxLDEuMDgwMDQsLjkxMDI3LDEsMSwxLC45OTg2MiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTA3MjcsLjkwNzI3LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSxibj17bGluZUhlaWdodDoxLjIyMDcsbGluZUdhcDouMjIwN30seW49WzEuMzg3NywxLDEsMSwuOTc4MDEsLjkyNDgyLC44OTU1MiwuOTExMzMsLjgxOTg4LC45NzU2NiwuOTgxNTIsLjkzNTQ4LC45MzU0OCwxLjI3OTgsLjg1Mjg0LC45Mjc5NCwxLC45NjEzNCwxLjU2MjM5LC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuODI4NDUsLjgyODQ1LC44NTI4NCwuODUyODQsLjg1Mjg0LC43NTg1OSwuOTIxMzgsLjgzOTA4LC43NzYyLC43MTgwNSwuODcyODksLjczMTMzLC43NTE0LC44MTkyMSwuODczNTYsLjk1OTU4LC41OTUyNiwuNzU3MjcsLjY5MjI1LDEuMDQ5MjQsLjkwODcyLC44NTkzOCwuNzk3OTUsLjg3MDY4LC43Nzk1OCwuNjk3NjYsLjgxMDU1LC45MDM5OSwuODg2NTMsLjk2MDY4LC44MjU3NywuNzc4OTIsLjc4MjU3LC45NzUwNywxLjUyOSwuOTc1MDcsLjg1Mjg0LC44OTU1MiwuOTAxNzYsLjk0OTA4LC44NjQxMSwuNzQwMTIsLjg2NDExLC44ODMyMywuOTUwMTUsLjg2NDExLC44NjMzMSwuODg0MDEsLjkxOTE2LC44NjMwNCwuODg0MDEsLjkwMzksLjg2MzMxLC44NjMzMSwuODY0MTEsLjg2NDExLC45MDQ2NCwuNzA4NTIsMS4wNDEwNiwuODYzMzEsLjg0MzcyLC45NTc5NCwuODI2MTYsLjg0NTQ4LC43OTQ5MiwuODgzMzEsMS42OTgwOCwuODgzMzEsLjg1Mjg0LC45NzgwMSwuODk1NTIsLjkxMTMzLC44OTU1MiwuOTExMzMsMS43ODAxLC44OTU1MiwxLjI0NDg3LDEuMTMyNTQsMS4xOTEyOSwuOTY4MzksLjg1Mjg0LC42ODc4NywuNzA2NDUsLjg1NTkyLC45MDc0NywxLjAxNDY2LDEuMDA4OCwuOTAzMjMsMSwxLjA3NDYzLDEsLjkxMDU2LC43NTgwNiwxLjE5MTE4LC45NjgzOSwuNzg4NjQsLjgyODQ1LC44NDEzMywuNzU4NTksLjgzOTA4LC44MzkwOCwuODM5MDgsLjgzOTA4LC44MzkwOCwuODM5MDgsLjc3NTM5LC43MTgwNSwuNzMxMzMsLjczMTMzLC43MzEzMywuNzMxMzMsLjk1OTU4LC45NTk1OCwuOTU5NTgsLjk1OTU4LC44ODUwNiwuOTA4NzIsLjg1OTM4LC44NTkzOCwuODU5MzgsLjg1OTM4LC44NTkzOCwuODUyODQsLjg3MDY4LC45MDM5OSwuOTAzOTksLjkwMzk5LC45MDM5OSwuNzc4OTIsLjc5Nzk1LC45MDgwNywuOTQ5MDgsLjk0OTA4LC45NDkwOCwuOTQ5MDgsLjk0OTA4LC45NDkwOCwuODU4ODcsLjc0MDEyLC44ODMyMywuODgzMjMsLjg4MzIzLC44ODMyMywuODg0MDEsLjg4NDAxLC44ODQwMSwuODg0MDEsLjg3ODUsLjg2MzMxLC44NjMzMSwuODYzMzEsLjg2MzMxLC44NjMzMSwuODYzMzEsLjkwNzQ3LC44OTA0OSwuODYzMzEsLjg2MzMxLC44NjMzMSwuODYzMzEsLjg0NTQ4LC44NjQxMSwuODQ1NDgsLjgzOTA4LC45NDkwOCwuODM5MDgsLjk0OTA4LC44MzkwOCwuOTQ5MDgsLjcxODA1LC43NDAxMiwuNzE4MDUsLjc0MDEyLC43MTgwNSwuNzQwMTIsLjcxODA1LC43NDAxMiwuODcyODksLjc5NTM4LC44ODUwNiwuOTI3MjYsLjczMTMzLC44ODMyMywuNzMxMzMsLjg4MzIzLC43MzEzMywuODgzMjMsLjczMTMzLC44ODMyMywuNzMxMzMsLjg4MzIzLC44MTkyMSwuODY0MTEsLjgxOTIxLC44NjQxMSwuODE5MjEsLjg2NDExLDEsMSwuODczNTYsLjg2MzMxLC45MTA3NSwuODc3NywuOTU5NTgsLjg4NDAxLC45NTk1OCwuODg0MDEsLjk1OTU4LC44ODQwMSwuOTU5NTgsLjg4NDAxLC45NTk1OCwuODg0MDEsLjc2NDY3LC45MDE2NywuNTk1MjYsLjkxOTE2LDEsMSwuODYzMDQsLjY5MjI1LC44ODQwMSwxLDEsLjcwNDI0LC43NzMxMiwuOTE5MjYsLjg4MTc1LC43MDgyMywuOTQ5MDMsLjkwODcyLC44NjMzMSwxLDEsLjkwODcyLC44NjMzMSwuODY5MDYsLjg4MTE2LC44NjMzMSwuODU5MzgsLjg2MzMxLC44NTkzOCwuODYzMzEsLjg1OTM4LC44NjMzMSwuODc0MDIsLjg2NTQ5LC43Nzk1OCwuOTA0NjQsMSwxLC43Nzk1OCwuOTA0NjQsLjY5NzY2LC43MDg1MiwuNjk3NjYsLjcwODUyLC42OTc2NiwuNzA4NTIsLjY5NzY2LC43MDg1MiwxLDEsLjgxMDU1LC43NTg0MSwuODEwNTUsMS4wNjQ1MiwuOTAzOTksLjg2MzMxLC45MDM5OSwuODYzMzEsLjkwMzk5LC44NjMzMSwuOTAzOTksLjg2MzMxLC45MDM5OSwuODYzMzEsLjkwMzk5LC44NjMzMSwuOTYwNjgsLjk1Nzk0LC43Nzg5MiwuODQ1NDgsLjc3ODkyLC43ODI1NywuNzk0OTIsLjc4MjU3LC43OTQ5MiwuNzgyNTcsLjc5NDkyLC45Mjk3LC41Njg5MiwuODM5MDgsLjk0OTA4LC43NzUzOSwuODU4ODcsLjg3MDY4LC44OTA0OSwxLDEsLjgxMDU1LDEuMDQxMDYsMS4yMDUyOCwxLjIwNTI4LDEsMS4xNTU0MywuNzAwODgsLjk4Mzg3LC45NDcyMSwxLjMzNDMxLDEuNDU4OTQsLjk1MTYxLDEuNDgzODcsLjgzOTA4LC44MDM1MiwuNTcxMTgsLjY5NjUsLjU2MzQ3LC43OTE3OSwuNTU4NTMsLjgwMzQ2LDEuMDI5ODgsLjgzOTA4LC43NzYyLC42NzE3NCwuODYwMzYsLjczMTMzLC43ODI1NywuODczNTYsLjg2NDQxLC45NTk1OCwuNzU3MjcsLjg5MDE5LDEuMDQ5MjQsLjkwODcyLC43NDg4OSwuODU5MzgsLjg3ODkxLC43OTc5NSwuNzk1NywuODEwNTUsLjc3ODkyLC45NzQ0NywuODI1NzcsLjk3NDY2LC44NzE3OSwuOTU5NTgsLjc3ODkyLC45NDI1MiwuOTU2MTIsLjg3NTMsMS4wMjk4OCwuOTI3MzMsLjk0MjUyLC44NzQxMSwuODQwMjEsLjg3MjgsLjk1NjEyLC43NDA4MSwuODc1MywxLjAyMTg5LDEuMDI5ODgsLjg0ODE0LC44NzQ0NSwuOTE4MjIsLjg0NzIzLC44NTY2OCwuODYzMzEsLjgxMzQ0LC44NzU4MSwuNzY0MjIsLjgyMDQ2LC45NjA1NywuOTI3MzMsLjk5Mzc1LC43ODAyMiwuOTU0NTIsLjg2MDE1LDEuMDI5ODgsLjkyNzMzLC44NjMzMSwuOTI3MzMsLjg2MDE1LC43MzEzMywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTA2MzEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjg4MzIzLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC44NTE3NCwxLDEsMSwxLDEsMSwuOTYwNjgsLjk1Nzk0LC45NjA2OCwuOTU3OTQsLjk2MDY4LC45NTc5NCwuNzc4OTIsLjg0NTQ4LDEsMSwuODk1NTIsLjkwNTI3LDEsLjkwMzYzLC45Mjc5NCwuOTI3OTQsLjkyNzk0LC44OTgwNywuODcwMTIsLjg3MDEyLC44NzAxMiwuODk1NTIsLjg5NTUyLDEuNDIyNTksLjcxMDk0LDEuMDYxNTIsMSwxLDEuMDMzNzIsMS4wMzM3MiwuOTcxNzEsMS40OTU2LDIuMjgwNywuOTI5NzIsLjgzNDA2LC45MTEzMywuODMzMjYsLjkxMTMzLDEsMSwxLC43MjAyMSwxLDEuMjMxMDgsLjgzNDg5LC44ODUyNSwuODg1MjUsLjgxNDk5LC45MDYxNiwxLjgxMDU1LC45MDUyNywxLjgxMDU1LDEuMzEwNywxLjUzNzExLC45NDQzNCwxLjA4Njk2LDEsLjk1MDE4LC43NzE5MiwuODUyODQsLjkwNzQ3LDEuMTc1MzQsLjY5ODI1LC45NzE2LDEuMzcwNzcsLjkwNzQ3LC45MDc0NywuODUzNTYsLjkwNzQ3LC45MDc0NywxLjQ0OTQ3LC44NTI4NCwuODk0MSwuODk0MSwuNzA1NzIsLjgsLjcwNTcyLC43MDU3MiwuNzA1NzIsLjcwNTcyLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTk4NjIsLjk5ODYyLDEsMSwxLDEsMSwxLjA4MDA0LC45MTAyNywxLDEsMSwuOTk4NjIsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjkwNzI3LC45MDcyNywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0sd249e2xpbmVIZWlnaHQ6MS4yMjA3LGxpbmVHYXA6LjIyMDd9LHhuPVsxLjM4NzcsMSwxLDEsMS4xNzIyMywxLjEyOTMsLjg5NTUyLC45MTEzMywuODAzOTUsMS4wMjI2OSwxLjE1NjAxLC45MTA1NiwuOTEwNTYsMS4yNzk4LC44NTI4NCwuODk4MDcsMSwuOTA4NjEsMS4zOTU0MywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjk2MzA5LC45NjMwOSwuODUyODQsLjg1Mjg0LC44NTI4NCwuODMzMTksLjg4MDcxLC44Njc1LC44MTU1MiwuNzIzNDYsLjg1MTkzLC43MzIwNiwuNzUyMiwuODExMDUsLjg2Mjc1LC45MDY4NSwuNjM3NywuNzc4OTIsLjc1NTkzLDEuMDI2MzgsLjg5MjQ5LC44NDExOCwuNzc0NTIsLjg1Mzc0LC43NTE4NiwuNjc3ODksLjc5Nzc2LC44ODg0NCwuODUwNjYsLjk0MzA5LC43NzgxOCwuNzMwNiwuNzY2NTksMS4xMDM2OSwxLjM4MzEzLDEuMTAzNjksMS4wNjEzOSwuODk1NTIsLjg3MzksLjkyNDUsLjkyNDUsLjgzMjAzLC45MjQ1LC44NTg2NSwxLjA5ODQyLC45MjQ1LC45MjQ1LDEuMDMyOTcsMS4wNzY5MiwuOTA5MTgsMS4wMzI5NywuOTQ5NTksLjkyNDUsLjkyMjc0LC45MjQ1LC45MjQ1LDEuMDI5MzMsLjc3ODMyLDEuMjA1NjIsLjkyNDUsLjg5MTYsLjk4OTg2LC44NjYyMSwuODk0NTMsLjc5MDA0LC45NDE1MiwxLjc3MjU2LC45NDE1MiwuODUyODQsLjk3ODAxLC44OTU1MiwuOTExMzMsLjg5NTUyLC45MTEzMywxLjkxNzI5LC44OTU1MiwxLjE3ODg5LDEuMTMyNTQsMS4xNjM1OSwuOTIwOTgsLjg1Mjg0LC42ODc4NywuNzEzNTMsLjg0NzM3LC45MDc0NywxLjAwODgsMS4wMDQ0LC44NzY4MywxLDEuMDkwOTEsMSwuOTIyMjksLjczOSwxLjE1NjQyLC45MjA5OCwuNzYyODgsLjgwNTA0LC44MDk3MiwuNzU4NTksLjg2NzUsLjg2NzUsLjg2NzUsLjg2NzUsLjg2NzUsLjg2NzUsLjc2MzE4LC43MjM0NiwuNzMyMDYsLjczMjA2LC43MzIwNiwuNzMyMDYsLjkwNjg1LC45MDY4NSwuOTA2ODUsLjkwNjg1LC44NjQ3NywuODkyNDksLjg0MTE4LC44NDExOCwuODQxMTgsLjg0MTE4LC44NDExOCwuODUyODQsLjg0NTU3LC44ODg0NCwuODg4NDQsLjg4ODQ0LC44ODg0NCwuNzMwNiwuNzc0NTIsLjg2MzMxLC45MjQ1LC45MjQ1LC45MjQ1LC45MjQ1LC45MjQ1LC45MjQ1LC44NDg0MywuODMyMDMsLjg1ODY1LC44NTg2NSwuODU4NjUsLjg1ODY1LC44MjYwMSwuODI2MDEsLjgyNjAxLC44MjYwMSwuOTQ0NjksLjkyNDUsLjkyMjc0LC45MjI3NCwuOTIyNzQsLjkyMjc0LC45MjI3NCwuOTA3NDcsLjg2NjUxLC45MjQ1LC45MjQ1LC45MjQ1LC45MjQ1LC44OTQ1MywuOTI0NSwuODk0NTMsLjg2NzUsLjkyNDUsLjg2NzUsLjkyNDUsLjg2NzUsLjkyNDUsLjcyMzQ2LC44MzIwMywuNzIzNDYsLjgzMjAzLC43MjM0NiwuODMyMDMsLjcyMzQ2LC44MzIwMywuODUxOTMsLjg4NzUsLjg2NDc3LC45OTAzNCwuNzMyMDYsLjg1ODY1LC43MzIwNiwuODU4NjUsLjczMjA2LC44NTg2NSwuNzMyMDYsLjg1ODY1LC43MzIwNiwuODU4NjUsLjgxMTA1LC45MjQ1LC44MTEwNSwuOTI0NSwuODExMDUsLjkyNDUsMSwxLC44NjI3NSwuOTI0NSwuOTA4NzIsLjkzNTkxLC45MDY4NSwuODI2MDEsLjkwNjg1LC44MjYwMSwuOTA2ODUsLjgyNjAxLC45MDY4NSwxLjAzMjk3LC45MDY4NSwuODI2MDEsLjc3ODk2LDEuMDU2MTEsLjYzNzcsMS4wNzY5MiwxLDEsLjkwOTE4LC43NTU5MywxLjAzMjk3LDEsMSwuNzYwMzIsLjkzNzUsLjk4MTU2LC45MzQwNywuNzcyNjEsMS4xMTQyOSwuODkyNDksLjkyNDUsMSwxLC44OTI0OSwuOTI0NSwuOTI1MzQsLjg2Njk4LC45MjQ1LC44NDExOCwuOTIyNzQsLjg0MTE4LC45MjI3NCwuODQxMTgsLjkyMjc0LC44NjY3LC44NjI5MSwuNzUxODYsMS4wMjkzMywxLDEsLjc1MTg2LDEuMDI5MzMsLjY3Nzg5LC43NzgzMiwuNjc3ODksLjc3ODMyLC42Nzc4OSwuNzc4MzIsLjY3Nzg5LC43NzgzMiwxLDEsLjc5Nzc2LC45NzY1NSwuNzk3NzYsMS4yMzAyMywuODg4NDQsLjkyNDUsLjg4ODQ0LC45MjQ1LC44ODg0NCwuOTI0NSwuODg4NDQsLjkyNDUsLjg4ODQ0LC45MjQ1LC44ODg0NCwuOTI0NSwuOTQzMDksLjk4OTg2LC43MzA2LC44OTQ1MywuNzMwNiwuNzY2NTksLjc5MDA0LC43NjY1OSwuNzkwMDQsLjc2NjU5LC43OTAwNCwxLjA5MjMxLC41NDg3MywuODY3NSwuOTI0NSwuNzYzMTgsLjg0ODQzLC44NDU1NywuODY2NTEsMSwxLC43OTc3NiwxLjIwNTYyLDEuMTg2MjIsMS4xODYyMiwxLDEuMTQzNywuNjcwMDksLjk2MzM0LC45MzY5NSwxLjM1MTkxLDEuNDA5MDksLjk1MTYxLDEuNDgzODcsLjg2NzUsLjkwODYxLC42MTkyLC43MzYzLC42NDgyNCwuODI0MTEsLjU2MzIxLC44NTY5NiwxLjIzNTE2LC44Njc1LC44MTU1MiwuNzI4NiwuODQxMzQsLjczMjA2LC43NjY1OSwuODYyNzUsLjg0MzY5LC45MDY4NSwuNzc4OTIsLjg1ODcxLDEuMDI2MzgsLjg5MjQ5LC43NTgyOCwuODQxMTgsLjg1OTg0LC43NzQ1MiwuNzY0NjYsLjc5Nzc2LC43MzA2LC45MDc4MiwuNzc4MTgsLjkwMywuODcyOTEsLjkwNjg1LC43MzA2LC45OTA1OCwxLjAzNjY3LC45NDYzNSwxLjIzNTE2LC45ODQ5LC45OTA1OCwuOTIzOTMsLjg5MTYsLjk0MiwxLjAzNjY3LC43NTAyNiwuOTQ2MzUsMS4wMjk3LDEuMjM1MTYsLjkwOTE4LC45NDA0OCwuOTgyMTcsLjg5NzQ2LC44NDE1MywuOTIyNzQsLjgyNTA3LC44ODgzMiwuODQ0MzgsLjg4MTc4LDEuMDM1MjUsLjk4NDksMS4wMDIyNSwuNzgwODYsLjk3MjQ4LC44OTQwNCwxLjIzNTE2LC45ODQ5LC45MjI3NCwuOTg0OSwuODk0MDQsLjczMjA2LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC44OTY5MywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuODU4NjUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjkwOTMzLDEsMSwxLDEsMSwxLC45NDMwOSwuOTg5ODYsLjk0MzA5LC45ODk4NiwuOTQzMDksLjk4OTg2LC43MzA2LC44OTQ1MywxLDEsLjg5NTUyLC45MDUyNywxLC45MDE4NiwxLjEyMzA4LDEuMTIzMDgsMS4xMjMwOCwxLjEyMzA4LDEuMjU2NiwxLjI1NjYsMS4yNTY2LC44OTU1MiwuODk1NTIsMS40MjI1OSwuNjg5OTQsMS4wMzgwOSwxLDEsMS4wMTc2LDEuMDE3NiwxLjExNTIzLDEuNDk1NiwyLjAxNDYyLC45Nzg1OCwuODI2MTYsLjkxMTMzLC44MzQzNywuOTExMzMsMSwxLDEsLjcwNTA4LDEsMS4yMzEwOCwuNzk4MDEsLjg0NDI2LC44NDQyNiwuNzc0LC45MDU3MiwxLjgxMDU1LC45MDc0OSwxLjgxMDU1LDEuMjg4MDksMS41NTQ2OSwuOTQ0MzQsMS4wNzgwNiwxLC45NzA5NCwuNzU4OSwuODUyODQsLjkwNzQ3LDEuMTk2NTgsLjY5ODI1LC45NzYyMiwxLjMzNTEyLC45MDc0NywuOTA3NDcsLjg1Mjg0LC45MDc0NywuOTA3NDcsMS40NDk0NywuODUyODQsLjg5NDEsLjg5NDEsLjcwNTcyLC44LC43MDU3MiwuNzA1NzIsLjcwNTcyLC43MDU3MiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjk5ODYyLC45OTg2MiwxLDEsMSwxLDEsMS4wMzM2LC45MTAyNywxLDEsMSwuOTk4NjIsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMS4wNTg1OSwxLjA1ODU5LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSxTbj17bGluZUhlaWdodDoxLjIyMDcsbGluZUdhcDouMjIwN30sQW49WzEuMzg3NywxLDEsMSwxLjE3MjIzLDEuMTI5MywuODk1NTIsLjkxMTMzLC44MDM5NSwxLjAyMjY5LDEuMTU2MDEsLjkxMDU2LC45MTA1NiwxLjI3OTgsLjg1Mjg0LC44OTgwNywxLC45MDg2MSwxLjM5MDE2LC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTExMzMsLjkxMTMzLC45MTEzMywuOTYzMDksLjk2MzA5LC44NTI4NCwuODUyODQsLjg1Mjg0LC44MzMxOSwuODgwNzEsLjg2NzUsLjgxNTUyLC43MzgzNCwuODUxOTMsLjczMjA2LC43NTIyLC44MTEwNSwuODYyNzUsLjkwNjg1LC42Mzc3LC43Nzg5MiwuNzU1OTMsMS4wMjYzOCwuODkzODUsLjg1MTIyLC43NzQ1MiwuODY1MDMsLjc1MTg2LC42ODg4NywuNzk3NzYsLjg4ODQ0LC44NTA2NiwuOTQyNTgsLjc3ODE4LC43MzA2LC43NjY1OSwxLjEwMzY5LDEuMzkwMTYsMS4xMDM2OSwxLjA2MTM5LC44OTU1MiwuODczOSwuODYxMjgsLjk0NDY5LC44NDU3LC45NDQ2OSwuODk0NjQsMS4wOTg0MiwuODQ2MzYsLjk0NDY5LDEuMDMyOTcsMS4wNzY5MiwuOTA5MTgsMS4wMzI5NywuOTU4OTcsLjk0NDY5LC45NDgyLC45NDQ2OSwuOTQ0NjksMS4wNDY5MiwuNzgyMjMsMS4yMDU2MiwuOTQ0NjksLjkwMzMyLC45ODk4NiwuODY2MjEsLjkwNTI3LC43OTAwNCwuOTQxNTIsMS43NzI1NiwuOTQxNTIsLjg1Mjg0LC45NzgwMSwuODk1NTIsLjkxMTMzLC44OTU1MiwuOTExMzMsMS45MTcyOSwuODk1NTIsMS4xNzg4OSwxLjEzMjU0LDEuMDg3MDcsLjkyMDk4LC44NTI4NCwuNjg3ODcsLjcxMzUzLC44NDczNywuOTA3NDcsMS4wMDg4LDEuMDA0NCwuODc2ODMsMSwxLjA5MDkxLDEsLjkyMjI5LC43MzksMS4xNTY0MiwuOTIwOTgsLjc2Mjg4LC44MDUwNCwuODA5NzIsLjc1ODU5LC44Njc1LC44Njc1LC44Njc1LC44Njc1LC44Njc1LC44Njc1LC43NjMxOCwuNzM4MzQsLjczMjA2LC43MzIwNiwuNzMyMDYsLjczMjA2LC45MDY4NSwuOTA2ODUsLjkwNjg1LC45MDY4NSwuODY0NzcsLjg5Mzg1LC44NTEyMiwuODUxMjIsLjg1MTIyLC44NTEyMiwuODUxMjIsLjg1Mjg0LC44NTMxMSwuODg4NDQsLjg4ODQ0LC44ODg0NCwuODg4NDQsLjczMDYsLjc3NDUyLC44NjMzMSwuODYxMjgsLjg2MTI4LC44NjEyOCwuODYxMjgsLjg2MTI4LC44NjEyOCwuODY5MywuODQ1NywuODk0NjQsLjg5NDY0LC44OTQ2NCwuODk0NjQsLjgyNjAxLC44MjYwMSwuODI2MDEsLjgyNjAxLC45NDQ2OSwuOTQ0NjksLjk0ODIsLjk0ODIsLjk0ODIsLjk0ODIsLjk0ODIsLjkwNzQ3LC44NjY1MSwuOTQ0NjksLjk0NDY5LC45NDQ2OSwuOTQ0NjksLjkwNTI3LC45NDQ2OSwuOTA1MjcsLjg2NzUsLjg2MTI4LC44Njc1LC44NjEyOCwuODY3NSwuODYxMjgsLjczODM0LC44NDU3LC43MzgzNCwuODQ1NywuNzM4MzQsLjg0NTcsLjczODM0LC44NDU3LC44NTE5MywuOTI0NTQsLjg2NDc3LC45OTIxLC43MzIwNiwuODk0NjQsLjczMjA2LC44OTQ2NCwuNzMyMDYsLjg5NDY0LC43MzIwNiwuODk0NjQsLjczMjA2LC44OTQ2NCwuODExMDUsLjg0NjM2LC44MTEwNSwuODQ2MzYsLjgxMTA1LC44NDYzNiwxLDEsLjg2Mjc1LC45NDQ2OSwuOTA4NzIsLjk1Nzg2LC45MDY4NSwuODI2MDEsLjkwNjg1LC44MjYwMSwuOTA2ODUsLjgyNjAxLC45MDY4NSwxLjAzMjk3LC45MDY4NSwuODI2MDEsLjc3NzQxLDEuMDU2MTEsLjYzNzcsMS4wNzY5MiwxLDEsLjkwOTE4LC43NTU5MywxLjAzMjk3LDEsMSwuNzYwMzIsLjkwNDUyLC45ODE1NiwxLjExODQyLC43NzI2MSwxLjExNDI5LC44OTM4NSwuOTQ0NjksMSwxLC44OTM4NSwuOTQ0NjksLjk1ODc3LC44NjkwMSwuOTQ0NjksLjg1MTIyLC45NDgyLC44NTEyMiwuOTQ4MiwuODUxMjIsLjk0ODIsLjg2NjcsLjkwMDE2LC43NTE4NiwxLjA0NjkyLDEsMSwuNzUxODYsMS4wNDY5MiwuNjg4ODcsLjc4MjIzLC42ODg4NywuNzgyMjMsLjY4ODg3LC43ODIyMywuNjg4ODcsLjc4MjIzLDEsMSwuNzk3NzYsLjkyMTg4LC43OTc3NiwxLjIzMDIzLC44ODg0NCwuOTQ0NjksLjg4ODQ0LC45NDQ2OSwuODg4NDQsLjk0NDY5LC44ODg0NCwuOTQ0NjksLjg4ODQ0LC45NDQ2OSwuODg4NDQsLjk0NDY5LC45NDI1OCwuOTg5ODYsLjczMDYsLjkwNTI3LC43MzA2LC43NjY1OSwuNzkwMDQsLjc2NjU5LC43OTAwNCwuNzY2NTksLjc5MDA0LDEuMDkyMzEsLjU0ODczLC44Njc1LC44NjEyOCwuNzYzMTgsLjg2OTMsLjg1MzExLC44NjY1MSwxLDEsLjc5Nzc2LDEuMjA1NjIsMS4xODYyMiwxLjE4NjIyLDEsMS4xNDM3LC42Nzc0MiwuOTYzMzQsLjkzNjk1LDEuMzUxOTEsMS40MDkwOSwuOTUxNjEsMS40ODM4NywuODY2ODYsLjkwODYxLC42MjI2NywuNzQzNTksLjY1NjQ5LC44NTQ5OCwuNTY5NjMsLjg4MjU0LDEuMjM1MTYsLjg2NzUsLjgxNTUyLC43NTQ0MywuODQ1MDMsLjczMjA2LC43NjY1OSwuODYyNzUsLjg1MTIyLC45MDY4NSwuNzc4OTIsLjg1NzQ2LDEuMDI2MzgsLjg5Mzg1LC43NTY1NywuODUxMjIsLjg2Mjc1LC43NzQ1MiwuNzQxNzEsLjc5Nzc2LC43MzA2LC45NTE2NSwuNzc4MTgsLjg5NzcyLC44ODgzMSwuOTA2ODUsLjczMDYsLjk4MTQyLDEuMDIxOTEsLjk2NTc2LDEuMjM1MTYsLjk5MDE4LC45ODE0MiwuOTIzNiwuODkyNTgsLjk0MDM1LDEuMDIxOTEsLjc4ODQ4LC45NjU3NiwuOTU2MSwxLjIzNTE2LC45MDkxOCwuOTI1NzgsLjk1NDI0LC44OTc0NiwuODM5NjksLjk0ODIsLjgwMTEzLC44OTQ0MiwuODUyMDgsLjg2MTU1LC45ODAyMiwuOTkwMTgsMS4wMDQ1MiwuODEyMDksLjk5MjQ3LC44OTE4MSwxLjIzNTE2LC45OTAxOCwuOTQ4MiwuOTkwMTgsLjg5MTgxLC43MzIwNiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuODg4NDQsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjg5NDY0LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45Njc2NiwxLDEsMSwxLDEsMSwuOTQyNTgsLjk4OTg2LC45NDI1OCwuOTg5ODYsLjk0MjU4LC45ODk4NiwuNzMwNiwuOTA1MjcsMSwxLC44OTU1MiwuOTA1MjcsMSwuOTAxODYsMS4xMjMwOCwxLjEyMzA4LDEuMTIzMDgsMS4xMjMwOCwxLjI1NjYsMS4yNTY2LDEuMjU2NiwuODk1NTIsLjg5NTUyLDEuNDIyNTksLjY5MDQzLDEuMDM4MDksMSwxLDEuMDE3NiwxLjAxNzYsMS4xMTUyMywxLjQ5NTYsMi4wMTQ2MiwuOTkzMzEsLjgyNjE2LC45MTEzMywuODQyODYsLjkxMTMzLDEsMSwxLC43MDUwOCwxLDEuMjMxMDgsLjc5ODAxLC44NDQyNiwuODQ0MjYsLjc3NCwuOTA1MjcsMS44MTA1NSwuOTA1MjcsMS44MTA1NSwxLjI4ODA5LDEuNTU0NjksLjk0NDM0LDEuMDc4MDYsMSwuOTcwOTQsLjc1ODksLjg1Mjg0LC45MDc0NywxLjE5NjU4LC42OTgyNSwuOTc2MjIsMS4zMzUxMiwuOTA3NDcsLjkwNzQ3LC44NTM1NiwuOTA3NDcsLjkwNzQ3LDEuNDQ5NDcsLjg1Mjg0LC44OTQxLC44OTQxLC43MDU3MiwuOCwuNzA1NzIsLjcwNTcyLC43MDU3MiwuNzA1NzIsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45OTg2MiwuOTk4NjIsMSwxLDEsMSwxLDEuMDMzNiwuOTEwMjcsMSwxLDEsLjk5ODYyLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMDU4NTksMS4wNTg1OSwxLDEsMSwxLjA3MTg1LC45OTQxMywuOTYzMzQsMS4wODA2NSwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLGtuPXtsaW5lSGVpZ2h0OjEuMjIwNyxsaW5lR2FwOi4yMjA3fSxDbj1bLjc2MTE2LDEsMSwxLjAwMDYsLjk5OTk4LC45OTk3NCwuOTk5NzMsLjk5OTczLC45OTk4MiwuOTk5NzcsMS4wMDA4NywuOTk5OTgsLjk5OTk4LC45OTk1OSwxLjAwMDAzLDEuMDAwNiwuOTk5OTgsMS4wMDA2LDEuMDAwNiwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTk4LDEsMS4wMDAwMywxLjAwMDAzLDEuMDAwMDMsMS4wMDAyNiwuOTk5OSwuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsMS4wMDAwMSwxLjAwMDI2LDEuMDAwMjIsLjk5OTc3LDEuMDAwNiwuOTk5NzMsLjk5OTc3LDEuMDAwMjYsLjk5OTk5LC45OTk3NywxLjAwMDIyLDEuMDAwMDEsMS4wMDAyMiwuOTk5NzcsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDAxLDEuMDAwMTYsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsLjk5OTk4LDEuMDAwNiwuOTk5OTgsMS4wMDAwMywuOTk5NzMsLjk5OTk4LC45OTk3MywxLjAwMDI2LC45OTk3MywxLjAwMDI2LC45OTk3MywuOTk5OTgsMS4wMDAyNiwxLjAwMDI2LDEuMDAwNiwxLjAwMDYsLjk5OTczLDEuMDAwNiwuOTk5ODIsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwuOTk5NTksLjk5OTczLC45OTk5OCwxLjAwMDI2LC45OTk3MywxLjAwMDIyLC45OTk3MywuOTk5NzMsMSwuOTk5NTksMS4wMDA3NywuOTk5NTksMS4wMDAwMywuOTk5OTgsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLDEuMDAwNzcsLjk5OTczLC45OTk5OCwxLjAwMDI1LC45OTk2OCwuOTk5NzMsMS4wMDAwMywxLjAwMDI1LC42MDI5OSwxLjAwMDI0LDEuMDY0MDksMSwxLC45OTk5OCwxLC45OTk3MywxLjAwMDYsLjk5OTk4LDEsLjk5OTM2LC45OTk3MywxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDI2LC45OTk3NywuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsLjk5OTc3LDEsLjk5OTc3LDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTk3NywuOTk5NzcsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMjIsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMDMsMS4wMDAyMiwuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTgyLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wNjQwOSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsLjk5OTczLDEuMDAwMjYsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LDEuMDMzNzQsLjk5OTc3LDEuMDAwMjYsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAyMiwxLjAwMDI2LDEuMDAwMjIsMS4wMDAyNiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAyMiwxLjAwMDI2LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDQyLC45OTk3MywuOTk5NzMsMS4wMDA2LC45OTk3NywuOTk5NzMsLjk5OTczLDEuMDAwMjYsMS4wMDA2LDEuMDAwMjYsMS4wMDA2LDEuMDAwMjYsMS4wMzgyOCwxLjAwMDI2LC45OTk5OSwxLjAwMDI2LDEuMDAwNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5MywuOTk5OCwxLjAwMDI2LDEuMDAwMjIsMS4wMDAyNiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAyMiwxLjAwMDI2LDEsMS4wMDAxNiwuOTk5NzcsLjk5OTU5LC45OTk3NywuOTk5NTksLjk5OTc3LC45OTk1OSwxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDI2LC45OTk5OCwxLjAwMDI2LC44MTIxLDEuMDAwMjYsLjk5OTk4LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LC45OTk3NywxLjAwMDI2LDEuMDAwMTYsMS4wMDAyMiwxLjAwMDAxLC45OTk3MywxLjAwMDAxLDEuMDAwMjYsMSwxLjAwMDI2LDEsMS4wMDAyNiwxLDEuMDAwNiwuOTk5NzMsLjk5OTc3LC45OTk3MywxLC45OTk4MiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAwMSwuOTk5NzMsMS4wMDAyNiwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LDEuMDAwMzQsLjk5OTc3LDEsLjk5OTk3LDEuMDAwMjYsMS4wMDA3OCwxLjAwMDM2LC45OTk3MywxLjAwMDEzLDEuMDAwNiwuOTk5NzcsLjk5OTc3LC45OTk4OCwuODUxNDgsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDIyLDEuMDAwNiwuOTk5NzcsMS4wMDAwMSwuOTk5OTksLjk5OTc3LDEuMDAwNjksMS4wMDAyMiwuOTk5NzcsMS4wMDAwMSwuOTk5ODQsMS4wMDAyNiwxLjAwMDAxLDEuMDAwMjQsMS4wMDAwMSwuOTk5OSwxLDEuMDAwNiwxLjAwMDAxLDEuMDAwNDEsLjk5OTYyLDEuMDAwMjYsMS4wMDA2LC45OTk5NSwxLjAwMDQxLC45OTk0MiwuOTk5NzMsLjk5OTI3LDEuMDAwODIsLjk5OTAyLDEuMDAwMjYsMS4wMDA4NywxLjAwMDYsMS4wMDA2OSwuOTk5NzMsLjk5ODY3LC45OTk3MywuOTk5MywxLjAwMDI2LDEuMDAwNDksMS4wMDA1NiwxLC45OTk4OCwuOTk5MzUsLjk5OTk1LC45OTk1NCwxLjAwMDU1LC45OTk0NSwxLjAwMDMyLDEuMDAwNiwuOTk5OTUsMS4wMDAyNiwuOTk5OTUsMS4wMDAzMiwxLjAwMDAxLDEuMDAwMDgsLjk5OTcxLDEuMDAwMTksLjk5OTQsMS4wMDAwMSwxLjAwMDYsMS4wMDA0NCwuOTk5NzMsMS4wMDAyMywxLjAwMDQ3LDEsLjk5OTQyLC45OTU2MSwuOTk5ODksMS4wMDAzNSwuOTk5NzcsMS4wMDAzNSwuOTk5NzcsMS4wMDAxOSwuOTk5NDQsMS4wMDAwMSwxLjAwMDIxLC45OTkyNiwxLjAwMDM1LDEuMDAwMzUsLjk5OTQyLDEuMDAwNDgsLjk5OTk5LC45OTk3NywxLjAwMDIyLDEuMDAwMzUsMS4wMDAwMSwuOTk5NzcsMS4wMDAyNiwuOTk5ODksMS4wMDA1NywxLjAwMDAxLC45OTkzNiwxLjAwMDUyLDEuMDAwMTIsLjk5OTk2LDEuMDAwNDMsMSwxLjAwMDM1LC45OTk0LC45OTk3NiwxLjAwMDM1LC45OTk3MywxLjAwMDUyLDEuMDAwNDEsMS4wMDExOSwxLjAwMDM3LC45OTk3MywxLjAwMDAyLC45OTk4NiwxLjAwMDQxLDEuMDAwNDEsLjk5OTAyLC45OTk2LDEuMDAwMzQsLjk5OTk5LDEuMDAwMjYsLjk5OTk5LDEuMDAwMjYsLjk5OTczLDEuMDAwNTIsLjk5OTczLDEsLjk5OTczLDEuMDAwNDEsMS4wMDA3NSwuOTk5NCwxLjAwMDMsLjk5OTk5LDEsMS4wMDA0MSwuOTk5NTUsMSwuOTk5MTUsLjk5OTczLC45OTk3MywxLjAwMDI2LDEuMDAxMTksLjk5OTU1LC45OTk3MywxLjAwMDYsLjk5OTExLDEuMDAwNiwxLjAwMDI2LC45OTk3MiwxLjAwMDI2LC45OTkwMiwxLjAwMDQxLC45OTk3MywuOTk5OTksMSwxLDEuMDAwMzgsMS4wMDA1LDEuMDAwMTYsMS4wMDAyMiwxLjAwMDE2LDEuMDAwMjIsMS4wMDAxNiwxLjAwMDIyLDEuMDAwMDEsLjk5OTczLDEsMSwuOTk5NzMsMSwxLC45OTk1NSwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMSwxLDEsLjk5OTczLC45OTk3MywuOTk5NzIsMSwxLDEuMDAxMDYsLjk5OTk5LC45OTk5OCwuOTk5OTgsLjk5OTk5LC45OTk5OCwxLjY2NDc1LDEsLjk5OTczLC45OTk3MywxLjAwMDIzLC45OTk3MywuOTk5NzEsMS4wMDA0NywxLjAwMDIzLDEsLjk5OTkxLC45OTk4NCwxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDAyLDEsMSwxLDEsMSwxLDEsLjk5OTcyLDEsMS4yMDk4NSwxLjM5NzEzLDEuMDAwMDMsMS4wMDAzMSwxLjAwMDE1LDEsLjk5NTYxLDEuMDAwMjcsMS4wMDAzMSwxLjAwMDMxLC45OTkxNSwxLjAwMDMxLDEuMDAwMzEsLjk5OTk5LDEuMDAwMDMsLjk5OTk5LC45OTk5OSwxLjQxMTQ0LDEuNiwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDA1NzksMS40MDU3OSwxLjM2NjI1LC45OTk5OSwxLC45OTg2MSwuOTk4NjEsMSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LC45OTk3MiwuOTk5OTksLjk5OTk5LC45OTk5OSwuOTk5OTksMS40MDQ4MywxLC45OTk3NywxLjAwMDU0LDEsMSwuOTk5NTMsLjk5OTYyLDEuMDAwNDIsLjk5OTUsMSwxLDEsMSwxLDEsMSwxLC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLHZuPXtsaW5lSGVpZ2h0OjEuMixsaW5lR2FwOi4yfSxGbj1bLjc2MTE2LDEsMSwxLjAwMDYsLjk5OTk4LC45OTk3NCwuOTk5NzMsLjk5OTczLC45OTk4MiwuOTk5NzcsMS4wMDA4NywuOTk5OTgsLjk5OTk4LC45OTk1OSwxLjAwMDAzLDEuMDAwNiwuOTk5OTgsMS4wMDA2LDEuMDAwNiwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTk4LDEsMS4wMDAwMywxLjAwMDAzLDEuMDAwMDMsMS4wMDAyNiwuOTk5OSwuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsMS4wMDAwMSwxLjAwMDI2LDEuMDAwMjIsLjk5OTc3LDEuMDAwNiwuOTk5NzMsLjk5OTc3LDEuMDAwMjYsLjk5OTk5LC45OTk3NywxLjAwMDIyLDEuMDAwMDEsMS4wMDAyMiwuOTk5NzcsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDAxLDEuMDAwMTYsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsLjk5OTk4LDEuMDAwNiwuOTk5OTgsMS4wMDAwMywuOTk5NzMsLjk5OTk4LC45OTk3MywxLjAwMDI2LC45OTk3MywxLjAwMDI2LC45OTk3MywuOTk5OTgsMS4wMDAyNiwxLjAwMDI2LDEuMDAwNiwxLjAwMDYsLjk5OTczLDEuMDAwNiwuOTk5ODIsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwuOTk5NTksLjk5OTczLC45OTk5OCwxLjAwMDI2LC45OTk3MywxLjAwMDIyLC45OTk3MywuOTk5NzMsMSwuOTk5NTksMS4wMDA3NywuOTk5NTksMS4wMDAwMywuOTk5OTgsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLDEuMDAwNzcsLjk5OTczLC45OTk5OCwxLjAwMDI1LC45OTk2OCwuOTk5NzMsMS4wMDAwMywxLjAwMDI1LC42MDI5OSwxLjAwMDI0LDEuMDY0MDksMSwxLC45OTk5OCwxLC45OTk3MywxLjAwMDYsLjk5OTk4LDEsLjk5OTM2LC45OTk3MywxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDI2LC45OTk3NywuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsLjk5OTc3LDEsLjk5OTc3LDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTk3NywuOTk5NzcsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMjIsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMDMsMS4wMDAyMiwuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTgyLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsMS4wNjQwOSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsLjk5OTczLDEuMDAwMjYsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LDEuMDA0NCwuOTk5NzcsMS4wMDAyNiwxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDIyLDEuMDAwMjYsMS4wMDAyMiwxLjAwMDI2LDEuMDAwMjIsMS4wMDAyNiwxLjAwMDIyLDEuMDAwMjYsLjk5OTc3LDEuMDAwMjYsLjk5OTc3LDEuMDAwMjYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTk3MSwuOTk5NzMsLjk5OTczLDEuMDAwNiwuOTk5NzcsLjk5OTczLC45OTk3MywxLjAwMDI2LDEuMDAwNiwxLjAwMDI2LDEuMDAwNiwxLjAwMDI2LDEuMDEwMTEsMS4wMDAyNiwuOTk5OTksMS4wMDAyNiwxLjAwMDYsLjk5OTc3LDEuMDAwMjYsLjk5OTc3LDEuMDAwMjYsLjk5OTc3LDEuMDAwMjYsLjk5OTMsLjk5OTgsMS4wMDAyNiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAyMiwxLjAwMDI2LDEuMDAwMjIsMS4wMDAyNiwxLDEuMDAwMTYsLjk5OTc3LC45OTk1OSwuOTk5NzcsLjk5OTU5LC45OTk3NywuOTk5NTksMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAyNiwuOTk5OTgsMS4wMDAyNiwuODEyMSwxLjAwMDI2LC45OTk5OCwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwuOTk5NzcsMS4wMDAyNiwxLjAwMDE2LDEuMDAwMjIsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwxLjAwMDI2LDEsMS4wMDAyNiwxLDEuMDAwMjYsMSwxLjAwMDYsLjk5OTczLC45OTk3NywuOTk5NzMsMSwuOTk5ODIsMS4wMDAyMiwxLjAwMDI2LDEuMDAwMDEsLjk5OTczLDEuMDAwMjYsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTc3LDEsMSwxLjAwMDI2LC45OTk2OSwuOTk5NzIsLjk5OTgxLC45OTk4LDEuMDAwNiwuOTk5NzcsLjk5OTc3LDEuMDAwMjIsLjkxMTU1LDEuMDAwMDEsMS4wMDAyNiwuOTk5NzcsMS4wMDAyMiwxLjAwMDYsLjk5OTc3LDEuMDAwMDEsLjk5OTk5LC45OTk3NywuOTk5NjYsMS4wMDAyMiwxLjAwMDMyLDEuMDAwMDEsLjk5OTQ0LDEuMDAwMjYsMS4wMDAwMSwuOTk5NjgsMS4wMDAwMSwxLjAwMDQ3LDEsMS4wMDA2LDEuMDAwMDEsLjk5OTgxLDEuMDAxMDEsMS4wMDAyNiwxLjAwMDYsLjk5OTQ4LC45OTk4MSwxLjAwMDY0LC45OTk3MywuOTk5NDIsMS4wMDEwMSwxLjAwMDYxLDEuMDAwMjYsMS4wMDA2OSwxLjAwMDYsMS4wMDAxNCwuOTk5NzMsMS4wMTMyMiwuOTk5NzMsMS4wMDA2NSwxLjAwMDI2LDEuMDAwMTIsLjk5OTIzLDEsMS4wMDA2NCwxLjAwMDc2LC45OTk0OCwxLjAwMDU1LDEuMDAwNjMsMS4wMDAwNywuOTk5NDMsMS4wMDA2LC45OTk0OCwxLjAwMDI2LC45OTk0OCwuOTk5NDMsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjksMS4wMDAzOCwxLjAwMDM1LDEuMDAwMDEsMS4wMDA2LDEuMDAwNiwuOTk5NzMsLjk5OTc4LDEuMDAwMDEsMS4wMDA1NywuOTk5ODksLjk5OTY3LC45OTk2NCwuOTk5NjcsLjk5OTc3LC45OTk5OSwuOTk5NzcsMS4wMDAzOCwuOTk5NzcsMS4wMDAwMSwuOTk5NzMsMS4wMDA2NiwuOTk5NjcsLjk5OTY3LDEuMDAwNDEsLjk5OTk4LC45OTk5OSwuOTk5NzcsMS4wMDAyMiwuOTk5NjcsMS4wMDAwMSwuOTk5NzcsMS4wMDAyNiwuOTk5NjQsMS4wMDAzMSwxLjAwMDAxLC45OTk5OSwuOTk5OTksMSwxLjAwMDIzLDEsMSwuOTk5OTksMS4wMDAzNSwxLjAwMDAxLC45OTk5OSwuOTk5NzMsLjk5OTc3LC45OTk5OSwxLjAwMDU4LC45OTk3MywuOTk5NzMsLjk5OTU1LC45OTk1LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDMyLC45OTk4OSwxLjAwMDM0LC45OTk5OSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwuOTk5NzMsLjQ1OTk4LC45OTk3MywxLjAwMDI2LC45OTk3MywxLjAwMDAxLC45OTk5OSwuOTk5ODIsLjk5OTk0LC45OTk5NiwxLDEuMDAwNDIsMS4wMDA0NCwxLjAwMDI5LDEuMDAwMjMsLjk5OTczLC45OTk3MywxLjAwMDI2LC45OTk0OSwxLjAwMDAyLC45OTk3MywxLjAwMDYsMS4wMDA2LDEuMDAwNiwuOTk5NzUsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMzIsLjk4Njg1LC45OTk3MywxLjAwMDI2LDEsMSwuOTk5NjYsMS4wMDA0NCwxLjAwMDE2LDEuMDAwMjIsMS4wMDAxNiwxLjAwMDIyLDEuMDAwMTYsMS4wMDAyMiwxLjAwMDAxLC45OTk3MywxLDEsLjk5OTczLDEsMSwuOTk5NTUsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEsMSwxLC45OTk3MywuOTk5NzMsLjk5OTcyLDEsMSwxLjAwMTA2LC45OTk5OSwuOTk5OTgsLjk5OTk4LC45OTk5OSwuOTk5OTgsMS42NjQ3NSwxLC45OTk3MywuOTk5NzMsMSwuOTk5NzMsLjk5OTcxLC45OTk3OCwxLDEsLjk5OTkxLC45OTk4NCwxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDAyLDEuMDAwOTgsMSwxLDEsMS4wMDA0OSwxLDEsLjk5OTcyLDEsMS4yMDk4NSwxLjM5NzEzLDEuMDAwMDMsMS4wMDAzMSwxLjAwMDE1LDEsLjk5NTYxLDEuMDAwMjcsMS4wMDAzMSwxLjAwMDMxLC45OTkxNSwxLjAwMDMxLDEuMDAwMzEsLjk5OTk5LDEuMDAwMDMsLjk5OTk5LC45OTk5OSwxLjQxMTQ0LDEuNiwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDA1NzksMS40MDU3OSwxLjM2NjI1LC45OTk5OSwxLC45OTg2MSwuOTk4NjEsMSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LC45OTk3MiwuOTk5OTksLjk5OTk5LC45OTk5OSwuOTk5OTksMS40MDQ4MywxLC45OTk3NywxLjAwMDU0LDEsMSwuOTk5NTMsLjk5OTYyLDEuMDAwNDIsLjk5OTUsMSwxLDEsMSwxLDEsMSwxLC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLEluPXtsaW5lSGVpZ2h0OjEuMzUsbGluZUdhcDouMn0sVG49Wy43NjExNiwxLDEsMS4wMDA2LDEuMDAwNiwxLjAwMDA2LC45OTk3MywuOTk5NzMsLjk5OTgyLDEuMDAwMDEsMS4wMDA0MywuOTk5OTgsLjk5OTk4LC45OTk1OSwxLjAwMDAzLDEuMDAwNiwuOTk5OTgsMS4wMDA2LDEuMDAwNiwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDA2LDEsMS4wMDAwMywxLjAwMDAzLDEuMDAwMDMsLjk5OTczLC45OTk4NywxLjAwMDAxLDEuMDAwMDEsLjk5OTc3LC45OTk3NywxLjAwMDAxLDEuMDAwMjYsMS4wMDAyMiwuOTk5NzcsMS4wMDA2LDEsMS4wMDAwMSwuOTk5NzMsLjk5OTk5LC45OTk3NywxLjAwMDIyLDEuMDAwMDEsMS4wMDAyMiwuOTk5NzcsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDAxLDEuMDAwMTYsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsLjk5OTQ5LC45OTk3MywuOTk5OTgsLjk5OTczLC45OTk3MywxLC45OTk3MywuOTk5NzMsMS4wMDA2LC45OTk3MywuOTk5NzMsLjk5OTI0LC45OTkyNCwxLC45OTkyNCwuOTk5OTksLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk5OCwxLDEuMDAwNiwuOTk5NzMsMSwuOTk5NzcsMSwxLDEsMS4wMDAwNSwxLjAwMDksMS4wMDAwNSwxLjAwMDAzLC45OTk5OCwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDA5LC45OTk3MywuOTk5OTgsMS4wMDAyNSwuOTk5NjgsLjk5OTczLDEuMDAwMDMsMS4wMDAyNSwuNjAyOTksMS4wMDAyNCwxLjA2NDA5LDEsMSwuOTk5OTgsMSwuOTk5OCwxLjAwMDYsLjk5OTk4LDEsLjk5OTM2LC45OTk3MywxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDI2LDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEsLjk5OTc3LDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTk3NywuOTk5NzcsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMjIsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMDMsMS4wMDAyMiwuOTk5NzcsLjk5OTc3LC45OTk3NywuOTk5NzcsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjYsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTgyLDEsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wNjQwOSwxLjAwMDI2LC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywxLC45OTk3MywxLDEuMDAwMDEsLjk5OTczLDEuMDAwMDEsLjk5OTczLDEuMDAwMDEsLjk5OTczLC45OTk3NywxLC45OTk3NywxLC45OTk3NywxLC45OTk3NywxLC45OTk3NywxLjAyODgsLjk5OTc3LC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTkyNCwxLjAwMDYsMS4wMDA2LC45OTk0NiwxLjAwMDM0LDEsLjk5OTI0LDEuMDAwMDEsMSwxLC45OTk3MywuOTk5MjQsLjk5OTczLC45OTkyNCwuOTk5NzMsMS4wNjMxMSwuOTk5NzMsMS4wMDAyNCwuOTk5NzMsLjk5OTI0LC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLDEuMDAwNDEsLjk5OTgsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEsMS4wMDAxNiwuOTk5NzcsLjk5OTk4LC45OTk3NywuOTk5OTgsLjk5OTc3LC45OTk5OCwxLjAwMDAxLDEsMS4wMDAwMSwxLDEuMDAwMDEsMSwxLjAwMDAxLDEsMS4wMDAyNiwxLjAwMDYsMS4wMDAyNiwuODk1NDcsMS4wMDAyNiwxLjAwMDYsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsMS4wMDAxNiwuOTk5NzcsMS4wMDAwMSwxLDEuMDAwMDEsMS4wMDAyNiwxLDEuMDAwMjYsMSwxLjAwMDI2LDEsLjk5OTI0LC45OTk3MywxLjAwMDAxLC45OTk3MywxLC45OTk4MiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAwMSwxLDEuMDAwMjYsMS4wMDA2LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsMS4wMDAwMSwxLDEuMDAwNTQsLjk5OTc3LDEuMDAwODQsMS4wMDAwNywuOTk5NzMsMS4wMDAxMywuOTk5MjQsMS4wMDAwMSwxLjAwMDAxLC45OTk0NSwuOTEyMjEsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDIyLDEuMDAwNiwxLjAwMDAxLDEuMDAwMDEsLjk5OTk5LC45OTk3NywuOTk5MzMsMS4wMDAyMiwxLjAwMDU0LDEuMDAwMDEsMS4wMDA2NSwxLjAwMDI2LDEuMDAwMDEsMS4wMDAxLDEuMDAwMDEsMS4wMDA1MiwxLDEuMDAwNiwxLjAwMDAxLC45OTk0NSwuOTk4OTcsLjk5OTY4LC45OTkyNCwxLjAwMDM2LC45OTk0NSwuOTk5NDksMSwxLjAwMDYsLjk5ODk3LC45OTkxOCwuOTk5NjgsLjk5OTExLC45OTkyNCwxLC45OTk2MiwxLjAxNDg3LDEsMS4wMDA1LC45OTk3MywxLjAwMDEyLDEuMDAwNDMsMSwuOTk5OTUsLjk5OTk0LDEuMDAwMzYsLjk5OTQ3LDEuMDAwMTksMS4wMDA2MywxLjAwMDI1LC45OTkyNCwxLjAwMDM2LC45OTk3MywxLjAwMDM2LDEuMDAwMjUsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMjcsMS4wMDAxLDEuMDAwNjgsMS4wMDAwMSwxLjAwMDYsMS4wMDA2LDEsMS4wMDAwOCwuOTk5NTcsLjk5OTcyLC45OTk0LC45OTk1NCwuOTk5NzUsMS4wMDA1MSwxLjAwMDAxLDEuMDAwMTksMS4wMDAwMSwxLjAwMDEsLjk5OTg2LDEuMDAwMDEsMS4wMDAwMSwxLjAwMDM4LC45OTk1NCwuOTk5NTQsLjk5OTQsMS4wMDA2NiwuOTk5OTksLjk5OTc3LDEuMDAwMjIsMS4wMDA1NCwxLjAwMDAxLC45OTk3NywxLjAwMDI2LC45OTk3NSwxLjAwMDEsMS4wMDAwMSwuOTk5OTMsLjk5OTUsLjk5OTU1LDEuMDAwMTYsLjk5OTc4LC45OTk3NCwxLjAwMDE5LDEuMDAwMjIsLjk5OTU1LDEuMDAwNTMsLjk5OTczLDEuMDAwODksMS4wMDAwNSwuOTk5NjcsMS4wMDA0OCwuOTk5NzMsMS4wMDAwMiwxLjAwMDM0LC45OTk3MywuOTk5NzMsLjk5OTY0LDEuMDAwMDYsMS4wMDA2NiwuOTk5NDcsLjk5OTczLC45ODg5NCwuOTk5NzMsMSwuNDQ4OTgsMSwuOTk5NDYsMSwxLjAwMDM5LDEuMDAwODIsLjk5OTkxLC45OTk5MSwuOTk5ODUsMS4wMDAyMiwxLjAwMDIzLDEuMDAwNjEsMS4wMDAwNiwuOTk5NjYsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDAxOSwxLjAwMDgsMSwuOTk5MjQsLjk5OTI0LC45OTkyNCwuOTk5ODMsMS4wMDA0NCwuOTk5NzMsLjk5OTY0LC45ODMzMiwxLC45OTk3MywxLDEsLjk5OTYyLC45OTg5NSwxLjAwMDE2LC45OTk3NywxLjAwMDE2LC45OTk3NywxLjAwMDE2LC45OTk3NywxLjAwMDAxLDEsMSwxLC45OTk3MywxLDEsLjk5OTU1LC45OTkyNCwuOTk5MjQsLjk5OTI0LC45OTkyNCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5NzMsLjk5OTczLC45OTk3MiwxLDEsMS4wMDI2NywuOTk5OTksLjk5OTk4LC45OTk5OCwxLC45OTk5OCwxLjY2NDc1LDEsLjk5OTczLC45OTk3MywxLjAwMDIzLC45OTk3MywxLjAwNDIzLC45OTkyNSwuOTk5OTksMSwuOTk5OTEsLjk5OTg0LDEuMDAwMDIsMS4wMDAwMiwxLjAwMDAyLDEuMDAwMDIsMS4wMDA0OSwxLDEuMDAyNDUsMSwxLDEsMSwuOTYzMjksMSwxLjIwOTg1LDEuMzk3MTMsMS4wMDAwMywuODI1NCwxLjAwMDE1LDEsMS4wMDAzNSwxLjAwMDI3LDEuMDAwMzEsMS4wMDAzMSwxLjAwMDAzLDEuMDAwMzEsMS4wMDAzMSwuOTk5OTksMS4wMDAwMywuOTk5OTksLjk5OTk5LDEuNDExNDQsMS42LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MDU3OSwxLjQwNTc5LDEuMzY2MjUsLjk5OTk5LDEsLjk5ODYxLC45OTg2MSwxLDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LDEuMDAwMjYsLjk1MzE3LC45OTk5OSwuOTk5OTksLjk5OTk5LC45OTk5OSwxLjQwNDgzLDEsLjk5OTc3LDEuMDAwNTQsMSwxLC45OTk1MywuOTk5NjIsMS4wMDA0MiwuOTk5NSwxLDEsMSwxLDEsMSwxLDEsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0sT249e2xpbmVIZWlnaHQ6MS4zNSxsaW5lR2FwOi4yfSxNbj1bLjc2MTE2LDEsMSwxLjAwMDYsMS4wMDA2LDEuMDAwMDYsLjk5OTczLC45OTk3MywuOTk5ODIsMS4wMDAwMSwxLjAwMDQzLC45OTk5OCwuOTk5OTgsLjk5OTU5LDEuMDAwMDMsMS4wMDA2LC45OTk5OCwxLjAwMDYsMS4wMDA2LC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywxLjAwMDYsMSwxLjAwMDAzLDEuMDAwMDMsMS4wMDAwMywuOTk5NzMsLjk5OTg3LDEuMDAwMDEsMS4wMDAwMSwuOTk5NzcsLjk5OTc3LDEuMDAwMDEsMS4wMDAyNiwxLjAwMDIyLC45OTk3NywxLjAwMDYsMSwxLjAwMDAxLC45OTk3MywuOTk5OTksLjk5OTc3LDEuMDAwMjIsMS4wMDAwMSwxLjAwMDIyLC45OTk3NywxLjAwMDAxLDEuMDAwMjYsLjk5OTc3LDEuMDAwMDEsMS4wMDAxNiwxLjAwMDAxLDEuMDAwMDEsMS4wMDAyNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwuOTk5NDksLjk5OTczLC45OTk5OCwuOTk5NzMsLjk5OTczLDEsLjk5OTczLC45OTk3MywxLjAwMDYsLjk5OTczLC45OTk3MywuOTk5MjQsLjk5OTI0LDEsLjk5OTI0LC45OTk5OSwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTk4LDEsMS4wMDA2LC45OTk3MywxLC45OTk3NywxLDEsMSwxLjAwMDA1LDEuMDAwOSwxLjAwMDA1LDEuMDAwMDMsLjk5OTk4LC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywxLjAwMDksLjk5OTczLC45OTk5OCwxLjAwMDI1LC45OTk2OCwuOTk5NzMsMS4wMDAwMywxLjAwMDI1LC42MDI5OSwxLjAwMDI0LDEuMDY0MDksMSwxLC45OTk5OCwxLC45OTk4LDEuMDAwNiwuOTk5OTgsMSwuOTk5MzYsLjk5OTczLDEuMDAwMDIsMS4wMDAwMiwxLjAwMDAyLDEuMDAwMjYsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMSwuOTk5NzcsMS4wMDAwMSwxLjAwMDAxLDEuMDAwMDEsMS4wMDAwMSwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsLjk5OTc3LC45OTk3NywxLjAwMDIyLDEuMDAwMjIsMS4wMDAyMiwxLjAwMDIyLDEuMDAwMjIsMS4wMDAwMywxLjAwMDIyLC45OTk3NywuOTk5NzcsLjk5OTc3LC45OTk3NywxLjAwMDAxLDEuMDAwMDEsMS4wMDAyNiwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5ODIsMSwuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLC45OTk3MywxLjA2NDA5LDEuMDAwMjYsLjk5OTczLC45OTk3MywuOTk5NzMsLjk5OTczLDEsLjk5OTczLDEsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsMS4wMDAwMSwuOTk5NzMsLjk5OTc3LDEsLjk5OTc3LDEsLjk5OTc3LDEsLjk5OTc3LDEsLjk5OTc3LDEuMDQ1OTYsLjk5OTc3LC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDAxLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywxLjAwMDIyLC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LDEuMDAwNiwxLjAwMDYsMS4wMDA2LC45OTkyNCwxLjAwMDYsMS4wMDA2LDEuMDAwMTksMS4wMDAzNCwxLC45OTkyNCwxLjAwMDAxLDEsMSwuOTk5NzMsLjk5OTI0LC45OTk3MywuOTk5MjQsLjk5OTczLDEuMDI1NzIsLjk5OTczLDEuMDAwMDUsLjk5OTczLC45OTkyNCwuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5OTksLjk5OTgsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEuMDAwMjIsLjk5OTczLDEsMS4wMDAxNiwuOTk5NzcsLjk5OTk4LC45OTk3NywuOTk5OTgsLjk5OTc3LC45OTk5OCwxLjAwMDAxLDEsMS4wMDAwMSwxLDEuMDAwMDEsMSwxLjAwMDAxLDEsMS4wMDAyNiwxLjAwMDYsMS4wMDAyNiwuODQ1MzMsMS4wMDAyNiwxLjAwMDYsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsLjk5OTc3LC45OTk3MywuOTk5NzcsLjk5OTczLC45OTk3NywuOTk5NzMsMS4wMDAxNiwuOTk5NzcsMS4wMDAwMSwxLDEuMDAwMDEsMS4wMDAyNiwxLDEuMDAwMjYsMSwxLjAwMDI2LDEsLjk5OTI0LC45OTk3MywxLjAwMDAxLC45OTk3MywxLC45OTk4MiwxLjAwMDIyLDEuMDAwMjYsMS4wMDAwMSwxLDEuMDAwMjYsMS4wMDA2LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk5OCwuOTk5OTgsLjk5OTI4LDEsLjk5OTc3LDEuMDAwMTMsMS4wMDA1NSwuOTk5NDcsLjk5OTQ1LC45OTk0MSwuOTk5MjQsMS4wMDAwMSwxLjAwMDAxLDEuMDAwNCwuOTE2MjEsMS4wMDAwMSwxLjAwMDI2LC45OTk3NywxLjAwMDIyLDEuMDAwNiwxLjAwMDAxLDEuMDAwMDUsLjk5OTk5LC45OTk3NywxLjAwMDE1LDEuMDAwMjIsLjk5OTc3LDEuMDAwMDEsLjk5OTczLDEuMDAwMjYsMS4wMDAwMSwxLjAwMDE5LDEuMDAwMDEsLjk5OTQ2LDEsMS4wMDA2LDEuMDAwMDEsLjk5OTc4LDEuMDAwNDUsLjk5OTczLC45OTkyNCwxLjAwMDIzLC45OTk3OCwuOTk5NjYsMSwxLjAwMDY1LDEuMDAwNDUsMS4wMDAxOSwuOTk5NzMsLjk5OTczLC45OTkyNCwxLDEsLjk2NDk5LDEsMS4wMDA1NSwuOTk5NzMsMS4wMDAwOCwxLjAwMDI3LDEsLjk5OTcsLjk5OTk1LDEuMDAwMjMsLjk5OTMzLDEuMDAwMTksMS4wMDAxNSwxLjAwMDMxLC45OTkyNCwxLjAwMDIzLC45OTk3MywxLjAwMDIzLDEuMDAwMzEsMS4wMDAwMSwuOTk5MjgsMS4wMDAyOSwxLjAwMDkyLDEuMDAwMzUsMS4wMDAwMSwxLjAwMDYsMS4wMDA2LDEsLjk5OTg4LC45OTk3NSwxLDEuMDAwODIsLjk5NTYxLC45OTk2LDEuMDAwMzUsMS4wMDAwMSwuOTk5NjIsMS4wMDAwMSwxLjAwMDkyLC45OTk2NCwxLjAwMDAxLC45OTk2MywuOTk5OTksMS4wMDAzNSwxLjAwMDM1LDEuMDAwODIsLjk5OTYyLC45OTk5OSwuOTk5NzcsMS4wMDAyMiwxLjAwMDM1LDEuMDAwMDEsLjk5OTc3LDEuMDAwMjYsLjk5OTYsLjk5OTY3LDEuMDAwMDEsMS4wMDAzNCwxLjAwMDc0LDEuMDAwNTQsMS4wMDA1MywxLjAwMDYzLC45OTk3MSwuOTk5NjIsMS4wMDAzNSwuOTk5NzUsLjk5OTc3LC45OTk3MywxLjAwMDQzLC45OTk1MywxLjAwMDcsLjk5OTE1LC45OTk3MywxLjAwMDA4LC45OTg5MiwxLjAwMDczLDEuMDAwNzMsMS4wMDExNCwuOTk5MTUsMS4wMDA3MywuOTk5NTUsLjk5OTczLDEuMDAwOTIsLjk5OTczLDEsLjk5OTk4LDEsMS4wMDAzLDEsMS4wMDA0MywxLjAwMDAxLC45OTk2OSwxLjAwMDMsMSwxLjAwMDM1LDEuMDAwMDEsLjk5OTUsMSwxLjAwMDkyLC45OTk3MywuOTk5NzMsLjk5OTczLDEuMDAwNywuOTk5NSwxLC45OTkyNCwxLjAwMDYsLjk5OTI0LC45OTk3MiwxLjAwMDYyLC45OTk3MywxLjAwMTE0LDEuMDAwNzMsMSwuOTk5NTUsMSwxLDEuMDAwNDcsLjk5OTY4LDEuMDAwMTYsLjk5OTc3LDEuMDAwMTYsLjk5OTc3LDEuMDAwMTYsLjk5OTc3LDEuMDAwMDEsMSwxLDEsLjk5OTczLDEsMSwuOTk5NTUsLjk5OTI0LC45OTkyNCwuOTk5MjQsLjk5OTI0LC45OTk5OCwuOTk5OTgsLjk5OTk4LC45OTk3MywuOTk5NzMsLjk5OTcyLDEsMSwxLjAwMjY3LC45OTk5OSwuOTk5OTgsLjk5OTk4LDEsLjk5OTk4LDEuNjY0NzUsMSwuOTk5NzMsLjk5OTczLDEuMDAwMjMsLjk5OTczLC45OTk3MSwuOTk5MjUsMS4wMDAyMywxLC45OTk5MSwuOTk5ODQsMS4wMDAwMiwxLjAwMDAyLDEuMDAwMDIsMS4wMDAwMiwxLDEsMSwxLDEsMSwxLC45NjMyOSwxLDEuMjA5ODUsMS4zOTcxMywxLjAwMDAzLC44MjU0LDEuMDAwMTUsMSwxLjAwMDM1LDEuMDAwMjcsMS4wMDAzMSwxLjAwMDMxLC45OTkxNSwxLjAwMDMxLDEuMDAwMzEsLjk5OTk5LDEuMDAwMDMsLjk5OTk5LC45OTk5OSwxLjQxMTQ0LDEuNiwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDExNDQsMS40MTE0NCwxLjQxMTQ0LDEuNDA1NzksMS40MDU3OSwxLjM2NjI1LC45OTk5OSwxLC45OTg2MSwuOTk4NjEsMSwxLjAwMDI2LDEuMDAwMjYsMS4wMDAyNiwxLjAwMDI2LC45NTMxNywuOTk5OTksLjk5OTk5LC45OTk5OSwuOTk5OTksMS40MDQ4MywxLC45OTk3NywxLjAwMDU0LDEsMSwuOTk5NTMsLjk5OTYyLDEuMDAwNDIsLjk5OTUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSxEbj17bGluZUhlaWdodDoxLjIsbGluZUdhcDouMn0sQm49WzM2NSwwLDMzMywyNzgsMzMzLDQ3NCw1NTYsNTU2LDg4OSw3MjIsMjM4LDMzMywzMzMsMzg5LDU4NCwyNzgsMzMzLDI3OCwyNzgsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDMzMywzMzMsNTg0LDU4NCw1ODQsNjExLDk3NSw3MjIsNzIyLDcyMiw3MjIsNjY3LDYxMSw3NzgsNzIyLDI3OCw1NTYsNzIyLDYxMSw4MzMsNzIyLDc3OCw2NjcsNzc4LDcyMiw2NjcsNjExLDcyMiw2NjcsOTQ0LDY2Nyw2NjcsNjExLDMzMywyNzgsMzMzLDU4NCw1NTYsMzMzLDU1Niw2MTEsNTU2LDYxMSw1NTYsMzMzLDYxMSw2MTEsMjc4LDI3OCw1NTYsMjc4LDg4OSw2MTEsNjExLDYxMSw2MTEsMzg5LDU1NiwzMzMsNjExLDU1Niw3NzgsNTU2LDU1Niw1MDAsMzg5LDI4MCwzODksNTg0LDMzMyw1NTYsNTU2LDU1Niw1NTYsMjgwLDU1NiwzMzMsNzM3LDM3MCw1NTYsNTg0LDczNyw1NTIsNDAwLDU0OSwzMzMsMzMzLDMzMyw1NzYsNTU2LDI3OCwzMzMsMzMzLDM2NSw1NTYsODM0LDgzNCw4MzQsNjExLDcyMiw3MjIsNzIyLDcyMiw3MjIsNzIyLDFlMyw3MjIsNjY3LDY2Nyw2NjcsNjY3LDI3OCwyNzgsMjc4LDI3OCw3MjIsNzIyLDc3OCw3NzgsNzc4LDc3OCw3NzgsNTg0LDc3OCw3MjIsNzIyLDcyMiw3MjIsNjY3LDY2Nyw2MTEsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsODg5LDU1Niw1NTYsNTU2LDU1Niw1NTYsMjc4LDI3OCwyNzgsMjc4LDYxMSw2MTEsNjExLDYxMSw2MTEsNjExLDYxMSw1NDksNjExLDYxMSw2MTEsNjExLDYxMSw1NTYsNjExLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw3MTksNzIyLDYxMSw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNzc4LDYxMSw3NzgsNjExLDc3OCw2MTEsNzc4LDYxMSw3MjIsNjExLDcyMiw2MTEsMjc4LDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDc4NSw1NTYsNTU2LDI3OCw3MjIsNTU2LDU1Niw2MTEsMjc4LDYxMSwyNzgsNjExLDM4NSw2MTEsNDc5LDYxMSwyNzgsNzIyLDYxMSw3MjIsNjExLDcyMiw2MTEsNzA4LDcyMyw2MTEsNzc4LDYxMSw3NzgsNjExLDc3OCw2MTEsMWUzLDk0NCw3MjIsMzg5LDcyMiwzODksNzIyLDM4OSw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2NjcsNTU2LDYxMSwzMzMsNjExLDQ3OSw2MTEsMzMzLDcyMiw2MTEsNzIyLDYxMSw3MjIsNjExLDcyMiw2MTEsNzIyLDYxMSw3MjIsNjExLDk0NCw3NzgsNjY3LDU1Niw2NjcsNjExLDUwMCw2MTEsNTAwLDYxMSw1MDAsMjc4LDU1Niw3MjIsNTU2LDFlMyw4ODksNzc4LDYxMSw2NjcsNTU2LDYxMSwzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDQ2NSw3MjIsMzMzLDg1Myw5MDYsNDc0LDgyNSw5MjcsODM4LDI3OCw3MjIsNzIyLDYwMSw3MTksNjY3LDYxMSw3MjIsNzc4LDI3OCw3MjIsNjY3LDgzMyw3MjIsNjQ0LDc3OCw3MjIsNjY3LDYwMCw2MTEsNjY3LDgyMSw2NjcsODA5LDgwMiwyNzgsNjY3LDYxNSw0NTEsNjExLDI3OCw1ODIsNjE1LDYxMCw1NTYsNjA2LDQ3NSw0NjAsNjExLDU0MSwyNzgsNTU4LDU1Niw2MTIsNTU2LDQ0NSw2MTEsNzY2LDYxOSw1MjAsNjg0LDQ0Niw1ODIsNzE1LDU3Niw3NTMsODQ1LDI3OCw1ODIsNjExLDU4Miw4NDUsNjY3LDY2OSw4ODUsNTY3LDcxMSw2NjcsMjc4LDI3Niw1NTYsMTA5NCwxMDYyLDg3NSw2MTAsNzIyLDYyMiw3MTksNzIyLDcxOSw3MjIsNTY3LDcxMiw2NjcsOTA0LDYyNiw3MTksNzE5LDYxMCw3MDIsODMzLDcyMiw3NzgsNzE5LDY2Nyw3MjIsNjExLDYyMiw4NTQsNjY3LDczMCw3MDMsMTAwNSwxMDE5LDg3MCw5NzksNzE5LDcxMSwxMDMxLDcxOSw1NTYsNjE4LDYxNSw0MTcsNjM1LDU1Niw3MDksNDk3LDYxNSw2MTUsNTAwLDYzNSw3NDAsNjA0LDYxMSw2MDQsNjExLDU1Niw0OTAsNTU2LDg3NSw1NTYsNjE1LDU4MSw4MzMsODQ0LDcyOSw4NTQsNjE1LDU1Miw4NTQsNTgzLDU1Niw1NTYsNjExLDQxNyw1NTIsNTU2LDI3OCwyODEsMjc4LDk2OSw5MDYsNjExLDUwMCw2MTUsNTU2LDYwNCw3NzgsNjExLDQ4Nyw0NDcsOTQ0LDc3OCw5NDQsNzc4LDk0NCw3NzgsNjY3LDU1NiwzMzMsMzMzLDU1NiwxZTMsMWUzLDU1MiwyNzgsMjc4LDI3OCwyNzgsNTAwLDUwMCw1MDAsNTU2LDU1NiwzNTAsMWUzLDFlMywyNDAsNDc5LDMzMywzMzMsNjA0LDMzMywxNjcsMzk2LDU1Niw1NTYsMTA5NCw1NTYsODg1LDQ4OSwxMTE1LDFlMyw3NjgsNjAwLDgzNCw4MzQsODM0LDgzNCwxZTMsNTAwLDFlMyw1MDAsMWUzLDUwMCw1MDAsNDk0LDYxMiw4MjMsNzEzLDU4NCw1NDksNzEzLDk3OSw3MjIsMjc0LDU0OSw1NDksNTgzLDU0OSw1NDksNjA0LDU4NCw2MDQsNjA0LDcwOCw2MjUsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzI5LDYwNCw2MDQsMzU0LDM1NCwxZTMsOTkwLDk5MCw5OTAsOTkwLDQ5NCw2MDQsNjA0LDYwNCw2MDQsMzU0LDEwMjEsMTA1Miw5MTcsNzUwLDc1MCw1MzEsNjU2LDU5NCw1MTAsNTAwLDc1MCw3NTAsNjExLDYxMSwzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDIyMiwyMjIsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzM10sUm49Wy0xLC0xLC0xLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLDYyLDYzLDY0LDY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDc4LDc5LDgwLDgxLDgyLDgzLDg0LDg1LDg2LDg3LDg4LDg5LDkwLDkxLDkyLDkzLDk0LDk1LDk2LDk3LDk4LDk5LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDExOCwxMTksMTIwLDEyMSwxMjIsMTIzLDEyNCwxMjUsMTI2LDE2MSwxNjIsMTYzLDE2NCwxNjUsMTY2LDE2NywxNjgsMTY5LDE3MCwxNzEsMTcyLDE3NCwxNzUsMTc2LDE3NywxNzgsMTc5LDE4MCwxODEsMTgyLDE4MywxODQsMTg1LDE4NiwxODcsMTg4LDE4OSwxOTAsMTkxLDE5MiwxOTMsMTk0LDE5NSwxOTYsMTk3LDE5OCwxOTksMjAwLDIwMSwyMDIsMjAzLDIwNCwyMDUsMjA2LDIwNywyMDgsMjA5LDIxMCwyMTEsMjEyLDIxMywyMTQsMjE1LDIxNiwyMTcsMjE4LDIxOSwyMjAsMjIxLDIyMiwyMjMsMjI0LDIyNSwyMjYsMjI3LDIyOCwyMjksMjMwLDIzMSwyMzIsMjMzLDIzNCwyMzUsMjM2LDIzNywyMzgsMjM5LDI0MCwyNDEsMjQyLDI0MywyNDQsMjQ1LDI0NiwyNDcsMjQ4LDI0OSwyNTAsMjUxLDI1MiwyNTMsMjU0LDI1NSwyNTYsMjU3LDI1OCwyNTksMjYwLDI2MSwyNjIsMjYzLDI2NCwyNjUsMjY2LDI2NywyNjgsMjY5LDI3MCwyNzEsMjcyLDI3MywyNzQsMjc1LDI3NiwyNzcsMjc4LDI3OSwyODAsMjgxLDI4MiwyODMsMjg0LDI4NSwyODYsMjg3LDI4OCwyODksMjkwLDI5MSwyOTIsMjkzLDI5NCwyOTUsMjk2LDI5NywyOTgsMjk5LDMwMCwzMDEsMzAyLDMwMywzMDQsMzA1LDMwNiwzMDcsMzA4LDMwOSwzMTAsMzExLDMxMiwzMTMsMzE0LDMxNSwzMTYsMzE3LDMxOCwzMTksMzIwLDMyMSwzMjIsMzIzLDMyNCwzMjUsMzI2LDMyNywzMjgsMzI5LDMzMCwzMzEsMzMyLDMzMywzMzQsMzM1LDMzNiwzMzcsMzM4LDMzOSwzNDAsMzQxLDM0MiwzNDMsMzQ0LDM0NSwzNDYsMzQ3LDM0OCwzNDksMzUwLDM1MSwzNTIsMzUzLDM1NCwzNTUsMzU2LDM1NywzNTgsMzU5LDM2MCwzNjEsMzYyLDM2MywzNjQsMzY1LDM2NiwzNjcsMzY4LDM2OSwzNzAsMzcxLDM3MiwzNzMsMzc0LDM3NSwzNzYsMzc3LDM3OCwzNzksMzgwLDM4MSwzODIsMzgzLDQwMiw1MDYsNTA3LDUwOCw1MDksNTEwLDUxMSw1MzYsNTM3LDUzOCw1MzksNzEwLDcxMSw3MTMsNzI4LDcyOSw3MzAsNzMxLDczMiw3MzMsOTAwLDkwMSw5MDIsOTAzLDkwNCw5MDUsOTA2LDkwOCw5MTAsOTExLDkxMiw5MTMsOTE0LDkxNSw5MTYsOTE3LDkxOCw5MTksOTIwLDkyMSw5MjIsOTIzLDkyNCw5MjUsOTI2LDkyNyw5MjgsOTI5LDkzMSw5MzIsOTMzLDkzNCw5MzUsOTM2LDkzNyw5MzgsOTM5LDk0MCw5NDEsOTQyLDk0Myw5NDQsOTQ1LDk0Niw5NDcsOTQ4LDk0OSw5NTAsOTUxLDk1Miw5NTMsOTU0LDk1NSw5NTYsOTU3LDk1OCw5NTksOTYwLDk2MSw5NjIsOTYzLDk2NCw5NjUsOTY2LDk2Nyw5NjgsOTY5LDk3MCw5NzEsOTcyLDk3Myw5NzQsMTAyNCwxMDI1LDEwMjYsMTAyNywxMDI4LDEwMjksMTAzMCwxMDMxLDEwMzIsMTAzMywxMDM0LDEwMzUsMTAzNiwxMDM3LDEwMzgsMTAzOSwxMDQwLDEwNDEsMTA0MiwxMDQzLDEwNDQsMTA0NSwxMDQ2LDEwNDcsMTA0OCwxMDQ5LDEwNTAsMTA1MSwxMDUyLDEwNTMsMTA1NCwxMDU1LDEwNTYsMTA1NywxMDU4LDEwNTksMTA2MCwxMDYxLDEwNjIsMTA2MywxMDY0LDEwNjUsMTA2NiwxMDY3LDEwNjgsMTA2OSwxMDcwLDEwNzEsMTA3MiwxMDczLDEwNzQsMTA3NSwxMDc2LDEwNzcsMTA3OCwxMDc5LDEwODAsMTA4MSwxMDgyLDEwODMsMTA4NCwxMDg1LDEwODYsMTA4NywxMDg4LDEwODksMTA5MCwxMDkxLDEwOTIsMTA5MywxMDk0LDEwOTUsMTA5NiwxMDk3LDEwOTgsMTA5OSwxMTAwLDExMDEsMTEwMiwxMTAzLDExMDQsMTEwNSwxMTA2LDExMDcsMTEwOCwxMTA5LDExMTAsMTExMSwxMTEyLDExMTMsMTExNCwxMTE1LDExMTYsMTExNywxMTE4LDExMTksMTEzOCwxMTM5LDExNjgsMTE2OSw3ODA4LDc4MDksNzgxMCw3ODExLDc4MTIsNzgxMyw3OTIyLDc5MjMsODIwOCw4MjA5LDgyMTEsODIxMiw4MjEzLDgyMTUsODIxNiw4MjE3LDgyMTgsODIxOSw4MjIwLDgyMjEsODIyMiw4MjI0LDgyMjUsODIyNiw4MjMwLDgyNDAsODI0Miw4MjQzLDgyNDksODI1MCw4MjUyLDgyNTQsODI2MCw4MzE5LDgzNTUsODM1Niw4MzU5LDgzNjQsODQ1Myw4NDY3LDg0NzAsODQ4Miw4NDg2LDg0OTQsODUzOSw4NTQwLDg1NDEsODU0Miw4NTkyLDg1OTMsODU5NCw4NTk1LDg1OTYsODU5Nyw4NjE2LDg3MDYsODcxMCw4NzE5LDg3MjEsODcyMiw4NzMwLDg3MzQsODczNSw4NzQ1LDg3NDcsODc3Niw4ODAwLDg4MDEsODgwNCw4ODA1LDg5NjIsODk3Niw4OTkyLDg5OTMsOTQ3Miw5NDc0LDk0ODQsOTQ4OCw5NDkyLDk0OTYsOTUwMCw5NTA4LDk1MTYsOTUyNCw5NTMyLDk1NTIsOTU1Myw5NTU0LDk1NTUsOTU1Niw5NTU3LDk1NTgsOTU1OSw5NTYwLDk1NjEsOTU2Miw5NTYzLDk1NjQsOTU2NSw5NTY2LDk1NjcsOTU2OCw5NTY5LDk1NzAsOTU3MSw5NTcyLDk1NzMsOTU3NCw5NTc1LDk1NzYsOTU3Nyw5NTc4LDk1NzksOTU4MCw5NjAwLDk2MDQsOTYwOCw5NjEyLDk2MTYsOTYxNyw5NjE4LDk2MTksOTYzMiw5NjMzLDk2NDIsOTY0Myw5NjQ0LDk2NTAsOTY1OCw5NjYwLDk2NjgsOTY3NCw5Njc1LDk2NzksOTY4OCw5Njg5LDk3MDIsOTc4Niw5Nzg3LDk3ODgsOTc5Miw5Nzk0LDk4MjQsOTgyNyw5ODI5LDk4MzAsOTgzNCw5ODM1LDk4MzYsNjE0NDEsNjE0NDIsNjE0NDUsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTEsLTFdLEVuPVszNjUsMCwzMzMsMjc4LDMzMyw0NzQsNTU2LDU1Niw4ODksNzIyLDIzOCwzMzMsMzMzLDM4OSw1ODQsMjc4LDMzMywyNzgsMjc4LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1NiwzMzMsMzMzLDU4NCw1ODQsNTg0LDYxMSw5NzUsNzIyLDcyMiw3MjIsNzIyLDY2Nyw2MTEsNzc4LDcyMiwyNzgsNTU2LDcyMiw2MTEsODMzLDcyMiw3NzgsNjY3LDc3OCw3MjIsNjY3LDYxMSw3MjIsNjY3LDk0NCw2NjcsNjY3LDYxMSwzMzMsMjc4LDMzMyw1ODQsNTU2LDMzMyw1NTYsNjExLDU1Niw2MTEsNTU2LDMzMyw2MTEsNjExLDI3OCwyNzgsNTU2LDI3OCw4ODksNjExLDYxMSw2MTEsNjExLDM4OSw1NTYsMzMzLDYxMSw1NTYsNzc4LDU1Niw1NTYsNTAwLDM4OSwyODAsMzg5LDU4NCwzMzMsNTU2LDU1Niw1NTYsNTU2LDI4MCw1NTYsMzMzLDczNywzNzAsNTU2LDU4NCw3MzcsNTUyLDQwMCw1NDksMzMzLDMzMywzMzMsNTc2LDU1NiwyNzgsMzMzLDMzMywzNjUsNTU2LDgzNCw4MzQsODM0LDYxMSw3MjIsNzIyLDcyMiw3MjIsNzIyLDcyMiwxZTMsNzIyLDY2Nyw2NjcsNjY3LDY2NywyNzgsMjc4LDI3OCwyNzgsNzIyLDcyMiw3NzgsNzc4LDc3OCw3NzgsNzc4LDU4NCw3NzgsNzIyLDcyMiw3MjIsNzIyLDY2Nyw2NjcsNjExLDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDg4OSw1NTYsNTU2LDU1Niw1NTYsNTU2LDI3OCwyNzgsMjc4LDI3OCw2MTEsNjExLDYxMSw2MTEsNjExLDYxMSw2MTEsNTQ5LDYxMSw2MTEsNjExLDYxMSw2MTEsNTU2LDYxMSw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNzQwLDcyMiw2MTEsNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2NjcsNTU2LDc3OCw2MTEsNzc4LDYxMSw3NzgsNjExLDc3OCw2MTEsNzIyLDYxMSw3MjIsNjExLDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDI3OCw3ODIsNTU2LDU1NiwyNzgsNzIyLDU1Niw1NTYsNjExLDI3OCw2MTEsMjc4LDYxMSwzOTYsNjExLDQ3OSw2MTEsMjc4LDcyMiw2MTEsNzIyLDYxMSw3MjIsNjExLDcwOCw3MjMsNjExLDc3OCw2MTEsNzc4LDYxMSw3NzgsNjExLDFlMyw5NDQsNzIyLDM4OSw3MjIsMzg5LDcyMiwzODksNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2MTEsMzMzLDYxMSw0NzksNjExLDMzMyw3MjIsNjExLDcyMiw2MTEsNzIyLDYxMSw3MjIsNjExLDcyMiw2MTEsNzIyLDYxMSw5NDQsNzc4LDY2Nyw1NTYsNjY3LDYxMSw1MDAsNjExLDUwMCw2MTEsNTAwLDI3OCw1NTYsNzIyLDU1NiwxZTMsODg5LDc3OCw2MTEsNjY3LDU1Niw2MTEsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsNzIyLDMzMyw4NTQsOTA2LDQ3Myw4NDQsOTMwLDg0NywyNzgsNzIyLDcyMiw2MTAsNjcxLDY2Nyw2MTEsNzIyLDc3OCwyNzgsNzIyLDY2Nyw4MzMsNzIyLDY1Nyw3NzgsNzE4LDY2Nyw1OTAsNjExLDY2Nyw4MjIsNjY3LDgyOSw3ODEsMjc4LDY2Nyw2MjAsNDc5LDYxMSwyNzgsNTkxLDYyMCw2MjEsNTU2LDYxMCw0NzksNDkyLDYxMSw1NTgsMjc4LDU2Niw1NTYsNjAzLDU1Niw0NTAsNjExLDcxMiw2MDUsNTMyLDY2NCw0MDksNTkxLDcwNCw1NzgsNzczLDgzNCwyNzgsNTkxLDYxMSw1OTEsODM0LDY2Nyw2NjcsODg2LDYxNCw3MTksNjY3LDI3OCwyNzgsNTU2LDEwOTQsMTA0Miw4NTQsNjIyLDcxOSw2NzcsNzE5LDcyMiw3MDgsNzIyLDYxNCw3MjIsNjY3LDkyNyw2NDMsNzE5LDcxOSw2MTUsNjg3LDgzMyw3MjIsNzc4LDcxOSw2NjcsNzIyLDYxMSw2NzcsNzgxLDY2Nyw3MjksNzA4LDk3OSw5ODksODU0LDFlMyw3MDgsNzE5LDEwNDIsNzI5LDU1Niw2MTksNjA0LDUzNCw2MTgsNTU2LDczNiw1MTAsNjExLDYxMSw1MDcsNjIyLDc0MCw2MDQsNjExLDYxMSw2MTEsNTU2LDg4OSw1NTYsODg1LDU1Niw2NDYsNTgzLDg4OSw5MzUsNzA3LDg1NCw1OTQsNTUyLDg2NSw1ODksNTU2LDU1Niw2MTEsNDY5LDU2Myw1NTYsMjc4LDI3OCwyNzgsOTY5LDkwNiw2MTEsNTA3LDYxOSw1NTYsNjExLDc3OCw2MTEsNTc1LDQ2Nyw5NDQsNzc4LDk0NCw3NzgsOTQ0LDc3OCw2NjcsNTU2LDMzMywzMzMsNTU2LDFlMywxZTMsNTUyLDI3OCwyNzgsMjc4LDI3OCw1MDAsNTAwLDUwMCw1NTYsNTU2LDM1MCwxZTMsMWUzLDI0MCw0NzksMzMzLDMzMyw2MDQsMzMzLDE2NywzOTYsNTU2LDU1NiwxMTA0LDU1Niw4ODUsNTE2LDExNDYsMWUzLDc2OCw2MDAsODM0LDgzNCw4MzQsODM0LDk5OSw1MDAsMWUzLDUwMCwxZTMsNTAwLDUwMCw0OTQsNjEyLDgyMyw3MTMsNTg0LDU0OSw3MTMsOTc5LDcyMiwyNzQsNTQ5LDU0OSw1ODMsNTQ5LDU0OSw2MDQsNTg0LDYwNCw2MDQsNzA4LDYyNSw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MjksNjA0LDYwNCwzNTQsMzU0LDFlMyw5OTAsOTkwLDk5MCw5OTAsNDk0LDYwNCw2MDQsNjA0LDYwNCwzNTQsMTAyMSwxMDUyLDkxNyw3NTAsNzUwLDUzMSw2NTYsNTk0LDUxMCw1MDAsNzUwLDc1MCw2MTEsNjExLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMjIyLDIyMiwzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzXSxObj1bLTEsLTEsLTEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsNTIsNTMsNTQsNTUsNTYsNTcsNTgsNTksNjAsNjEsNjIsNjMsNjQsNjUsNjYsNjcsNjgsNjksNzAsNzEsNzIsNzMsNzQsNzUsNzYsNzcsNzgsNzksODAsODEsODIsODMsODQsODUsODYsODcsODgsODksOTAsOTEsOTIsOTMsOTQsOTUsOTYsOTcsOTgsOTksMTAwLDEwMSwxMDIsMTAzLDEwNCwxMDUsMTA2LDEwNywxMDgsMTA5LDExMCwxMTEsMTEyLDExMywxMTQsMTE1LDExNiwxMTcsMTE4LDExOSwxMjAsMTIxLDEyMiwxMjMsMTI0LDEyNSwxMjYsMTYxLDE2MiwxNjMsMTY0LDE2NSwxNjYsMTY3LDE2OCwxNjksMTcwLDE3MSwxNzIsMTc0LDE3NSwxNzYsMTc3LDE3OCwxNzksMTgwLDE4MSwxODIsMTgzLDE4NCwxODUsMTg2LDE4NywxODgsMTg5LDE5MCwxOTEsMTkyLDE5MywxOTQsMTk1LDE5NiwxOTcsMTk4LDE5OSwyMDAsMjAxLDIwMiwyMDMsMjA0LDIwNSwyMDYsMjA3LDIwOCwyMDksMjEwLDIxMSwyMTIsMjEzLDIxNCwyMTUsMjE2LDIxNywyMTgsMjE5LDIyMCwyMjEsMjIyLDIyMywyMjQsMjI1LDIyNiwyMjcsMjI4LDIyOSwyMzAsMjMxLDIzMiwyMzMsMjM0LDIzNSwyMzYsMjM3LDIzOCwyMzksMjQwLDI0MSwyNDIsMjQzLDI0NCwyNDUsMjQ2LDI0NywyNDgsMjQ5LDI1MCwyNTEsMjUyLDI1MywyNTQsMjU1LDI1NiwyNTcsMjU4LDI1OSwyNjAsMjYxLDI2MiwyNjMsMjY0LDI2NSwyNjYsMjY3LDI2OCwyNjksMjcwLDI3MSwyNzIsMjczLDI3NCwyNzUsMjc2LDI3NywyNzgsMjc5LDI4MCwyODEsMjgyLDI4MywyODQsMjg1LDI4NiwyODcsMjg4LDI4OSwyOTAsMjkxLDI5MiwyOTMsMjk0LDI5NSwyOTYsMjk3LDI5OCwyOTksMzAwLDMwMSwzMDIsMzAzLDMwNCwzMDUsMzA2LDMwNywzMDgsMzA5LDMxMCwzMTEsMzEyLDMxMywzMTQsMzE1LDMxNiwzMTcsMzE4LDMxOSwzMjAsMzIxLDMyMiwzMjMsMzI0LDMyNSwzMjYsMzI3LDMyOCwzMjksMzMwLDMzMSwzMzIsMzMzLDMzNCwzMzUsMzM2LDMzNywzMzgsMzM5LDM0MCwzNDEsMzQyLDM0MywzNDQsMzQ1LDM0NiwzNDcsMzQ4LDM0OSwzNTAsMzUxLDM1MiwzNTMsMzU0LDM1NSwzNTYsMzU3LDM1OCwzNTksMzYwLDM2MSwzNjIsMzYzLDM2NCwzNjUsMzY2LDM2NywzNjgsMzY5LDM3MCwzNzEsMzcyLDM3MywzNzQsMzc1LDM3NiwzNzcsMzc4LDM3OSwzODAsMzgxLDM4MiwzODMsNDAyLDUwNiw1MDcsNTA4LDUwOSw1MTAsNTExLDUzNiw1MzcsNTM4LDUzOSw3MTAsNzExLDcxMyw3MjgsNzI5LDczMCw3MzEsNzMyLDczMyw5MDAsOTAxLDkwMiw5MDMsOTA0LDkwNSw5MDYsOTA4LDkxMCw5MTEsOTEyLDkxMyw5MTQsOTE1LDkxNiw5MTcsOTE4LDkxOSw5MjAsOTIxLDkyMiw5MjMsOTI0LDkyNSw5MjYsOTI3LDkyOCw5MjksOTMxLDkzMiw5MzMsOTM0LDkzNSw5MzYsOTM3LDkzOCw5MzksOTQwLDk0MSw5NDIsOTQzLDk0NCw5NDUsOTQ2LDk0Nyw5NDgsOTQ5LDk1MCw5NTEsOTUyLDk1Myw5NTQsOTU1LDk1Niw5NTcsOTU4LDk1OSw5NjAsOTYxLDk2Miw5NjMsOTY0LDk2NSw5NjYsOTY3LDk2OCw5NjksOTcwLDk3MSw5NzIsOTczLDk3NCwxMDI0LDEwMjUsMTAyNiwxMDI3LDEwMjgsMTAyOSwxMDMwLDEwMzEsMTAzMiwxMDMzLDEwMzQsMTAzNSwxMDM2LDEwMzcsMTAzOCwxMDM5LDEwNDAsMTA0MSwxMDQyLDEwNDMsMTA0NCwxMDQ1LDEwNDYsMTA0NywxMDQ4LDEwNDksMTA1MCwxMDUxLDEwNTIsMTA1MywxMDU0LDEwNTUsMTA1NiwxMDU3LDEwNTgsMTA1OSwxMDYwLDEwNjEsMTA2MiwxMDYzLDEwNjQsMTA2NSwxMDY2LDEwNjcsMTA2OCwxMDY5LDEwNzAsMTA3MSwxMDcyLDEwNzMsMTA3NCwxMDc1LDEwNzYsMTA3NywxMDc4LDEwNzksMTA4MCwxMDgxLDEwODIsMTA4MywxMDg0LDEwODUsMTA4NiwxMDg3LDEwODgsMTA4OSwxMDkwLDEwOTEsMTA5MiwxMDkzLDEwOTQsMTA5NSwxMDk2LDEwOTcsMTA5OCwxMDk5LDExMDAsMTEwMSwxMTAyLDExMDMsMTEwNCwxMTA1LDExMDYsMTEwNywxMTA4LDExMDksMTExMCwxMTExLDExMTIsMTExMywxMTE0LDExMTUsMTExNiwxMTE3LDExMTgsMTExOSwxMTM4LDExMzksMTE2OCwxMTY5LDc4MDgsNzgwOSw3ODEwLDc4MTEsNzgxMiw3ODEzLDc5MjIsNzkyMyw4MjA4LDgyMDksODIxMSw4MjEyLDgyMTMsODIxNSw4MjE2LDgyMTcsODIxOCw4MjE5LDgyMjAsODIyMSw4MjIyLDgyMjQsODIyNSw4MjI2LDgyMzAsODI0MCw4MjQyLDgyNDMsODI0OSw4MjUwLDgyNTIsODI1NCw4MjYwLDgzMTksODM1NSw4MzU2LDgzNTksODM2NCw4NDUzLDg0NjcsODQ3MCw4NDgyLDg0ODYsODQ5NCw4NTM5LDg1NDAsODU0MSw4NTQyLDg1OTIsODU5Myw4NTk0LDg1OTUsODU5Niw4NTk3LDg2MTYsODcwNiw4NzEwLDg3MTksODcyMSw4NzIyLDg3MzAsODczNCw4NzM1LDg3NDUsODc0Nyw4Nzc2LDg4MDAsODgwMSw4ODA0LDg4MDUsODk2Miw4OTc2LDg5OTIsODk5Myw5NDcyLDk0NzQsOTQ4NCw5NDg4LDk0OTIsOTQ5Niw5NTAwLDk1MDgsOTUxNiw5NTI0LDk1MzIsOTU1Miw5NTUzLDk1NTQsOTU1NSw5NTU2LDk1NTcsOTU1OCw5NTU5LDk1NjAsOTU2MSw5NTYyLDk1NjMsOTU2NCw5NTY1LDk1NjYsOTU2Nyw5NTY4LDk1NjksOTU3MCw5NTcxLDk1NzIsOTU3Myw5NTc0LDk1NzUsOTU3Niw5NTc3LDk1NzgsOTU3OSw5NTgwLDk2MDAsOTYwNCw5NjA4LDk2MTIsOTYxNiw5NjE3LDk2MTgsOTYxOSw5NjMyLDk2MzMsOTY0Miw5NjQzLDk2NDQsOTY1MCw5NjU4LDk2NjAsOTY2OCw5Njc0LDk2NzUsOTY3OSw5Njg4LDk2ODksOTcwMiw5Nzg2LDk3ODcsOTc4OCw5NzkyLDk3OTQsOTgyNCw5ODI3LDk4MjksOTgzMCw5ODM0LDk4MzUsOTgzNiw2MTQ0MSw2MTQ0Miw2MTQ0NSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMSwtMV0sUG49WzM2NSwwLDMzMywyNzgsMjc4LDM1NSw1NTYsNTU2LDg4OSw2NjcsMTkxLDMzMywzMzMsMzg5LDU4NCwyNzgsMzMzLDI3OCwyNzgsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDI3OCwyNzgsNTg0LDU4NCw1ODQsNTU2LDEwMTUsNjY3LDY2Nyw3MjIsNzIyLDY2Nyw2MTEsNzc4LDcyMiwyNzgsNTAwLDY2Nyw1NTYsODMzLDcyMiw3NzgsNjY3LDc3OCw3MjIsNjY3LDYxMSw3MjIsNjY3LDk0NCw2NjcsNjY3LDYxMSwyNzgsMjc4LDI3OCw0NjksNTU2LDMzMyw1NTYsNTU2LDUwMCw1NTYsNTU2LDI3OCw1NTYsNTU2LDIyMiwyMjIsNTAwLDIyMiw4MzMsNTU2LDU1Niw1NTYsNTU2LDMzMyw1MDAsMjc4LDU1Niw1MDAsNzIyLDUwMCw1MDAsNTAwLDMzNCwyNjAsMzM0LDU4NCwzMzMsNTU2LDU1Niw1NTYsNTU2LDI2MCw1NTYsMzMzLDczNywzNzAsNTU2LDU4NCw3MzcsNTUyLDQwMCw1NDksMzMzLDMzMywzMzMsNTc2LDUzNywyNzgsMzMzLDMzMywzNjUsNTU2LDgzNCw4MzQsODM0LDYxMSw2NjcsNjY3LDY2Nyw2NjcsNjY3LDY2NywxZTMsNzIyLDY2Nyw2NjcsNjY3LDY2NywyNzgsMjc4LDI3OCwyNzgsNzIyLDcyMiw3NzgsNzc4LDc3OCw3NzgsNzc4LDU4NCw3NzgsNzIyLDcyMiw3MjIsNzIyLDY2Nyw2NjcsNjExLDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDg4OSw1MDAsNTU2LDU1Niw1NTYsNTU2LDI3OCwyNzgsMjc4LDI3OCw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTQ5LDYxMSw1NTYsNTU2LDU1Niw1NTYsNTAwLDU1Niw1MDAsNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNzIyLDUwMCw3MjIsNTAwLDcyMiw1MDAsNzIyLDUwMCw3MjIsNjI1LDcyMiw1NTYsNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2NjcsNTU2LDc3OCw1NTYsNzc4LDU1Niw3NzgsNTU2LDc3OCw1NTYsNzIyLDU1Niw3MjIsNTU2LDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDI3OCwyMjIsMjc4LDI3OCw3MzMsNDQ0LDUwMCwyMjIsNjY3LDUwMCw1MDAsNTU2LDIyMiw1NTYsMjIyLDU1NiwyODEsNTU2LDQwMCw1NTYsMjIyLDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDYxNSw3MjMsNTU2LDc3OCw1NTYsNzc4LDU1Niw3NzgsNTU2LDFlMyw5NDQsNzIyLDMzMyw3MjIsMzMzLDcyMiwzMzMsNjY3LDUwMCw2NjcsNTAwLDY2Nyw1MDAsNjY3LDUwMCw2MTEsMjc4LDYxMSwzNTQsNjExLDI3OCw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw5NDQsNzIyLDY2Nyw1MDAsNjY3LDYxMSw1MDAsNjExLDUwMCw2MTEsNTAwLDIyMiw1NTYsNjY3LDU1NiwxZTMsODg5LDc3OCw2MTEsNjY3LDUwMCw2MTEsMjc4LDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsNjY3LDI3OCw3ODksODQ2LDM4OSw3OTQsODY1LDc3NSwyMjIsNjY3LDY2Nyw1NzAsNjcxLDY2Nyw2MTEsNzIyLDc3OCwyNzgsNjY3LDY2Nyw4MzMsNzIyLDY0OCw3NzgsNzI1LDY2Nyw2MDAsNjExLDY2Nyw4MzcsNjY3LDgzMSw3NjEsMjc4LDY2Nyw1NzAsNDM5LDU1NSwyMjIsNTUwLDU3MCw1NzEsNTAwLDU1Niw0MzksNDYzLDU1NSw1NDIsMjIyLDUwMCw0OTIsNTQ4LDUwMCw0NDcsNTU2LDY3MCw1NzMsNDg2LDYwMywzNzQsNTUwLDY1Miw1NDYsNzI4LDc3OSwyMjIsNTUwLDU1Niw1NTAsNzc5LDY2Nyw2NjcsODQzLDU0NCw3MDgsNjY3LDI3OCwyNzgsNTAwLDEwNjYsOTgyLDg0NCw1ODksNzE1LDYzOSw3MjQsNjY3LDY1MSw2NjcsNTQ0LDcwNCw2NjcsOTE3LDYxNCw3MTUsNzE1LDU4OSw2ODYsODMzLDcyMiw3NzgsNzI1LDY2Nyw3MjIsNjExLDYzOSw3OTUsNjY3LDcyNyw2NzMsOTIwLDkyMyw4MDUsODg2LDY1MSw2OTQsMTAyMiw2ODIsNTU2LDU2Miw1MjIsNDkzLDU1Myw1NTYsNjg4LDQ2NSw1NTYsNTU2LDQ3Miw1NjQsNjg2LDU1MCw1NTYsNTU2LDU1Niw1MDAsODMzLDUwMCw4MzUsNTAwLDU3Miw1MTgsODMwLDg1MSw2MjEsNzM2LDUyNiw0OTIsNzUyLDUzNCw1NTYsNTU2LDU1NiwzNzgsNDk2LDUwMCwyMjIsMjIyLDIyMiw5MTAsODI4LDU1Niw0NzIsNTY1LDUwMCw1NTYsNzc4LDU1Niw0OTIsMzM5LDk0NCw3MjIsOTQ0LDcyMiw5NDQsNzIyLDY2Nyw1MDAsMzMzLDMzMyw1NTYsMWUzLDFlMyw1NTIsMjIyLDIyMiwyMjIsMjIyLDMzMywzMzMsMzMzLDU1Niw1NTYsMzUwLDFlMywxZTMsMTg4LDM1NCwzMzMsMzMzLDUwMCwzMzMsMTY3LDM2NSw1NTYsNTU2LDEwOTQsNTU2LDg4NSwzMjMsMTA4MywxZTMsNzY4LDYwMCw4MzQsODM0LDgzNCw4MzQsMWUzLDUwMCw5OTgsNTAwLDFlMyw1MDAsNTAwLDQ5NCw2MTIsODIzLDcxMyw1ODQsNTQ5LDcxMyw5NzksNzE5LDI3NCw1NDksNTQ5LDU4NCw1NDksNTQ5LDYwNCw1ODQsNjA0LDYwNCw3MDgsNjI1LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcyOSw2MDQsNjA0LDM1NCwzNTQsMWUzLDk5MCw5OTAsOTkwLDk5MCw0OTQsNjA0LDYwNCw2MDQsNjA0LDM1NCwxMDIxLDEwNTIsOTE3LDc1MCw3NTAsNTMxLDY1Niw1OTQsNTEwLDUwMCw3NTAsNzUwLDUwMCw1MDAsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywyMjIsMjIyLDI5NCwyOTQsMzI0LDMyNCwzMTYsMzI4LDM5OCwyODVdLF9uPVstMSwtMSwtMSwzMiwzMywzNCwzNSwzNiwzNywzOCwzOSw0MCw0MSw0Miw0Myw0NCw0NSw0Niw0Nyw0OCw0OSw1MCw1MSw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSw2Miw2Myw2NCw2NSw2Niw2Nyw2OCw2OSw3MCw3MSw3Miw3Myw3NCw3NSw3Niw3Nyw3OCw3OSw4MCw4MSw4Miw4Myw4NCw4NSw4Niw4Nyw4OCw4OSw5MCw5MSw5Miw5Myw5NCw5NSw5Niw5Nyw5OCw5OSwxMDAsMTAxLDEwMiwxMDMsMTA0LDEwNSwxMDYsMTA3LDEwOCwxMDksMTEwLDExMSwxMTIsMTEzLDExNCwxMTUsMTE2LDExNywxMTgsMTE5LDEyMCwxMjEsMTIyLDEyMywxMjQsMTI1LDEyNiwxNjEsMTYyLDE2MywxNjQsMTY1LDE2NiwxNjcsMTY4LDE2OSwxNzAsMTcxLDE3MiwxNzQsMTc1LDE3NiwxNzcsMTc4LDE3OSwxODAsMTgxLDE4MiwxODMsMTg0LDE4NSwxODYsMTg3LDE4OCwxODksMTkwLDE5MSwxOTIsMTkzLDE5NCwxOTUsMTk2LDE5NywxOTgsMTk5LDIwMCwyMDEsMjAyLDIwMywyMDQsMjA1LDIwNiwyMDcsMjA4LDIwOSwyMTAsMjExLDIxMiwyMTMsMjE0LDIxNSwyMTYsMjE3LDIxOCwyMTksMjIwLDIyMSwyMjIsMjIzLDIyNCwyMjUsMjI2LDIyNywyMjgsMjI5LDIzMCwyMzEsMjMyLDIzMywyMzQsMjM1LDIzNiwyMzcsMjM4LDIzOSwyNDAsMjQxLDI0MiwyNDMsMjQ0LDI0NSwyNDYsMjQ3LDI0OCwyNDksMjUwLDI1MSwyNTIsMjUzLDI1NCwyNTUsMjU2LDI1NywyNTgsMjU5LDI2MCwyNjEsMjYyLDI2MywyNjQsMjY1LDI2NiwyNjcsMjY4LDI2OSwyNzAsMjcxLDI3MiwyNzMsMjc0LDI3NSwyNzYsMjc3LDI3OCwyNzksMjgwLDI4MSwyODIsMjgzLDI4NCwyODUsMjg2LDI4NywyODgsMjg5LDI5MCwyOTEsMjkyLDI5MywyOTQsMjk1LDI5NiwyOTcsMjk4LDI5OSwzMDAsMzAxLDMwMiwzMDMsMzA0LDMwNSwzMDYsMzA3LDMwOCwzMDksMzEwLDMxMSwzMTIsMzEzLDMxNCwzMTUsMzE2LDMxNywzMTgsMzE5LDMyMCwzMjEsMzIyLDMyMywzMjQsMzI1LDMyNiwzMjcsMzI4LDMyOSwzMzAsMzMxLDMzMiwzMzMsMzM0LDMzNSwzMzYsMzM3LDMzOCwzMzksMzQwLDM0MSwzNDIsMzQzLDM0NCwzNDUsMzQ2LDM0NywzNDgsMzQ5LDM1MCwzNTEsMzUyLDM1MywzNTQsMzU1LDM1NiwzNTcsMzU4LDM1OSwzNjAsMzYxLDM2MiwzNjMsMzY0LDM2NSwzNjYsMzY3LDM2OCwzNjksMzcwLDM3MSwzNzIsMzczLDM3NCwzNzUsMzc2LDM3NywzNzgsMzc5LDM4MCwzODEsMzgyLDM4Myw0MDIsNTA2LDUwNyw1MDgsNTA5LDUxMCw1MTEsNTM2LDUzNyw1MzgsNTM5LDcxMCw3MTEsNzEzLDcyOCw3MjksNzMwLDczMSw3MzIsNzMzLDkwMCw5MDEsOTAyLDkwMyw5MDQsOTA1LDkwNiw5MDgsOTEwLDkxMSw5MTIsOTEzLDkxNCw5MTUsOTE2LDkxNyw5MTgsOTE5LDkyMCw5MjEsOTIyLDkyMyw5MjQsOTI1LDkyNiw5MjcsOTI4LDkyOSw5MzEsOTMyLDkzMyw5MzQsOTM1LDkzNiw5MzcsOTM4LDkzOSw5NDAsOTQxLDk0Miw5NDMsOTQ0LDk0NSw5NDYsOTQ3LDk0OCw5NDksOTUwLDk1MSw5NTIsOTUzLDk1NCw5NTUsOTU2LDk1Nyw5NTgsOTU5LDk2MCw5NjEsOTYyLDk2Myw5NjQsOTY1LDk2Niw5NjcsOTY4LDk2OSw5NzAsOTcxLDk3Miw5NzMsOTc0LDEwMjQsMTAyNSwxMDI2LDEwMjcsMTAyOCwxMDI5LDEwMzAsMTAzMSwxMDMyLDEwMzMsMTAzNCwxMDM1LDEwMzYsMTAzNywxMDM4LDEwMzksMTA0MCwxMDQxLDEwNDIsMTA0MywxMDQ0LDEwNDUsMTA0NiwxMDQ3LDEwNDgsMTA0OSwxMDUwLDEwNTEsMTA1MiwxMDUzLDEwNTQsMTA1NSwxMDU2LDEwNTcsMTA1OCwxMDU5LDEwNjAsMTA2MSwxMDYyLDEwNjMsMTA2NCwxMDY1LDEwNjYsMTA2NywxMDY4LDEwNjksMTA3MCwxMDcxLDEwNzIsMTA3MywxMDc0LDEwNzUsMTA3NiwxMDc3LDEwNzgsMTA3OSwxMDgwLDEwODEsMTA4MiwxMDgzLDEwODQsMTA4NSwxMDg2LDEwODcsMTA4OCwxMDg5LDEwOTAsMTA5MSwxMDkyLDEwOTMsMTA5NCwxMDk1LDEwOTYsMTA5NywxMDk4LDEwOTksMTEwMCwxMTAxLDExMDIsMTEwMywxMTA0LDExMDUsMTEwNiwxMTA3LDExMDgsMTEwOSwxMTEwLDExMTEsMTExMiwxMTEzLDExMTQsMTExNSwxMTE2LDExMTcsMTExOCwxMTE5LDExMzgsMTEzOSwxMTY4LDExNjksNzgwOCw3ODA5LDc4MTAsNzgxMSw3ODEyLDc4MTMsNzkyMiw3OTIzLDgyMDgsODIwOSw4MjExLDgyMTIsODIxMyw4MjE1LDgyMTYsODIxNyw4MjE4LDgyMTksODIyMCw4MjIxLDgyMjIsODIyNCw4MjI1LDgyMjYsODIzMCw4MjQwLDgyNDIsODI0Myw4MjQ5LDgyNTAsODI1Miw4MjU0LDgyNjAsODMxOSw4MzU1LDgzNTYsODM1OSw4MzY0LDg0NTMsODQ2Nyw4NDcwLDg0ODIsODQ4Niw4NDk0LDg1MzksODU0MCw4NTQxLDg1NDIsODU5Miw4NTkzLDg1OTQsODU5NSw4NTk2LDg1OTcsODYxNiw4NzA2LDg3MTAsODcxOSw4NzIxLDg3MjIsODczMCw4NzM0LDg3MzUsODc0NSw4NzQ3LDg3NzYsODgwMCw4ODAxLDg4MDQsODgwNSw4OTYyLDg5NzYsODk5Miw4OTkzLDk0NzIsOTQ3NCw5NDg0LDk0ODgsOTQ5Miw5NDk2LDk1MDAsOTUwOCw5NTE2LDk1MjQsOTUzMiw5NTUyLDk1NTMsOTU1NCw5NTU1LDk1NTYsOTU1Nyw5NTU4LDk1NTksOTU2MCw5NTYxLDk1NjIsOTU2Myw5NTY0LDk1NjUsOTU2Niw5NTY3LDk1NjgsOTU2OSw5NTcwLDk1NzEsOTU3Miw5NTczLDk1NzQsOTU3NSw5NTc2LDk1NzcsOTU3OCw5NTc5LDk1ODAsOTYwMCw5NjA0LDk2MDgsOTYxMiw5NjE2LDk2MTcsOTYxOCw5NjE5LDk2MzIsOTYzMyw5NjQyLDk2NDMsOTY0NCw5NjUwLDk2NTgsOTY2MCw5NjY4LDk2NzQsOTY3NSw5Njc5LDk2ODgsOTY4OSw5NzAyLDk3ODYsOTc4Nyw5Nzg4LDk3OTIsOTc5NCw5ODI0LDk4MjcsOTgyOSw5ODMwLDk4MzQsOTgzNSw5ODM2LDYxNDQxLDYxNDQyLDYxNDQ1LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xXSxMbj1bMzY1LDAsMzMzLDI3OCwyNzgsMzU1LDU1Niw1NTYsODg5LDY2NywxOTEsMzMzLDMzMywzODksNTg0LDI3OCwzMzMsMjc4LDI3OCw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsMjc4LDI3OCw1ODQsNTg0LDU4NCw1NTYsMTAxNSw2NjcsNjY3LDcyMiw3MjIsNjY3LDYxMSw3NzgsNzIyLDI3OCw1MDAsNjY3LDU1Niw4MzMsNzIyLDc3OCw2NjcsNzc4LDcyMiw2NjcsNjExLDcyMiw2NjcsOTQ0LDY2Nyw2NjcsNjExLDI3OCwyNzgsMjc4LDQ2OSw1NTYsMzMzLDU1Niw1NTYsNTAwLDU1Niw1NTYsMjc4LDU1Niw1NTYsMjIyLDIyMiw1MDAsMjIyLDgzMyw1NTYsNTU2LDU1Niw1NTYsMzMzLDUwMCwyNzgsNTU2LDUwMCw3MjIsNTAwLDUwMCw1MDAsMzM0LDI2MCwzMzQsNTg0LDMzMyw1NTYsNTU2LDU1Niw1NTYsMjYwLDU1NiwzMzMsNzM3LDM3MCw1NTYsNTg0LDczNyw1NTIsNDAwLDU0OSwzMzMsMzMzLDMzMyw1NzYsNTM3LDI3OCwzMzMsMzMzLDM2NSw1NTYsODM0LDgzNCw4MzQsNjExLDY2Nyw2NjcsNjY3LDY2Nyw2NjcsNjY3LDFlMyw3MjIsNjY3LDY2Nyw2NjcsNjY3LDI3OCwyNzgsMjc4LDI3OCw3MjIsNzIyLDc3OCw3NzgsNzc4LDc3OCw3NzgsNTg0LDc3OCw3MjIsNzIyLDcyMiw3MjIsNjY3LDY2Nyw2MTEsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NTYsODg5LDUwMCw1NTYsNTU2LDU1Niw1NTYsMjc4LDI3OCwyNzgsMjc4LDU1Niw1NTYsNTU2LDU1Niw1NTYsNTU2LDU1Niw1NDksNjExLDU1Niw1NTYsNTU2LDU1Niw1MDAsNTU2LDUwMCw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw3MjIsNTAwLDcyMiw1MDAsNzIyLDUwMCw3MjIsNTAwLDcyMiw2MTUsNzIyLDU1Niw2NjcsNTU2LDY2Nyw1NTYsNjY3LDU1Niw2NjcsNTU2LDY2Nyw1NTYsNzc4LDU1Niw3NzgsNTU2LDc3OCw1NTYsNzc4LDU1Niw3MjIsNTU2LDcyMiw1NTYsMjc4LDI3OCwyNzgsMjc4LDI3OCwyNzgsMjc4LDIyMiwyNzgsMjc4LDczNSw0NDQsNTAwLDIyMiw2NjcsNTAwLDUwMCw1NTYsMjIyLDU1NiwyMjIsNTU2LDI5Miw1NTYsMzM0LDU1NiwyMjIsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNjA0LDcyMyw1NTYsNzc4LDU1Niw3NzgsNTU2LDc3OCw1NTYsMWUzLDk0NCw3MjIsMzMzLDcyMiwzMzMsNzIyLDMzMyw2NjcsNTAwLDY2Nyw1MDAsNjY3LDUwMCw2NjcsNTAwLDYxMSwyNzgsNjExLDM3NSw2MTEsMjc4LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDcyMiw1NTYsNzIyLDU1Niw3MjIsNTU2LDk0NCw3MjIsNjY3LDUwMCw2NjcsNjExLDUwMCw2MTEsNTAwLDYxMSw1MDAsMjIyLDU1Niw2NjcsNTU2LDFlMyw4ODksNzc4LDYxMSw2NjcsNTAwLDYxMSwyNzgsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMyw2NjcsMjc4LDc4NCw4MzgsMzg0LDc3NCw4NTUsNzUyLDIyMiw2NjcsNjY3LDU1MSw2NjgsNjY3LDYxMSw3MjIsNzc4LDI3OCw2NjcsNjY4LDgzMyw3MjIsNjUwLDc3OCw3MjIsNjY3LDYxOCw2MTEsNjY3LDc5OCw2NjcsODM1LDc0OCwyNzgsNjY3LDU3OCw0NDYsNTU2LDIyMiw1NDcsNTc4LDU3NSw1MDAsNTU3LDQ0Niw0NDEsNTU2LDU1NiwyMjIsNTAwLDUwMCw1NzYsNTAwLDQ0OCw1NTYsNjkwLDU2OSw0ODIsNjE3LDM5NSw1NDcsNjQ4LDUyNSw3MTMsNzgxLDIyMiw1NDcsNTU2LDU0Nyw3ODEsNjY3LDY2Nyw4NjUsNTQyLDcxOSw2NjcsMjc4LDI3OCw1MDAsMTA1NywxMDEwLDg1NCw1ODMsNzIyLDYzNSw3MTksNjY3LDY1Niw2NjcsNTQyLDY3Nyw2NjcsOTIzLDYwNCw3MTksNzE5LDU4Myw2NTYsODMzLDcyMiw3NzgsNzE5LDY2Nyw3MjIsNjExLDYzNSw3NjAsNjY3LDc0MCw2NjcsOTE3LDkzOCw3OTIsODg1LDY1Niw3MTksMTAxMCw3MjIsNTU2LDU3Myw1MzEsMzY1LDU4Myw1NTYsNjY5LDQ1OCw1NTksNTU5LDQzOCw1ODMsNjg4LDU1Miw1NTYsNTQyLDU1Niw1MDAsNDU4LDUwMCw4MjMsNTAwLDU3Myw1MjEsODAyLDgyMyw2MjUsNzE5LDUyMSw1MTAsNzUwLDU0Miw1NTYsNTU2LDU1NiwzNjUsNTEwLDUwMCwyMjIsMjc4LDIyMiw5MDYsODEyLDU1Niw0MzgsNTU5LDUwMCw1NTIsNzc4LDU1Niw0ODksNDExLDk0NCw3MjIsOTQ0LDcyMiw5NDQsNzIyLDY2Nyw1MDAsMzMzLDMzMyw1NTYsMWUzLDFlMyw1NTIsMjIyLDIyMiwyMjIsMjIyLDMzMywzMzMsMzMzLDU1Niw1NTYsMzUwLDFlMywxZTMsMTg4LDM1NCwzMzMsMzMzLDUwMCwzMzMsMTY3LDM2NSw1NTYsNTU2LDEwOTQsNTU2LDg4NSwzMjMsMTA3MywxZTMsNzY4LDYwMCw4MzQsODM0LDgzNCw4MzQsMWUzLDUwMCwxZTMsNTAwLDFlMyw1MDAsNTAwLDQ5NCw2MTIsODIzLDcxMyw1ODQsNTQ5LDcxMyw5NzksNzE5LDI3NCw1NDksNTQ5LDU4Myw1NDksNTQ5LDYwNCw1ODQsNjA0LDYwNCw3MDgsNjI1LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcwOCw3MDgsNzA4LDcyOSw2MDQsNjA0LDM1NCwzNTQsMWUzLDk5MCw5OTAsOTkwLDk5MCw0OTQsNjA0LDYwNCw2MDQsNjA0LDM1NCwxMDIxLDEwNTIsOTE3LDc1MCw3NTAsNTMxLDY1Niw1OTQsNTEwLDUwMCw3NTAsNzUwLDUwMCw1MDAsMzMzLDMzMywzMzMsMzMzLDMzMywzMzMsMzMzLDMzMywyMjIsMjIyLDI5NCwyOTQsMzI0LDMyNCwzMTYsMzI4LDM5OCwyODVdLGpuPVstMSwtMSwtMSwzMiwzMywzNCwzNSwzNiwzNywzOCwzOSw0MCw0MSw0Miw0Myw0NCw0NSw0Niw0Nyw0OCw0OSw1MCw1MSw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSw2Miw2Myw2NCw2NSw2Niw2Nyw2OCw2OSw3MCw3MSw3Miw3Myw3NCw3NSw3Niw3Nyw3OCw3OSw4MCw4MSw4Miw4Myw4NCw4NSw4Niw4Nyw4OCw4OSw5MCw5MSw5Miw5Myw5NCw5NSw5Niw5Nyw5OCw5OSwxMDAsMTAxLDEwMiwxMDMsMTA0LDEwNSwxMDYsMTA3LDEwOCwxMDksMTEwLDExMSwxMTIsMTEzLDExNCwxMTUsMTE2LDExNywxMTgsMTE5LDEyMCwxMjEsMTIyLDEyMywxMjQsMTI1LDEyNiwxNjEsMTYyLDE2MywxNjQsMTY1LDE2NiwxNjcsMTY4LDE2OSwxNzAsMTcxLDE3MiwxNzQsMTc1LDE3NiwxNzcsMTc4LDE3OSwxODAsMTgxLDE4MiwxODMsMTg0LDE4NSwxODYsMTg3LDE4OCwxODksMTkwLDE5MSwxOTIsMTkzLDE5NCwxOTUsMTk2LDE5NywxOTgsMTk5LDIwMCwyMDEsMjAyLDIwMywyMDQsMjA1LDIwNiwyMDcsMjA4LDIwOSwyMTAsMjExLDIxMiwyMTMsMjE0LDIxNSwyMTYsMjE3LDIxOCwyMTksMjIwLDIyMSwyMjIsMjIzLDIyNCwyMjUsMjI2LDIyNywyMjgsMjI5LDIzMCwyMzEsMjMyLDIzMywyMzQsMjM1LDIzNiwyMzcsMjM4LDIzOSwyNDAsMjQxLDI0MiwyNDMsMjQ0LDI0NSwyNDYsMjQ3LDI0OCwyNDksMjUwLDI1MSwyNTIsMjUzLDI1NCwyNTUsMjU2LDI1NywyNTgsMjU5LDI2MCwyNjEsMjYyLDI2MywyNjQsMjY1LDI2NiwyNjcsMjY4LDI2OSwyNzAsMjcxLDI3MiwyNzMsMjc0LDI3NSwyNzYsMjc3LDI3OCwyNzksMjgwLDI4MSwyODIsMjgzLDI4NCwyODUsMjg2LDI4NywyODgsMjg5LDI5MCwyOTEsMjkyLDI5MywyOTQsMjk1LDI5NiwyOTcsMjk4LDI5OSwzMDAsMzAxLDMwMiwzMDMsMzA0LDMwNSwzMDYsMzA3LDMwOCwzMDksMzEwLDMxMSwzMTIsMzEzLDMxNCwzMTUsMzE2LDMxNywzMTgsMzE5LDMyMCwzMjEsMzIyLDMyMywzMjQsMzI1LDMyNiwzMjcsMzI4LDMyOSwzMzAsMzMxLDMzMiwzMzMsMzM0LDMzNSwzMzYsMzM3LDMzOCwzMzksMzQwLDM0MSwzNDIsMzQzLDM0NCwzNDUsMzQ2LDM0NywzNDgsMzQ5LDM1MCwzNTEsMzUyLDM1MywzNTQsMzU1LDM1NiwzNTcsMzU4LDM1OSwzNjAsMzYxLDM2MiwzNjMsMzY0LDM2NSwzNjYsMzY3LDM2OCwzNjksMzcwLDM3MSwzNzIsMzczLDM3NCwzNzUsMzc2LDM3NywzNzgsMzc5LDM4MCwzODEsMzgyLDM4Myw0MDIsNTA2LDUwNyw1MDgsNTA5LDUxMCw1MTEsNTM2LDUzNyw1MzgsNTM5LDcxMCw3MTEsNzEzLDcyOCw3MjksNzMwLDczMSw3MzIsNzMzLDkwMCw5MDEsOTAyLDkwMyw5MDQsOTA1LDkwNiw5MDgsOTEwLDkxMSw5MTIsOTEzLDkxNCw5MTUsOTE2LDkxNyw5MTgsOTE5LDkyMCw5MjEsOTIyLDkyMyw5MjQsOTI1LDkyNiw5MjcsOTI4LDkyOSw5MzEsOTMyLDkzMyw5MzQsOTM1LDkzNiw5MzcsOTM4LDkzOSw5NDAsOTQxLDk0Miw5NDMsOTQ0LDk0NSw5NDYsOTQ3LDk0OCw5NDksOTUwLDk1MSw5NTIsOTUzLDk1NCw5NTUsOTU2LDk1Nyw5NTgsOTU5LDk2MCw5NjEsOTYyLDk2Myw5NjQsOTY1LDk2Niw5NjcsOTY4LDk2OSw5NzAsOTcxLDk3Miw5NzMsOTc0LDEwMjQsMTAyNSwxMDI2LDEwMjcsMTAyOCwxMDI5LDEwMzAsMTAzMSwxMDMyLDEwMzMsMTAzNCwxMDM1LDEwMzYsMTAzNywxMDM4LDEwMzksMTA0MCwxMDQxLDEwNDIsMTA0MywxMDQ0LDEwNDUsMTA0NiwxMDQ3LDEwNDgsMTA0OSwxMDUwLDEwNTEsMTA1MiwxMDUzLDEwNTQsMTA1NSwxMDU2LDEwNTcsMTA1OCwxMDU5LDEwNjAsMTA2MSwxMDYyLDEwNjMsMTA2NCwxMDY1LDEwNjYsMTA2NywxMDY4LDEwNjksMTA3MCwxMDcxLDEwNzIsMTA3MywxMDc0LDEwNzUsMTA3NiwxMDc3LDEwNzgsMTA3OSwxMDgwLDEwODEsMTA4MiwxMDgzLDEwODQsMTA4NSwxMDg2LDEwODcsMTA4OCwxMDg5LDEwOTAsMTA5MSwxMDkyLDEwOTMsMTA5NCwxMDk1LDEwOTYsMTA5NywxMDk4LDEwOTksMTEwMCwxMTAxLDExMDIsMTEwMywxMTA0LDExMDUsMTEwNiwxMTA3LDExMDgsMTEwOSwxMTEwLDExMTEsMTExMiwxMTEzLDExMTQsMTExNSwxMTE2LDExMTcsMTExOCwxMTE5LDExMzgsMTEzOSwxMTY4LDExNjksNzgwOCw3ODA5LDc4MTAsNzgxMSw3ODEyLDc4MTMsNzkyMiw3OTIzLDgyMDgsODIwOSw4MjExLDgyMTIsODIxMyw4MjE1LDgyMTYsODIxNyw4MjE4LDgyMTksODIyMCw4MjIxLDgyMjIsODIyNCw4MjI1LDgyMjYsODIzMCw4MjQwLDgyNDIsODI0Myw4MjQ5LDgyNTAsODI1Miw4MjU0LDgyNjAsODMxOSw4MzU1LDgzNTYsODM1OSw4MzY0LDg0NTMsODQ2Nyw4NDcwLDg0ODIsODQ4Niw4NDk0LDg1MzksODU0MCw4NTQxLDg1NDIsODU5Miw4NTkzLDg1OTQsODU5NSw4NTk2LDg1OTcsODYxNiw4NzA2LDg3MTAsODcxOSw4NzIxLDg3MjIsODczMCw4NzM0LDg3MzUsODc0NSw4NzQ3LDg3NzYsODgwMCw4ODAxLDg4MDQsODgwNSw4OTYyLDg5NzYsODk5Miw4OTkzLDk0NzIsOTQ3NCw5NDg0LDk0ODgsOTQ5Miw5NDk2LDk1MDAsOTUwOCw5NTE2LDk1MjQsOTUzMiw5NTUyLDk1NTMsOTU1NCw5NTU1LDk1NTYsOTU1Nyw5NTU4LDk1NTksOTU2MCw5NTYxLDk1NjIsOTU2Myw5NTY0LDk1NjUsOTU2Niw5NTY3LDk1NjgsOTU2OSw5NTcwLDk1NzEsOTU3Miw5NTczLDk1NzQsOTU3NSw5NTc2LDk1NzcsOTU3OCw5NTc5LDk1ODAsOTYwMCw5NjA0LDk2MDgsOTYxMiw5NjE2LDk2MTcsOTYxOCw5NjE5LDk2MzIsOTYzMyw5NjQyLDk2NDMsOTY0NCw5NjUwLDk2NTgsOTY2MCw5NjY4LDk2NzQsOTY3NSw5Njc5LDk2ODgsOTY4OSw5NzAyLDk3ODYsOTc4Nyw5Nzg4LDk3OTIsOTc5NCw5ODI0LDk4MjcsOTgyOSw5ODMwLDk4MzQsOTgzNSw5ODM2LDYxNDQxLDYxNDQyLDYxNDQ1LC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xLC0xXSxVbj1bMS4zNjg5OCwxLDEsLjcyNzA2LC44MDQ3OSwuODM3MzQsLjk4ODk0LC45OTc5MywuOTg5NywuOTM4ODQsLjg2MjA5LC45NDI5MiwuOTQyOTIsMS4xNjY2MSwxLjAyMDU4LC45MzU4MiwuOTY2OTQsLjkzNTgyLDEuMTkxMzcsLjk5NzkzLC45OTc5MywuOTk3OTMsLjk5NzkzLC45OTc5MywuOTk3OTMsLjk5NzkzLC45OTc5MywuOTk3OTMsLjk5NzkzLC43ODA3NiwuNzgwNzYsMS4wMjA1OCwxLjAyMDU4LDEuMDIwNTgsLjcyODUxLC43ODk2NiwuOTA4MzgsLjgzNjM3LC44MjM5MSwuOTYzNzYsLjgwMDYxLC44NjI3NSwuODc2OCwuOTU0MDcsMS4wMjU4LC43MzkwMSwuODUwMjIsLjgzNjU1LDEuMDE1NiwuOTU1NDYsLjkyMTc5LC44NzEwNywuOTIxNzksLjgyMTE0LC44MDk2LC44OTcxMywuOTQ0MzgsLjk1MzUzLC45NDA4MywuOTE5MDUsLjkwNDA2LC45NDQ2LC45NDI5MiwxLjE4Nzc3LC45NDI5MiwxLjAyMDU4LC44OTkwMywuOTAwODgsLjk0OTM4LC45Nzg5OCwuODEwOTMsLjk3NTcxLC45NDkzOCwxLjAyNCwuOTU3NywuOTU5MzMsLjk4NjIxLDEuMDQ3NCwuOTc0NTUsLjk4OTgxLC45NjcyLC45NTkzMywuOTQ0NiwuOTc4OTgsLjk3NDA3LC45NzY0NiwuNzgwMzYsMS4xMDIwOCwuOTU0NDIsLjk1Mjk4LC45NzU3OSwuOTMzMiwuOTQwMzksLjkzOCwuODA2ODcsMS4wMTE0OSwuODA2ODcsMS4wMjA1OCwuODA0NzksLjk5NzkzLC45OTc5MywuOTk3OTMsLjk5NzkzLDEuMDExNDksMS4wMDg3MiwuOTAwODgsLjkxODgyLDEuMDIxMywuODM2MSwxLjAyMDU4LC42MjI5NSwuNTQzMjQsLjg5MDIyLDEuMDg1OTUsMSwxLC45MDA4OCwxLC45NzQ1NSwuOTM1ODIsLjkwMDg4LDEsMS4wNTY4NiwuODM2MSwuOTk2NDIsLjk5NjQyLC45OTY0MiwuNzI4NTEsLjkwODM4LC45MDgzOCwuOTA4MzgsLjkwODM4LC45MDgzOCwuOTA4MzgsLjg2OCwuODIzOTEsLjgwMDYxLC44MDA2MSwuODAwNjEsLjgwMDYxLDEuMDI1OCwxLjAyNTgsMS4wMjU4LDEuMDI1OCwuOTc0ODQsLjk1NTQ2LC45MjE3OSwuOTIxNzksLjkyMTc5LC45MjE3OSwuOTIxNzksMS4wMjA1OCwuOTIxNzksLjk0NDM4LC45NDQzOCwuOTQ0MzgsLjk0NDM4LC45MDQwNiwuODY5NTgsLjk4MjI1LC45NDkzOCwuOTQ5MzgsLjk0OTM4LC45NDkzOCwuOTQ5MzgsLjk0OTM4LC45MDMxLC44MTA5MywuOTQ5MzgsLjk0OTM4LC45NDkzOCwuOTQ5MzgsLjk4NjIxLC45ODYyMSwuOTg2MjEsLjk4NjIxLC45Mzk2OSwuOTU5MzMsLjk0NDYsLjk0NDYsLjk0NDYsLjk0NDYsLjk0NDYsMS4wODU5NSwuOTQ0NiwuOTU0NDIsLjk1NDQyLC45NTQ0MiwuOTU0NDIsLjk0MDM5LC45Nzg5OCwuOTQwMzksLjkwODM4LC45NDkzOCwuOTA4MzgsLjk0OTM4LC45MDgzOCwuOTQ5MzgsLjgyMzkxLC44MTA5MywuODIzOTEsLjgxMDkzLC44MjM5MSwuODEwOTMsLjgyMzkxLC44MTA5MywuOTYzNzYsLjg0MzEzLC45NzQ4NCwuOTc1NzEsLjgwMDYxLC45NDkzOCwuODAwNjEsLjk0OTM4LC44MDA2MSwuOTQ5MzgsLjgwMDYxLC45NDkzOCwuODAwNjEsLjk0OTM4LC44NzY4LC45NTc3LC44NzY4LC45NTc3LC44NzY4LC45NTc3LDEsMSwuOTU0MDcsLjk1OTMzLC45NzA2OSwuOTU5MzMsMS4wMjU4LC45ODYyMSwxLjAyNTgsLjk4NjIxLDEuMDI1OCwuOTg2MjEsMS4wMjU4LC45ODYyMSwxLjAyNTgsLjk4NjIxLC44ODcsMS4wMTU5MSwuNzM5MDEsMS4wNDc0LDEsMSwuOTc0NTUsLjgzNjU1LC45ODk4MSwxLDEsLjgzNjU1LC43Mzk3NywuODM2NTUsLjczOTAzLC44NDYzOCwxLjAzMywuOTU1NDYsLjk1OTMzLDEsMSwuOTU1NDYsLjk1OTMzLC44MjcxLC45NTQxNywuOTU5MzMsLjkyMTc5LC45NDQ2LC45MjE3OSwuOTQ0NiwuOTIxNzksLjk0NDYsLjkzNiwuOTE5NjQsLjgyMTE0LC45NzY0NiwxLDEsLjgyMTE0LC45NzY0NiwuODA5NiwuNzgwMzYsLjgwOTYsLjc4MDM2LDEsMSwuODA5NiwuNzgwMzYsMSwxLC44OTcxMywuNzc0NTIsLjg5NzEzLDEuMTAyMDgsLjk0NDM4LC45NTQ0MiwuOTQ0MzgsLjk1NDQyLC45NDQzOCwuOTU0NDIsLjk0NDM4LC45NTQ0MiwuOTQ0MzgsLjk1NDQyLC45NDQzOCwuOTU0NDIsLjk0MDgzLC45NzU3OSwuOTA0MDYsLjk0MDM5LC45MDQwNiwuOTQ0NiwuOTM4LC45NDQ2LC45MzgsLjk0NDYsLjkzOCwxLC45OTc5MywuOTA4MzgsLjk0OTM4LC44NjgsLjkwMzEsLjkyMTc5LC45NDQ2LDEsMSwuODk3MTMsMS4xMDIwOCwuOTAwODgsLjkwMDg4LC45MDA4OCwuOTAwODgsLjkwMDg4LC45MDA4OCwuOTAwODgsLjkwMDg4LC45MDA4OCwuOTA5ODksLjkzNTgsLjkxOTQ1LC44MzE4MSwuNzUyNjEsLjg3OTkyLC44Mjk3NiwuOTYwMzQsLjgzNjg5LC45NzI2OCwxLjAwNzgsLjkwODM4LC44MzYzNywuODAxOSwuOTAxNTcsLjgwMDYxLC45NDQ2LC45NTQwNywuOTI0MzYsMS4wMjU4LC44NTAyMiwuOTcxNTMsMS4wMTU2LC45NTU0NiwuODkxOTIsLjkyMTc5LC45MjM2MSwuODcxMDcsLjk2MzE4LC44OTcxMywuOTM3MDQsLjk1NjM4LC45MTkwNSwuOTE3MDksLjkyNzk2LDEuMDI1OCwuOTM3MDQsLjk0ODM2LDEuMDM3MywuOTU5MzMsMS4wMDc4LC45NTg3MSwuOTQ4MzYsLjk2MTc0LC45MjYwMSwuOTQ5OCwuOTg2MDcsLjk1Nzc2LC45NTkzMywxLjA1NDUzLDEuMDA3OCwuOTgyNzUsLjkzMTQsLjk1NjE3LC45MTcwMSwxLjA1OTkzLC45NDQ2LC43ODM2NywuOTU1MywxLC44NjgzMiwxLjAxMjgsLjk1ODcxLC45OTM5NCwuODc1NDgsLjk2MzYxLC44Njc3NCwxLjAwNzgsLjk1ODcxLC45NDQ2LC45NTg3MSwuODY3NzQsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTQwODMsLjk3NTc5LC45NDA4MywuOTc1NzksLjk0MDgzLC45NzU3OSwuOTA0MDYsLjk0MDM5LC45NjY5NCwxLC44OTkwMywxLDEsMSwuOTM1ODIsLjkzNTgyLC45MzU4MiwxLC45MDgsLjkwOCwuOTE4LC45NDIxOSwuOTQyMTksLjk2NTQ0LDEsMS4yODUsMSwxLC44MTA3OSwuODEwNzksMSwxLC43NDg1NCwxLDEsMSwxLC45OTc5MywxLDEsMSwuNjUsMSwxLjM2MTQ1LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjE3MTczLDEsLjgwNTM1LC43NjE2OSwxLjAyMDU4LDEuMDczMiwxLjA1NDg2LDEsMSwxLjMwNjkyLDEuMDg1OTUsMS4wODU5NSwxLDEuMDg1OTUsMS4wODU5NSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMTYxNjEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0scW49e2xpbmVIZWlnaHQ6MS4yLGxpbmVHYXA6LjJ9LFhuPVsxLjM2ODk4LDEsMSwuNjYyMjcsLjgwNzc5LC44MTYyNSwuOTcyNzYsLjk3Mjc2LC45NzczMywuOTIyMjIsLjgzMjY2LC45NDI5MiwuOTQyOTIsMS4xNjE0OCwxLjAyMDU4LC45MzU4MiwuOTY2OTQsLjkzNTgyLDEuMTczMzcsLjk3Mjc2LC45NzI3NiwuOTcyNzYsLjk3Mjc2LC45NzI3NiwuOTcyNzYsLjk3Mjc2LC45NzI3NiwuOTcyNzYsLjk3Mjc2LC43ODA3NiwuNzgwNzYsMS4wMjA1OCwxLjAyMDU4LDEuMDIwNTgsLjcxNTQxLC43NjgxMywuODU1NzYsLjgwNTkxLC44MDcyOSwuOTQyOTksLjc3NTEyLC44MzY1NSwuODY1MjMsLjkyMjIyLC45ODYyMSwuNzE3NDMsLjgxNjk4LC43OTcyNiwuOTg1NTgsLjkyMjIyLC45MDYzNywuODM4MDksLjkwNjM3LC44MDcyOSwuNzY0NjMsLjg2Mjc1LC45MDY5OSwuOTE2MDUsLjkxNTQsLjg1MzA4LC44NTQ1OCwuOTA1MzEsLjk0MjkyLDEuMjEyOTYsLjk0MjkyLDEuMDIwNTgsLjg5OTAzLDEuMTg2MTYsLjk5NjEzLC45MTY3NywuNzgyMTYsLjkxNjc3LC45MDA4MywuOTg3OTYsLjkxMzUsLjkyMTY4LC45NTM4MSwuOTg5ODEsLjk1Mjk4LC45NTM4MSwuOTM0NTksLjkyMTY4LC45MTUxMywuOTIwMDQsLjkxNjc3LC45NTA3NywuNzQ4LDEuMDQ1MDIsLjkxNjc3LC45MjA2MSwuOTQyMzYsLjg5NTQ0LC44OTM2NCwuOSwuODA2ODcsLjg1NzgsLjgwNjg3LDEuMDIwNTgsLjgwNzc5LC45NzI3NiwuOTcyNzYsLjk3Mjc2LC45NzI3NiwuODU3OCwuOTk5NzMsMS4xODYxNiwuOTEzMzksMS4wODA3NCwuODI4OTEsMS4wMjA1OCwuNTU1MDksLjcxNTI2LC44OTAyMiwxLjA4NTk1LDEsMSwxLjE4NjE2LDEsLjk2NzM2LC45MzU4MiwxLjE4NjE2LDEsMS4wNDg2NCwuODI3MTEsLjk5MDQzLC45OTA0MywuOTkwNDMsLjcxNTQxLC44NTU3NiwuODU1NzYsLjg1NTc2LC44NTU3NiwuODU1NzYsLjg1NTc2LC44NDUsLjgwNzI5LC43NzUxMiwuNzc1MTIsLjc3NTEyLC43NzUxMiwuOTg2MjEsLjk4NjIxLC45ODYyMSwuOTg2MjEsLjk1OTYxLC45MjIyMiwuOTA2MzcsLjkwNjM3LC45MDYzNywuOTA2MzcsLjkwNjM3LDEuMDIwNTgsLjkwMjUxLC45MDY5OSwuOTA2OTksLjkwNjk5LC45MDY5OSwuODU0NTgsLjgzNjU5LC45NDk1MSwuOTk2MTMsLjk5NjEzLC45OTYxMywuOTk2MTMsLjk5NjEzLC45OTYxMywuODU4MTEsLjc4MjE2LC45MDA4MywuOTAwODMsLjkwMDgzLC45MDA4MywuOTUzODEsLjk1MzgxLC45NTM4MSwuOTUzODEsLjkxMzUsLjkyMTY4LC45MTUxMywuOTE1MTMsLjkxNTEzLC45MTUxMywuOTE1MTMsMS4wODU5NSwuOTE2NzcsLjkxNjc3LC45MTY3NywuOTE2NzcsLjkxNjc3LC44OTM2NCwuOTIzMzIsLjg5MzY0LC44NTU3NiwuOTk2MTMsLjg1NTc2LC45OTYxMywuODU1NzYsLjk5NjEzLC44MDcyOSwuNzgyMTYsLjgwNzI5LC43ODIxNiwuODA3MjksLjc4MjE2LC44MDcyOSwuNzgyMTYsLjk0Mjk5LC43Njc4MywuOTU5NjEsLjkxNjc3LC43NzUxMiwuOTAwODMsLjc3NTEyLC45MDA4MywuNzc1MTIsLjkwMDgzLC43NzUxMiwuOTAwODMsLjc3NTEyLC45MDA4MywuODY1MjMsLjkxMzUsLjg2NTIzLC45MTM1LC44NjUyMywuOTEzNSwxLDEsLjkyMjIyLC45MjE2OCwuOTIyMjIsLjkyMTY4LC45ODYyMSwuOTUzODEsLjk4NjIxLC45NTM4MSwuOTg2MjEsLjk1MzgxLC45ODYyMSwuOTUzODEsLjk4NjIxLC45NTM4MSwuODYwMzYsLjk3MDk2LC43MTc0MywuOTg5ODEsMSwxLC45NTI5OCwuNzk3MjYsLjk1MzgxLDEsMSwuNzk3MjYsLjY4OTQsLjc5NzI2LC43NDMyMSwuODE2OTEsMS4wMDA2LC45MjIyMiwuOTIxNjgsMSwxLC45MjIyMiwuOTIxNjgsLjc5NDY0LC45MjA5OCwuOTIxNjgsLjkwNjM3LC45MTUxMywuOTA2MzcsLjkxNTEzLC45MDYzNywuOTE1MTMsLjkwOSwuODc1MTQsLjgwNzI5LC45NTA3NywxLDEsLjgwNzI5LC45NTA3NywuNzY0NjMsLjc0OCwuNzY0NjMsLjc0OCwxLDEsLjc2NDYzLC43NDgsMSwxLC44NjI3NSwuNzI2NTEsLjg2Mjc1LDEuMDQ1MDIsLjkwNjk5LC45MTY3NywuOTA2OTksLjkxNjc3LC45MDY5OSwuOTE2NzcsLjkwNjk5LC45MTY3NywuOTA2OTksLjkxNjc3LC45MDY5OSwuOTE2NzcsLjkxNTQsLjk0MjM2LC44NTQ1OCwuODkzNjQsLjg1NDU4LC45MDUzMSwuOSwuOTA1MzEsLjksLjkwNTMxLC45LDEsLjk3Mjc2LC44NTU3NiwuOTk2MTMsLjg0NSwuODU4MTEsLjkwMjUxLC45MTY3NywxLDEsLjg2Mjc1LDEuMDQ1MDIsMS4xODYxNiwxLjE4NjE2LDEuMTg2MTYsMS4xODYxNiwxLjE4NjE2LDEuMTg2MTYsMS4xODYxNiwxLjE4NjE2LDEuMTg2MTYsMS4wMDg5OSwxLjMwNjI4LC44NTU3NiwuODAxNzgsLjY2ODYyLC43OTI3LC42OTMyMywuODgxMjcsLjcyNDU5LC44OTcxMSwuOTUzODEsLjg1NTc2LC44MDU5MSwuNzgwNSwuOTQ3MjksLjc3NTEyLC45MDUzMSwuOTIyMjIsLjkwNjM3LC45ODYyMSwuODE2OTgsLjkyNjU1LC45ODU1OCwuOTIyMjIsLjg1MzU5LC45MDYzNywuOTA5NzYsLjgzODA5LC45NDUyMywuODYyNzUsLjgzNTA5LC45MzE1NywuODUzMDgsLjgzMzkyLC45MjM0NiwuOTg2MjEsLjgzNTA5LC45Mjg4NiwuOTEzMjQsLjkyMTY4LC45NTM4MSwuOTA2NDYsLjkyODg2LC45MDU1NywuODY4NDcsLjkwMjc2LC45MTMyNCwuODY4NDIsLjkyMTY4LC45OTUzMSwuOTUzODEsLjkyMjQsLjg1NDA4LC45MjY5OSwuODY4NDcsMS4wMDUxLC45MTUxMywuODA0ODcsLjkzNDgxLDEsLjg4MTU5LDEuMDUyMTQsLjkwNjQ2LC45NzM1NSwuODE1MzksLjg5Mzk4LC44NTkyMywuOTUzODEsLjkwNjQ2LC45MTUxMywuOTA2NDYsLjg1OTIzLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjkxNTQsLjk0MjM2LC45MTU0LC45NDIzNiwuOTE1NCwuOTQyMzYsLjg1NDU4LC44OTM2NCwuOTY2OTQsMSwuODk5MDMsMSwxLDEsLjkxNzgyLC45MTc4MiwuOTE3ODIsMSwuODk2LC44OTYsLjg5NiwuOTMzMiwuOTMzMiwuOTU5NzMsMSwxLjI2LDEsMSwuODA0NzksLjgwMTc4LDEsMSwuODU2MzMsMSwxLDEsMSwuOTcyNzYsMSwxLDEsLjY5OCwxLDEuMzYxNDUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMTQ1NDIsMSwuNzkxOTksLjc4Njk0LDEuMDIwNTgsMS4wMzQ5MywxLjA1NDg2LDEsMSwxLjIzMDI2LDEuMDg1OTUsMS4wODU5NSwxLDEuMDg1OTUsMS4wODU5NSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMjAwMDYsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0sSG49e2xpbmVIZWlnaHQ6MS4yLGxpbmVHYXA6LjJ9LFduPVsxLjM2ODk4LDEsMSwuNjU1MDcsLjg0OTQzLC44NTYzOSwuODg0NjUsLjg4NDY1LC44NjkzNiwuODgzMDcsLjg2OTQ4LC44NTI4MywuODUyODMsMS4wNjM4MywxLjAyMDU4LC43NTk0NSwuOTIxOSwuNzU5NDUsMS4xNzMzNywuODg0NjUsLjg4NDY1LC44ODQ2NSwuODg0NjUsLjg4NDY1LC44ODQ2NSwuODg0NjUsLjg4NDY1LC44ODQ2NSwuODg0NjUsLjc1OTQ1LC43NTk0NSwxLjAyMDU4LDEuMDIwNTgsMS4wMjA1OCwuNjkwNDYsLjcwOTI2LC44NTE1OCwuNzc4MTIsLjc2ODUyLC44OTU5MSwuNzA0NjYsLjc2MTI1LC44MDA5NCwuODY4MjIsLjgzODY0LC43MjgsLjc3MjEyLC43OTQ3NSwuOTM2MzcsLjg3NTE0LC44NTg4LC43NjAxMywuODU4OCwuNzI0MjEsLjY5ODY2LC43NzU5OCwuODU5OTEsLjgwODExLC44NzgzMiwuNzgxMTIsLjc3NTEyLC44NTYyLDEuMDIyMiwxLjE4NDE3LDEuMDIyMiwxLjI3MDE0LC44OTkwMywxLjE1MDEyLC45Mzg1OSwuOTQzOTksLjg0NiwuOTQzOTksLjgxNDUzLDEuMDE4NiwuOTQyMTksLjk2MDE3LDEuMDMwNzUsMS4wMjE3NSwuOTEyLDEuMDMwNzUsLjk2OTk4LC45NjAxNywuOTM4NTksLjk0Mzk5LC45NDM5OSwuOTU0OTMsLjc0NiwxLjEyNjU4LC45NDU3OCwuOTEsLjk3OSwuODgyLC44ODIsLjgzLC44NTAzNCwuODM1MzcsLjg1MDM0LDEuMDIwNTgsLjcwODY5LC44ODQ2NSwuODg0NjUsLjg4NDY1LC44ODQ2NSwuODM1MzcsLjkwMDgzLDEuMTUwMTIsLjkxNjEsLjk0NTY1LC43MzU0MSwxLjAyMDU4LC41MzYwOSwuNjkzNTMsLjc5NTE5LDEuMDg1OTUsMSwxLDEuMTUwMTIsMSwuOTE5NzQsLjc1OTQ1LDEuMTUwMTIsMSwuOTQ0NiwuNzMzNjEsLjkwMDUsLjkwMDUsLjkwMDUsLjYyODY0LC44NTE1OCwuODUxNTgsLjg1MTU4LC44NTE1OCwuODUxNTgsLjg1MTU4LC43NzMsLjc2ODUyLC43MDQ2NiwuNzA0NjYsLjcwNDY2LC43MDQ2NiwuODM4NjQsLjgzODY0LC44Mzg2NCwuODM4NjQsLjkwNTYxLC44NzUxNCwuODU4OCwuODU4OCwuODU4OCwuODU4OCwuODU4OCwxLjAyMDU4LC44NTc1MSwuODU5OTEsLjg1OTkxLC44NTk5MSwuODU5OTEsLjc3NTEyLC43NjAxMywuODgwNzUsLjkzODU5LC45Mzg1OSwuOTM4NTksLjkzODU5LC45Mzg1OSwuOTM4NTksLjgwNzUsLjg0NiwuODE0NTMsLjgxNDUzLC44MTQ1MywuODE0NTMsLjgyNDI0LC44MjQyNCwuODI0MjQsLjgyNDI0LC45Mjc4LC45NjAxNywuOTM4NTksLjkzODU5LC45Mzg1OSwuOTM4NTksLjkzODU5LDEuMDg1OTUsLjg1NjIsLjk0NTc4LC45NDU3OCwuOTQ1NzgsLjk0NTc4LC44ODIsLjk0NTc4LC44ODIsLjg1MTU4LC45Mzg1OSwuODUxNTgsLjkzODU5LC44NTE1OCwuOTM4NTksLjc2ODUyLC44NDYsLjc2ODUyLC44NDYsLjc2ODUyLC44NDYsLjc2ODUyLC44NDYsLjg5NTkxLC44NTQ0LC45MDU2MSwuOTQzOTksLjcwNDY2LC44MTQ1MywuNzA0NjYsLjgxNDUzLC43MDQ2NiwuODE0NTMsLjcwNDY2LC44MTQ1MywuNzA0NjYsLjgxNDUzLC44MDA5NCwuOTQyMTksLjgwMDk0LC45NDIxOSwuODAwOTQsLjk0MjE5LDEsMSwuODY4MjIsLjk2MDE3LC44NjgyMiwuOTYwMTcsLjgzODY0LC44MjQyNCwuODM4NjQsLjgyNDI0LC44Mzg2NCwuODI0MjQsLjgzODY0LDEuMDMwNzUsLjgzODY0LC44MjQyNCwuODE0MDIsMS4wMjczOCwuNzI4LDEuMDIxNzUsMSwxLC45MTIsLjc5NDc1LDEuMDMwNzUsMSwxLC43OTQ3NSwuODM5MTEsLjc5NDc1LC42NjI2NiwuODA1NTMsMS4wNjY3NiwuODc1MTQsLjk2MDE3LDEsMSwuODc1MTQsLjk2MDE3LC44Njg2NSwuODczOTYsLjk2MDE3LC44NTg4LC45Mzg1OSwuODU4OCwuOTM4NTksLjg1ODgsLjkzODU5LC44NjcsLjg0NzU5LC43MjQyMSwuOTU0OTMsMSwxLC43MjQyMSwuOTU0OTMsLjY5ODY2LC43NDYsLjY5ODY2LC43NDYsMSwxLC42OTg2NiwuNzQ2LDEsMSwuNzc1OTgsLjg4NDE3LC43NzU5OCwxLjEyNjU4LC44NTk5MSwuOTQ1NzgsLjg1OTkxLC45NDU3OCwuODU5OTEsLjk0NTc4LC44NTk5MSwuOTQ1NzgsLjg1OTkxLC45NDU3OCwuODU5OTEsLjk0NTc4LC44NzgzMiwuOTc5LC43NzUxMiwuODgyLC43NzUxMiwuODU2MiwuODMsLjg1NjIsLjgzLC44NTYyLC44MywxLC44ODQ2NSwuODUxNTgsLjkzODU5LC43NzMsLjgwNzUsLjg1NzUxLC44NTYyLDEsMSwuNzc1OTgsMS4xMjY1OCwxLjE1MDEyLDEuMTUwMTIsMS4xNTAxMiwxLjE1MDEyLDEuMTUwMTIsMS4xNTMxMywxLjE1MDEyLDEuMTUwMTIsMS4xNTAxMiwxLjA4MTA2LDEuMDM5MDEsLjg1MTU4LC43NzAyNSwuNjIyNjQsLjc2NDYsLjY1MzUxLC44NjAyNiwuNjk0NjEsLjg5OTQ3LDEuMDMwNzUsLjg1MTU4LC43NzgxMiwuNzY0NDksLjg4ODM2LC43MDQ2NiwuODU2MiwuODY4MjIsLjg1ODgsLjgzODY0LC43NzIxMiwuODUzMDgsLjkzNjM3LC44NzUxNCwuODIzNTIsLjg1ODgsLjg1NzAxLC43NjAxMywuODkwNTgsLjc3NTk4LC44MTU2LC44MjU2NSwuNzgxMTIsLjc3ODk5LC44OTM4NiwuODM4NjQsLjgxNTYsLjk0ODYsLjkyMzg4LC45NjE4NiwxLjAzMDc1LC45MTEyMywuOTQ4NiwuOTMyOTgsLjg3OCwuOTM5NDIsLjkyMzg4LC44NDU5NiwuOTYxODYsLjk1MTE5LDEuMDMwNzUsLjkyMiwuODg3ODcsLjk1ODI5LC44OCwuOTM1NTksLjkzODU5LC43ODgxNSwuOTM3NTgsMSwuODkyMTcsMS4wMzczNywuOTExMjMsLjkzOTY5LC43NzQ4NywuODU3NjksLjg2Nzk5LDEuMDMwNzUsLjkxMTIzLC45Mzg1OSwuOTExMjMsLjg2Nzk5LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjg3ODMyLC45NzksLjg3ODMyLC45NzksLjg3ODMyLC45NzksLjc3NTEyLC44ODIsLjkyMTksMSwuODk5MDMsMSwxLDEsLjg3MzIxLC44NzMyMSwuODczMjEsMSwxLjAyNywxLjAyNywxLjAyNywuODY4NDcsLjg2ODQ3LC43OTEyMSwxLDEuMTI0LDEsMSwuNzM1NzIsLjczNTcyLDEsMSwuODUwMzQsMSwxLDEsMSwuODg0NjUsMSwxLDEsLjY2OSwxLDEuMzYxNDUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMDQ4MjgsMSwuNzQ5NDgsLjc1MTg3LDEuMDIwNTgsLjk4MzkxLDEuMDIxMTksMSwxLDEuMDYyMzMsMS4wODU5NSwxLjA4NTk1LDEsMS4wODU5NSwxLjA4NTk1LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMS4wNTIzMywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSx6bj17bGluZUhlaWdodDoxLjIsbGluZUdhcDouMn0sR249WzEuMzY4OTgsMSwxLC43NjMwNSwuODI3ODQsLjk0OTM1LC44OTM2NCwuOTIyNDEsLjg5MDczLC45MDcwNiwuOTg0NzIsLjg1MjgzLC44NTI4MywxLjA2NjQsMS4wMjA1OCwuNzQ1MDUsLjkyMTksLjc0NTA1LDEuMjM0NTYsLjkyMjQxLC45MjI0MSwuOTIyNDEsLjkyMjQxLC45MjI0MSwuOTIyNDEsLjkyMjQxLC45MjI0MSwuOTIyNDEsLjkyMjQxLC43NDUwNSwuNzQ1MDUsMS4wMjA1OCwxLjAyMDU4LDEuMDIwNTgsLjczMDAyLC43MjYwMSwuOTE3NTUsLjgxMjYsLjgwMzE0LC45MjIyMiwuNzM3NjQsLjc5NzI2LC44MzA1MSwuOTAyODQsLjg2MDIzLC43NCwuODEyNiwuODQ4NjksLjk2NTE4LC45MTExNSwuODg1OCwuNzk3NjEsLjg4NTgsLjc0NDk4LC43MzkxNCwuODEzNjMsLjg5NTkxLC44MzY1OSwuODk2MzMsLjg1NjA4LC44MTExLC45MDUzMSwxLjAyMjIsMS4yMjczNiwxLjAyMjIsMS4yNzAxNCwuODk5MDMsLjkwMDg4LC44NjY2NywxLjAyMzEsLjg5NiwxLjAxNDExLC45MDA4MywxLjA1MDk5LDEuMDA1MTIsLjk5NzkzLDEuMDUzMjYsMS4wOTM3NywuOTM4LDEuMDYyMjYsMS4wMDExOSwuOTk3OTMsLjk4NzE0LDEuMDIzMSwxLjAxMjMxLC45ODE5NiwuNzkyLDEuMTkxMzcsLjk5MDc0LC45NjIsMS4wMTkxNSwuOTI2LC45NDIsLjg1NiwuODUwMzQsLjkyMDA2LC44NTAzNCwxLjAyMDU4LC42OTA2NywuOTIyNDEsLjkyMjQxLC45MjI0MSwuOTIyNDEsLjkyMDA2LC45MzMyLC45MDA4OCwuOTE4ODIsLjkzNDg0LC43NTMzOSwxLjAyMDU4LC41Njg2NiwuNTQzMjQsLjc5NTE5LDEuMDg1OTUsMSwxLC45MDA4OCwxLC45NTMyNSwuNzQ1MDUsLjkwMDg4LDEsLjk3MTk4LC43NTMzOSwuOTEwMDksLjkxMDA5LC45MTAwOSwuNjY0NjYsLjkxNzU1LC45MTc1NSwuOTE3NTUsLjkxNzU1LC45MTc1NSwuOTE3NTUsLjc4OCwuODAzMTQsLjczNzY0LC43Mzc2NCwuNzM3NjQsLjczNzY0LC44NjAyMywuODYwMjMsLjg2MDIzLC44NjAyMywuOTI5MTUsLjkxMTE1LC44ODU4LC44ODU4LC44ODU4LC44ODU4LC44ODU4LDEuMDIwNTgsLjg4NTgsLjg5NTkxLC44OTU5MSwuODk1OTEsLjg5NTkxLC44MTExLC43OTYxMSwuODk3MTMsLjg2NjY3LC44NjY2NywuODY2NjcsLjg2NjY3LC44NjY2NywuODY2NjcsLjg2OTM2LC44OTYsLjkwMDgzLC45MDA4MywuOTAwODMsLjkwMDgzLC44NDIyNCwuODQyMjQsLjg0MjI0LC44NDIyNCwuOTcyNzYsLjk5NzkzLC45ODcxNCwuOTg3MTQsLjk4NzE0LC45ODcxNCwuOTg3MTQsMS4wODU5NSwuODk4NzYsLjk5MDc0LC45OTA3NCwuOTkwNzQsLjk5MDc0LC45NDIsMS4wMjMxLC45NDIsLjkxNzU1LC44NjY2NywuOTE3NTUsLjg2NjY3LC45MTc1NSwuODY2NjcsLjgwMzE0LC44OTYsLjgwMzE0LC44OTYsLjgwMzE0LC44OTYsLjgwMzE0LC44OTYsLjkyMjIyLC45MzM3MiwuOTI5MTUsMS4wMTQxMSwuNzM3NjQsLjkwMDgzLC43Mzc2NCwuOTAwODMsLjczNzY0LC45MDA4MywuNzM3NjQsLjkwMDgzLC43Mzc2NCwuOTAwODMsLjgzMDUxLDEuMDA1MTIsLjgzMDUxLDEuMDA1MTIsLjgzMDUxLDEuMDA1MTIsMSwxLC45MDI4NCwuOTk3OTMsLjkwOTc2LC45OTc5MywuODYwMjMsLjg0MjI0LC44NjAyMywuODQyMjQsLjg2MDIzLC44NDIyNCwuODYwMjMsMS4wNTMyNiwuODYwMjMsLjg0MjI0LC44Mjg3MywxLjA3NDY5LC43NCwxLjA5Mzc3LDEsMSwuOTM4LC44NDg2OSwxLjA2MjI2LDEsMSwuODQ4NjksLjgzNzA0LC44NDg2OSwuODE0NDEsLjg1NTg4LDEuMDg5MjcsLjkxMTE1LC45OTc5MywxLDEsLjkxMTE1LC45OTc5MywuOTE4ODcsLjkwOTkxLC45OTc5MywuODg1OCwuOTg3MTQsLjg4NTgsLjk4NzE0LC44ODU4LC45ODcxNCwuODk0LC45MTQzNCwuNzQ0OTgsLjk4MTk2LDEsMSwuNzQ0OTgsLjk4MTk2LC43MzkxNCwuNzkyLC43MzkxNCwuNzkyLDEsMSwuNzM5MTQsLjc5MiwxLDEsLjgxMzYzLC45MDQsLjgxMzYzLDEuMTkxMzcsLjg5NTkxLC45OTA3NCwuODk1OTEsLjk5MDc0LC44OTU5MSwuOTkwNzQsLjg5NTkxLC45OTA3NCwuODk1OTEsLjk5MDc0LC44OTU5MSwuOTkwNzQsLjg5NjMzLDEuMDE5MTUsLjgxMTEsLjk0MiwuODExMSwuOTA1MzEsLjg1NiwuOTA1MzEsLjg1NiwuOTA1MzEsLjg1NiwxLC45MjI0MSwuOTE3NTUsLjg2NjY3LC43ODgsLjg2OTM2LC44ODU4LC44OTg3NiwxLDEsLjgxMzYzLDEuMTkxMzcsLjkwMDg4LC45MDA4OCwuOTAwODgsLjkwMDg4LC45MDA4OCwuOTAwODgsLjkwMDg4LC45MDA4OCwuOTAwODgsLjkwMzg4LDEuMDM5MDEsLjkyMTM4LC43ODEwNSwuNzE1NCwuODYxNjksLjgwNTEzLC45NDAwNywuODI1MjgsLjk4NjEyLDEuMDYyMjYsLjkxNzU1LC44MTI2LC44MTg4NCwuOTI4MTksLjczNzY0LC45MDUzMSwuOTAyODQsLjg4NTgsLjg2MDIzLC44MTI2LC45MTE3MiwuOTY1MTgsLjkxMTE1LC44MzA4OSwuODg1OCwuODc3OTEsLjc5NzYxLC44OTI5NywuODEzNjMsLjg4MTU3LC44OTk5MiwuODU2MDgsLjgxOTkyLC45NDMwNywuODYwMjMsLjg4MTU3LC45NTMwOCwuOTg2OTksLjk5NzkzLDEuMDYyMjYsLjk1ODE3LC45NTMwOCwuOTczNTgsLjkyOCwuOTgwODgsLjk4Njk5LC45Mjc2MSwuOTk3OTMsLjk2MDE3LDEuMDYyMjYsLjk4NiwuOTQ0LC45NTk3OCwuOTM4LC45NjcwNSwuOTg3MTQsLjgwNDQyLC45ODk3MiwxLC44OTc2MiwxLjA0NTUyLC45NTgxNywuOTkwMDcsLjg3MDY0LC45MTg3OSwuODg4ODgsMS4wNjIyNiwuOTU4MTcsLjk4NzE0LC45NTgxNywuODg4ODgsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuODk2MzMsMS4wMTkxNSwuODk2MzMsMS4wMTkxNSwuODk2MzMsMS4wMTkxNSwuODExMSwuOTQyLC45MjE5LDEsLjg5OTAzLDEsMSwxLC45MzE3MywuOTMxNzMsLjkzMTczLDEsMS4wNjMwNCwxLjA2MzA0LDEuMDY5MDQsLjg5OTAzLC44OTkwMywuODA1NDksMSwxLjE1NiwxLDEsLjc2NTc1LC43NjU3NSwxLDEsLjcyNDU4LDEsMSwxLDEsLjkyMjQxLDEsMSwxLC42MTksMSwxLjM2MTQ1LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjA3MjU3LDEsLjc0NzA1LC43MTExOSwxLjAyMDU4LDEuMDI0LDEuMDIxMTksMSwxLDEuMTUzNiwxLjA4NTk1LDEuMDg1OTUsMSwxLjA4NTk1LDEuMDg1OTUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjA1NjM4LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLCRuPXtsaW5lSGVpZ2h0OjEuMixsaW5lR2FwOi4yfSxWbj1bMS43NjczOCwxLDEsLjk5Mjk3LC45ODI0LDEuMDQwMTYsMS4wNjQ5NywxLjAzNDI0LC45NzUyOSwxLjE3NjQ3LDEuMjMyMDMsMS4xMDg1LDEuMTA4NSwxLjE2OTM5LDEuMjEwNywuOTc1NCwxLjIxNDA4LC45NzU0LDEuNTk1NzgsMS4wMzQyNCwxLjAzNDI0LDEuMDM0MjQsMS4wMzQyNCwxLjAzNDI0LDEuMDM0MjQsMS4wMzQyNCwxLjAzNDI0LDEuMDM0MjQsMS4wMzQyNCwuODEzNzgsLjgxMzc4LDEuMjEwNywxLjIxMDcsMS4yMTA3LC43MTcwMywuOTc4NDcsLjk3MzYzLC44ODc3NiwuODY0MSwxLjAyMDk2LC43OTc5NSwuODUxMzIsLjkxNCwxLjA2MDg1LDEuMTQwNiwuODAwNywuODk4NTgsLjgzNjkzLDEuMTQ4ODksMS4wOTM5OCwuOTc0ODksLjkyMDk0LC45NzQ4OSwuOTAzOTksLjg0MDQxLC45NTkyMywxLjAwMTM1LDEsMS4wNjQ2NywuOTgyNDMsLjkwOTk2LC45OTM2MSwxLjEwODUsMS41Njk0MiwxLjEwODUsMS4yMTA3LC43NDYyNywuOTQyODIsLjk2NzUyLDEuMDE1MTksLjg2MzA0LDEuMDEzNTksLjk3Mjc4LDEuMTUxMDMsMS4wMTM1OSwuOTg1NjEsMS4wMjI4NSwxLjAyMjg1LDEuMDA1MjcsMS4wMjI4NSwxLjAzMDIsLjk5MDQxLDEuMDAwOCwxLjAxNTE5LDEuMDEzNTksMS4wMjI1OCwuNzkxMDQsMS4xNjg2MiwuOTkwNDEsLjk3NDU0LDEuMDI1MTEsLjk5Mjk4LC45Njc1MiwuOTU4MDEsLjk0ODU2LDEuMTY1NzksLjk0ODU2LDEuMjEwNywuOTgyNCwxLjAzNDI0LDEuMDM0MjQsMSwxLjAzNDI0LDEuMTY1NzksLjg3MjcsMS4zODcxLDEuMTg2MjIsMS4xMDgxOCwxLjA0NDc4LDEuMjEwNywxLjE4NjIyLC43NTE1NSwuOTQ5OTQsMS4yODgyNiwxLjIxNDA4LDEuMjE0MDgsLjkxMDU2LDEsLjkxNTcyLC45NzU0LC42NDY2MywxLjE4MzI4LDEuMjQ4NjYsMS4wNDQ3OCwxLjE0MTY5LDEuMTU3NDksMS4xNzM4OSwuNzE3MDMsLjk3MzYzLC45NzM2MywuOTczNjMsLjk3MzYzLC45NzM2MywuOTczNjMsLjkzNTA2LC44NjQxLC43OTc5NSwuNzk3OTUsLjc5Nzk1LC43OTc5NSwxLjE0MDYsMS4xNDA2LDEuMTQwNiwxLjE0MDYsMS4wMjA5NiwxLjA5Mzk4LC45NzQyNiwuOTc0MjYsLjk3NDI2LC45NzQyNiwuOTc0MjYsMS4yMTA3LC45NzQ4OSwxLjAwMTM1LDEuMDAxMzUsMS4wMDEzNSwxLjAwMTM1LC45MDk5NiwuOTIwOTQsMS4wMjc5OCwuOTY3NTIsLjk2NzUyLC45Njc1MiwuOTY3NTIsLjk2NzUyLC45Njc1MiwuOTMxMzYsLjg2MzA0LC45NzI3OCwuOTcyNzgsLjk3Mjc4LC45NzI3OCwxLjAyMjg1LDEuMDIyODUsMS4wMjI4NSwxLjAyMjg1LC45NzEyMiwuOTkwNDEsMSwxLDEsMSwxLDEuMjg4MjYsMS4wMDA4LC45OTA0MSwuOTkwNDEsLjk5MDQxLC45OTA0MSwuOTY3NTIsMS4wMTUxOSwuOTY3NTIsLjk3MzYzLC45Njc1MiwuOTczNjMsLjk2NzUyLC45NzM2MywuOTY3NTIsLjg2NDEsLjg2MzA0LC44NjQxLC44NjMwNCwuODY0MSwuODYzMDQsLjg2NDEsLjg2MzA0LDEuMDIwOTYsMS4wMzA1NywxLjAyMDk2LDEuMDM1MTcsLjc5Nzk1LC45NzI3OCwuNzk3OTUsLjk3Mjc4LC43OTc5NSwuOTcyNzgsLjc5Nzk1LC45NzI3OCwuNzk3OTUsLjk3Mjc4LC45MTQsMS4wMTM1OSwuOTE0LDEuMDEzNTksLjkxNCwxLjAxMzU5LDEsMSwxLjA2MDg1LC45ODU2MSwxLjA2MDg1LDEuMDA4NzksMS4xNDA2LDEuMDIyODUsMS4xNDA2LDEuMDIyODUsMS4xNDA2LDEuMDIyODUsMS4xNDA2LDEuMDIyODUsMS4xNDA2LDEuMDIyODUsLjk3MTM4LDEuMDg2OTIsLjgwMDcsMS4wMjI4NSwxLDEsMS4wMDUyNywuODM2OTMsMS4wMjI4NSwxLDEsLjgzNjkzLC45NDU1LC44MzY5MywuOTA0MTgsLjgzNjkzLDEuMTMwMDUsMS4wOTM5OCwuOTkwNDEsMSwxLDEuMDkzOTgsLjk5MDQxLC45NjY5MiwxLjA5MjUxLC45OTA0MSwuOTc0ODksMS4wMDA4LC45NzQ4OSwxLjAwMDgsLjk3NDg5LDEuMDAwOCwuOTM5OTQsLjk3OTMxLC45MDM5OSwxLjAyMjU4LDEsMSwuOTAzOTksMS4wMjI1OCwuODQwNDEsLjc5MTA0LC44NDA0MSwuNzkxMDQsLjg0MDQxLC43OTEwNCwuODQwNDEsLjc5MTA0LDEsMSwuOTU5MjMsMS4wNzAzNCwuOTU5MjMsMS4xNjg2MiwxLjAwMTM1LC45OTA0MSwxLjAwMTM1LC45OTA0MSwxLjAwMTM1LC45OTA0MSwxLjAwMTM1LC45OTA0MSwxLjAwMTM1LC45OTA0MSwxLjAwMTM1LC45OTA0MSwxLjA2NDY3LDEuMDI1MTEsLjkwOTk2LC45Njc1MiwuOTA5OTYsLjk5MzYxLC45NTgwMSwuOTkzNjEsLjk1ODAxLC45OTM2MSwuOTU4MDEsMS4wNzczMywxLjAzNDI0LC45NzM2MywuOTY3NTIsLjkzNTA2LC45MzEzNiwuOTc0ODksMS4wMDA4LDEsMSwuOTU5MjMsMS4xNjg2MiwxLjE1MTAzLDEuMTUxMDMsMS4wMTE3MywxLjAzOTU5LC43NTk1MywuODEzNzgsLjc5OTEyLDEuMTUxMDMsMS4yMTk5NCwuOTUxNjEsLjg3ODE1LDEuMDExNDksLjgxNTI1LC43Njc2LC45ODE2NywxLjAxMTM0LDEuMDI1NDYsLjg0MDk3LDEuMDMwODksMS4xODEwMiwuOTczNjMsLjg4Nzc2LC44NTEzNCwuOTc4MjYsLjc5Nzk1LC45OTM2MSwxLjA2MDg1LC45NzQ4OSwxLjE0MDYsLjg5ODU4LDEuMDM4OCwxLjE0ODg5LDEuMDkzOTgsLjg2MDM5LC45NzQ4OSwxLjA1OTUsLjkyMDk0LC45NDc5MywuOTU5MjMsLjkwOTk2LC45OTM0NiwuOTgyNDMsMS4wMjExMiwuOTU0OTMsMS4xNDA2LC45MDk5NiwxLjAzNTc0LDEuMDI1OTcsMS4wMDA4LDEuMTgxMDIsMS4wNjYyOCwxLjAzNTc0LDEuMDE5MiwxLjAxOTMyLDEuMDA4ODYsLjk3NTMxLDEuMDEwNiwxLjAwMDgsMS4xMzE4OSwxLjE4MTAyLDEuMDIyNzcsLjk4NjgzLDEuMDAxNiwuOTk1NjEsMS4wNzIzNywxLjAwMDgsLjkwNDM0LC45OTkyMSwuOTM4MDMsLjg5NjUsMS4yMzA4NSwxLjA2NjI4LDEuMDQ5ODMsLjk2MjY4LDEuMDQ5OSwuOTg0MzksMS4xODEwMiwxLjA2NjI4LDEuMDAwOCwxLjA2NjI4LC45ODQzOSwuNzk3OTUsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMS4wOTQ2NiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTcyNzgsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMS4wMjA2NSwxLDEsMSwxLDEsMSwxLjA2NDY3LDEuMDI1MTEsMS4wNjQ2NywxLjAyNTExLDEuMDY0NjcsMS4wMjUxMSwuOTA5OTYsLjk2NzUyLDEsMS4yMTQwOCwuODk5MDMsMSwxLC43NTE1NSwxLjA0Mzk0LDEuMDQzOTQsMS4wNDM5NCwxLjA0Mzk0LC45ODYzMywuOTg2MzMsLjk4NjMzLC43MzA0NywuNzMwNDcsMS4yMDY0MiwuOTEyMTEsMS4yNTYzNSwxLjIyMiwxLjAyOTU2LDEuMDMzNzIsMS4wMzM3MiwuOTYwMzksMS4yNDYzMywxLDEuMTI0NTQsLjkzNTAzLDEuMDM0MjQsMS4xOTY4NywxLjAzNDI0LDEsMSwxLC43NzEsMSwxLDEuMTU3NDksMS4xNTc0OSwxLjE1NzQ5LDEuMTA5NDgsLjg2Mjc5LC45NDQzNCwuODYyNzksLjk0NDM0LC44NjE4MiwxLDEsMS4xNjg5NywxLC45NjA4NSwuOTAxMzcsMS4yMTA3LDEuMTg0MTYsMS4xMzk3MywuNjk4MjUsLjk3MTYsMi4xMDMzOSwxLjI5MDA0LDEuMjkwMDQsMS4yMTE3MiwxLjI5MDA0LDEuMjkwMDQsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjQyNjAzLDEsLjk5ODYyLC45OTg2MiwxLC44NzAyNSwuODcwMjUsLjg3MDI1LC44NzAyNSwxLjE4ODc0LDEuNDI2MDMsMSwxLjQyNjAzLDEuNDI2MDMsLjk5ODYyLDEsMSwxLDEsMSwxLjI4ODYsMS4wNDMxNSwxLjE1Mjk2LDEuMzQxNjMsMSwxLDEsMS4wOTE5MywxLjA5MTkzLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSxLbj17bGluZUhlaWdodDoxLjMzMDA4LGxpbmVHYXA6MH0sSm49WzEuNzY3MzgsMSwxLC45ODk0NiwxLjAzOTU5LDEuMDQwMTYsMS4wMjgwOSwxLjAzNiwuOTc2MzksMS4xMDk1MywxLjIzMjAzLDEuMTExNDQsMS4xMTE0NCwxLjE2OTM5LDEuMjEyMzcsLjk3NTQsMS4yMTI2MSwuOTc1NCwxLjU5NzU0LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LDEuMDM2LC44MTM3OCwuODEzNzgsMS4yMTIzNywxLjIxMjM3LDEuMjEyMzcsLjczNTQxLC45Nzg0NywuOTczNjMsLjg5NzIzLC44Nzg5NywxLjA0MjYsLjc5NDI5LC44NTI5MiwuOTExNDksMS4wNTgxNSwxLjE0MDYsLjc5NjMxLC45MDEyOCwuODM4NTMsMS4wNDM5NiwxLjEwNjE1LC45NzU1MiwuOTQ0MzYsLjk3NTUyLC44ODY0MSwuODA1MjcsLjk2MDgzLDEuMDAxMzUsMSwxLjA2Nzc3LC45ODE3LC45MTE0MiwuOTkzNjEsMS4xMTE0NCwxLjU3MjkzLDEuMTExNDQsMS4yMTIzNywuNzQ2MjcsMS4zMTgxOCwxLjA2NTg1LC45NzA0MiwuODMwNTUsLjk3MDQyLC45MzUwMywxLjEyNjEsLjk3MDQyLC45NzkyMiwxLjE0MjM2LC45NDU1MiwxLjAxMDU0LDEuMTQyMzYsMS4wMjQ3MSwuOTc5MjIsLjk0MTY1LC45NzA0MiwuOTcwNDIsMS4wMjc2LC43ODkyOSwxLjEyNjEsLjk3OTIyLC45NTg3NCwxLjAyMTk3LC45ODUwNywuOTY3NTIsLjk3MTY4LC45NTEwNywxLjE2NTc5LC45NTEwNywxLjIxMjM3LDEuMDM5NTksMS4wMzYsMS4wMzYsMSwxLjAzNiwxLjE2NTc5LC44NzM1NywxLjMxODE4LDEuMTg3NTQsMS4yNjc4MSwxLjA1MzU2LDEuMjEyMzcsMS4xODYyMiwuNzk0ODcsLjk0OTk0LDEuMjkwMDQsMS4yNDA0NywxLjI0MDQ3LDEuMzE4MTgsMSwuOTE0ODQsLjk3NTQsMS4zMTgxOCwxLjEzNDksMS4yNDg2NiwxLjA1MzU2LDEuMTM5MzQsMS4xNTU3NCwxLjE3Mzg5LC43MzU0MSwuOTczNjMsLjk3MzYzLC45NzM2MywuOTczNjMsLjk3MzYzLC45NzM2MywuOTQzODUsLjg3ODk3LC43OTQyOSwuNzk0MjksLjc5NDI5LC43OTQyOSwxLjE0MDYsMS4xNDA2LDEuMTQwNiwxLjE0MDYsMS4wNDI2LDEuMTA2MTUsLjk3NTUyLC45NzU1MiwuOTc1NTIsLjk3NTUyLC45NzU1MiwxLjIxMjM3LC45NzU1MiwxLjAwMTM1LDEuMDAxMzUsMS4wMDEzNSwxLjAwMTM1LC45MTE0MiwuOTQ0MzYsLjk4NzIxLDEuMDY1ODUsMS4wNjU4NSwxLjA2NTg1LDEuMDY1ODUsMS4wNjU4NSwxLjA2NTg1LC45NjcwNSwuODMwNTUsLjkzNTAzLC45MzUwMywuOTM1MDMsLjkzNTAzLDEuMTQyMzYsMS4xNDIzNiwxLjE0MjM2LDEuMTQyMzYsLjkzMTI1LC45NzkyMiwuOTQxNjUsLjk0MTY1LC45NDE2NSwuOTQxNjUsLjk0MTY1LDEuMjkwMDQsLjk0MTY1LC45NzkyMiwuOTc5MjIsLjk3OTIyLC45NzkyMiwuOTY3NTIsLjk3MDQyLC45Njc1MiwuOTczNjMsMS4wNjU4NSwuOTczNjMsMS4wNjU4NSwuOTczNjMsMS4wNjU4NSwuODc4OTcsLjgzMDU1LC44Nzg5NywuODMwNTUsLjg3ODk3LC44MzA1NSwuODc4OTcsLjgzMDU1LDEuMDQyNiwxLjAwMzMsMS4wNDI2LC45NzA0MiwuNzk0MjksLjkzNTAzLC43OTQyOSwuOTM1MDMsLjc5NDI5LC45MzUwMywuNzk0MjksLjkzNTAzLC43OTQyOSwuOTM1MDMsLjkxMTQ5LC45NzA0MiwuOTExNDksLjk3MDQyLC45MTE0OSwuOTcwNDIsMSwxLDEuMDU4MTUsLjk3OTIyLDEuMDU4MTUsLjk3OTIyLDEuMTQwNiwxLjE0MjM2LDEuMTQwNiwxLjE0MjM2LDEuMTQwNiwxLjE0MjM2LDEuMTQwNiwxLjE0MjM2LDEuMTQwNiwxLjE0MjM2LC45NzQ0MSwxLjA0MzAyLC43OTYzMSwxLjAxNTgyLDEsMSwxLjAxMDU0LC44Mzg1MywxLjE0MjM2LDEsMSwuODM4NTMsMS4wOTEyNSwuODM4NTMsLjkwNDE4LC44Mzg1MywxLjE5NTA4LDEuMTA2MTUsLjk3OTIyLDEsMSwxLjEwNjE1LC45NzkyMiwxLjAxMDM0LDEuMTA0NjYsLjk3OTIyLC45NzU1MiwuOTQxNjUsLjk3NTUyLC45NDE2NSwuOTc1NTIsLjk0MTY1LC45MTYwMiwuOTE5ODEsLjg4NjQxLDEuMDI3NiwxLDEsLjg4NjQxLDEuMDI3NiwuODA1MjcsLjc4OTI5LC44MDUyNywuNzg5MjksLjgwNTI3LC43ODkyOSwuODA1MjcsLjc4OTI5LDEsMSwuOTYwODMsMS4wNTQwMywuOTU5MjMsMS4xNjg2MiwxLjAwMTM1LC45NzkyMiwxLjAwMTM1LC45NzkyMiwxLjAwMTM1LC45NzkyMiwxLjAwMTM1LC45NzkyMiwxLjAwMTM1LC45NzkyMiwxLjAwMTM1LC45NzkyMiwxLjA2Nzc3LDEuMDIxOTcsLjkxMTQyLC45Njc1MiwuOTExNDIsLjk5MzYxLC45NzE2OCwuOTkzNjEsLjk3MTY4LC45OTM2MSwuOTcxNjgsMS4yMzE5OSwxLjAzNiwuOTczNjMsMS4wNjU4NSwuOTQzODUsLjk2NzA1LC45NzU1MiwuOTQxNjUsMSwxLC45NjA4MywxLjEyNjEsMS4zMTgxOCwxLjMxODE4LDEuMzE4MTgsMS4zMTgxOCwxLjMxODE4LDEuMzE4MTgsMS4zMTgxOCwxLjMxODE4LDEuMzE4MTgsLjk1MTYxLDEuMjcxMjYsMS4wMDgxMSwuODMyODQsLjc3NzAyLC45OTEzNywuOTUyNTMsMS4wMzQ3LC44NjE0MiwxLjA3MjA1LDEuMTQyMzYsLjk3MzYzLC44OTcyMywuODY4NjksMS4wOTgxOCwuNzk0MjksLjk5MzYxLDEuMDU4MTUsLjk3NTUyLDEuMTQwNiwuOTAxMjgsMS4wNjY2MiwxLjA0Mzk2LDEuMTA2MTUsLjg0OTE4LC45NzU1MiwxLjA0Njk0LC45NDQzNiwuOTgwMTUsLjk2MDgzLC45MTE0MiwxLjAwMzU2LC45ODE3LDEuMDE5NDUsLjk4OTk5LDEuMTQwNiwuOTExNDIsMS4wNDk2MSwuOTg5OCwxLjAwNjM5LDEuMTQyMzYsMS4wNzUxNCwxLjA0OTYxLC45OTYwNywxLjAyODk3LDEuMDA4LC45ODk4LC45NTEzNCwxLjAwNjM5LDEuMTExMjEsMS4xNDIzNiwxLjAwNTE4LC45Nzk4MSwxLjAyMTg2LDEsMS4wODU3OCwuOTQxNjUsLjk5MzE0LC45ODM4NywuOTMwMjgsLjkzMzc3LDEuMzUxMjUsMS4wNzUxNCwxLjEwNjg3LC45MzQ5MSwxLjA0MjMyLDEuMDAzNTEsMS4xNDIzNiwxLjA3NTE0LC45NDE2NSwxLjA3NTE0LDEuMDAzNTEsLjc5NDI5LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMDkwOTcsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsLjkzNTAzLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45NjYwOSwxLDEsMSwxLDEsMSwxLjA2Nzc3LDEuMDIxOTcsMS4wNjc3NywxLjAyMTk3LDEuMDY3NzcsMS4wMjE5NywuOTExNDIsLjk2NzUyLDEsMS4yMTI2MSwuODk5MDMsMSwxLC43NTE1NSwxLjA0NzQ1LDEuMDQ3NDUsMS4wNDc0NSwxLjA0Mzk0LC45ODYzMywuOTg2MzMsLjk4NjMzLC43Mjk1OSwuNzI5NTksMS4yMDUwMiwuOTE0MDYsMS4yNjUxNCwxLjIyMiwxLjAyOTU2LDEuMDMzNzIsMS4wMzM3MiwuOTYwMzksMS4yNDYzMywxLDEuMDkxMjUsLjkzMzI3LDEuMDMzMzYsMS4xNjU0MSwxLjAzNiwxLDEsMSwuNzcxLDEsMSwxLjE1NTc0LDEuMTU1NzQsMS4xNTU3NCwxLjE1NTc0LC44NjM2NCwuOTQ0MzQsLjg2Mjc5LC45NDQzNCwuODYyMjQsMSwxLDEuMTY3OTgsMSwuOTYwODUsLjkwMDY4LDEuMjEyMzcsMS4xODQxNiwxLjEzOTA0LC42OTgyNSwuOTcxNiwyLjEwMzM5LDEuMjkwMDQsMS4yOTAwNCwxLjIxMzM5LDEuMjkwMDQsMS4yOTAwNCwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuNDI2MDMsMSwuOTk4NjIsLjk5ODYyLDEsLjg3MDI1LC44NzAyNSwuODcwMjUsLjg3MDI1LDEuMTg3NzUsMS40MjYwMywxLDEuNDI2MDMsMS40MjYwMywuOTk4NjIsMSwxLDEsMSwxLDEuMjg4NiwxLjA0MzE1LDEuMTUyOTYsMS4zNDE2MywxLDEsMSwxLjEzMjY5LDEuMTMyNjksMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLFluPXtsaW5lSGVpZ2h0OjEuMzMwMDgsbGluZUdhcDowfSxabj1bMS43NjczOCwxLDEsLjk4OTQ2LDEuMTQ3NjMsMS4wNTM2NSwxLjA2MjM0LC45NjkyNywuOTI1ODYsMS4xNTM3MywxLjE4NDE0LC45MTM0OSwuOTEzNDksMS4wNzQwMywxLjE3MzA4LC43ODM4MywxLjIwMDg4LC43ODM4MywxLjQyNTMxLC45NjkyNywuOTY5MjcsLjk2OTI3LC45NjkyNywuOTY5MjcsLjk2OTI3LC45NjkyNywuOTY5MjcsLjk2OTI3LC45NjkyNywuNzgzODMsLjc4MzgzLDEuMTczMDgsMS4xNzMwOCwxLjE3MzA4LC43NzM0OSwuOTQ1NjUsLjk0NzI5LC44NTk0NCwuODg1MDYsLjk4NTgsLjc0ODE3LC44MDAxNiwuODg0NDksLjk4MDM5LC45NTc4MiwuNjkyMzgsLjg5ODk4LC44MzIzMSwuOTgxODMsMS4wMzk4OSwuOTY5MjQsLjg2MjM3LC45NjkyNCwuODA1OTUsLjc0NTI0LC44NjA5MSwuOTU0MDIsLjk0MTQzLC45ODQ0OCwuODg1OCwuODMwODksLjkzMjg1LDEuMDk0OSwxLjM5MDE2LDEuMDk0OSwxLjQ1OTk0LC43NDYyNywxLjA0ODM5LC45NzQ1NCwuOTc0NTQsLjg3MjA3LC45NzQ1NCwuODc1MzMsMS4wNjE1MSwuOTc0NTQsMS4wMDE3NiwxLjE2NDg0LDEuMDgxMzIsLjk4MDQ3LDEuMTY0ODQsMS4wMjk4OSwxLjAxMDU0LC45NjIyNSwuOTc0NTQsLjk3NDU0LDEuMDY1OTgsLjc5MDA0LDEuMTYzNDQsMS4wMDM1MSwuOTQ2MjksLjk5NzMsLjkxMDE2LC45Njc3NywuOTA0MywuOTEwODIsLjkyNDgxLC45MTA4MiwxLjE3MzA4LC45NTc0OCwuOTY5MjcsLjk2OTI3LDEsLjk2OTI3LC45MjQ4MSwuODA1OTcsMS4wNDgzOSwxLjIzMzkzLDEuMTc4MSwuOTI0NSwxLjE3MzA4LDEuMjA4MDgsLjYzMjE4LC45NDI2MSwxLjI0ODIyLDEuMDk5NzEsMS4wOTk3MSwxLjA0ODM5LDEsLjg1MjczLC43ODAzMiwxLjA0ODM5LDEuMDk5NzEsMS4yMjMyNiwuOTI0NSwxLjA5ODM2LDEuMTM1MjUsMS4xNTIyMiwuNzA0MjQsLjk0NzI5LC45NDcyOSwuOTQ3MjksLjk0NzI5LC45NDcyOSwuOTQ3MjksLjg1NDk4LC44ODUwNiwuNzQ4MTcsLjc0ODE3LC43NDgxNywuNzQ4MTcsLjk1NzgyLC45NTc4MiwuOTU3ODIsLjk1NzgyLC45ODU4LDEuMDM5ODksLjk2OTI0LC45NjkyNCwuOTY5MjQsLjk2OTI0LC45NjkyNCwxLjE3MzA4LC45NjkyNCwuOTU0MDIsLjk1NDAyLC45NTQwMiwuOTU0MDIsLjgzMDg5LC44NjIzNywuODg0MDksLjk3NDU0LC45NzQ1NCwuOTc0NTQsLjk3NDU0LC45NzQ1NCwuOTc0NTQsLjkyOTE2LC44NzIwNywuODc1MzMsLjg3NTMzLC44NzUzMywuODc1MzMsLjkzMTQ2LC45MzE0NiwuOTMxNDYsLjkzMTQ2LC45Mzg1NCwxLjAxMDU0LC45NjIyNSwuOTYyMjUsLjk2MjI1LC45NjIyNSwuOTYyMjUsMS4yNDgyMiwuODc2MSwxLjAwMzUxLDEuMDAzNTEsMS4wMDM1MSwxLjAwMzUxLC45Njc3NywuOTc0NTQsLjk2Nzc3LC45NDcyOSwuOTc0NTQsLjk0NzI5LC45NzQ1NCwuOTQ3MjksLjk3NDU0LC44ODUwNiwuODcyMDcsLjg4NTA2LC44NzIwNywuODg1MDYsLjg3MjA3LC44ODUwNiwuODcyMDcsLjk4NTgsLjk1MzkxLC45ODU4LC45NzQ1NCwuNzQ4MTcsLjg3NTMzLC43NDgxNywuODc1MzMsLjc0ODE3LC44NzUzMywuNzQ4MTcsLjg3NTMzLC43NDgxNywuODc1MzMsLjg4NDQ5LC45NzQ1NCwuODg0NDksLjk3NDU0LC44ODQ0OSwuOTc0NTQsMSwxLC45ODAzOSwxLjAwMTc2LC45ODAzOSwxLjAwMTc2LC45NTc4MiwuOTMxNDYsLjk1NzgyLC45MzE0NiwuOTU3ODIsLjkzMTQ2LC45NTc4MiwxLjE2NDg0LC45NTc4MiwuOTMxNDYsLjg0NDIxLDEuMTI3NjEsLjY5MjM4LDEuMDgxMzIsMSwxLC45ODA0NywuODMyMzEsMS4xNjQ4NCwxLDEsLjg0NzIzLDEuMDQ4NjEsLjg0NzIzLC43ODc1NSwuODMyMzEsMS4yMzczNiwxLjAzOTg5LDEuMDEwNTQsMSwxLDEuMDM5ODksMS4wMTA1NCwuOTg1NywxLjAzODQ5LDEuMDEwNTQsLjk2OTI0LC45NjIyNSwuOTY5MjQsLjk2MjI1LC45NjkyNCwuOTYyMjUsLjkyMzgzLC45MDE3MSwuODA1OTUsMS4wNjU5OCwxLDEsLjgwNTk1LDEuMDY1OTgsLjc0NTI0LC43OTAwNCwuNzQ1MjQsLjc5MDA0LC43NDUyNCwuNzkwMDQsLjc0NTI0LC43OTAwNCwxLDEsLjg2MDkxLDEuMDI3NTksLjg1NzcxLDEuMTYzNDQsLjk1NDAyLDEuMDAzNTEsLjk1NDAyLDEuMDAzNTEsLjk1NDAyLDEuMDAzNTEsLjk1NDAyLDEuMDAzNTEsLjk1NDAyLDEuMDAzNTEsLjk1NDAyLDEuMDAzNTEsLjk4NDQ4LC45OTczLC44MzA4OSwuOTY3NzcsLjgzMDg5LC45MzI4NSwuOTA0MywuOTMyODUsLjkwNDMsLjkzMjg1LC45MDQzLDEuMzE4NjgsLjk2OTI3LC45NDcyOSwuOTc0NTQsLjg1NDk4LC45MjkxNiwuOTY5MjQsLjg3NjEsMSwxLC44NjA5MSwxLjE2MzQ0LDEuMDQ4MzksMS4wNDgzOSwxLjA0ODM5LDEuMDQ4MzksMS4wNDgzOSwxLjA0ODM5LDEuMDQ4MzksMS4wNDgzOSwxLjA0ODM5LC44MTk2NSwuODE5NjUsLjk0NzI5LC43ODAzMiwuNzEwMjIsLjkwODgzLC44NDE3MSwuOTk4NzcsLjc3NTk2LDEuMDU3MzQsMS4yLC45NDcyOSwuODU5NDQsLjgyNzkxLC45NjA3LC43NDgxNywuOTMyODUsLjk4MDM5LC45NjkyNCwuOTU3ODIsLjg5ODk4LC45ODMxNiwuOTgxODMsMS4wMzk4OSwuNzg2MTQsLjk2OTI0LC45NzY0MiwuODYyMzcsLjg2MDc1LC44NjA5MSwuODMwODksLjkwMDgyLC44ODU4LC45NzI5NiwxLjAxMjg0LC45NTc4MiwuODMwODksMS4wOTc2LDEuMDQsMS4wMzM0MiwxLjIsMS4wNjc1LDEuMDk3NiwuOTgyMDUsMS4wMzgwOSwxLjA1MDk3LDEuMDQsLjk1MzY0LDEuMDMzNDIsMS4wNTQwMSwxLjIsMS4wMjE0OCwxLjAxMTksMS4wNDcyNCwxLjAxMjcsMS4wMjczMiwuOTYyMjUsLjg5NjUsLjk3NzgzLC45MzU3NCwuOTQ4MTgsMS4zMDY3OSwxLjA2NzUsMS4xMTgyNiwuOTk4MjEsMS4wNTU3LDEuMDMyNiwxLjIsMS4wNjc1LC45NjIyNSwxLjA2NzUsMS4wMzI2LC43NDgxNywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjAzNzU0LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC44NzUzMywxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwuOTg3MDUsMSwxLDEsMSwxLDEsLjk4NDQ4LC45OTczLC45ODQ0OCwuOTk3MywuOTg0NDgsLjk5NzMsLjgzMDg5LC45Njc3NywxLDEuMjAwODgsLjg5OTAzLDEsMSwuNzUxNTUsLjk0OTQ1LC45NDk0NSwuOTQ5NDUsLjk0OTQ1LDEuMTIzMTcsMS4xMjMxNywxLjEyMzE3LC42NzYwMywuNjc2MDMsMS4xNTYyMSwuNzM1ODQsMS4yMTE5MSwxLjIyMTM1LDEuMDY0ODMsLjk0ODY4LC45NDg2OCwuOTU5OTYsMS4yNDYzMywxLDEuMDc0OTcsLjg3NzA5LC45NjkyNywxLjAxNDczLC45NjkyNywxLDEsMSwuNzcyOTUsMSwxLDEuMDk4MzYsMS4wOTgzNiwxLjA5ODM2LDEuMDE1MjIsLjg2MzIxLC45NDQzNCwuODY0OSwuOTQ0MzQsLjg2MTgyLDEsMSwxLjA4MywxLC45MTU3OCwuODY0MzgsMS4xNzMwOCwxLjE4NDE2LDEuMTQ1ODksLjY5ODI1LC45NzYyMiwxLjk2NzkxLDEuMjQ4MjIsMS4yNDgyMiwxLjE3MzA4LDEuMjQ4MjIsMS4yNDgyMiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuNDI2MDMsMSwuOTk4NjIsLjk5ODYyLDEsLjg3MDI1LC44NzAyNSwuODcwMjUsLjg3MDI1LDEuMTc5ODQsMS40MjYwMywxLDEuNDI2MDMsMS40MjYwMywuOTk4NjIsMSwxLDEsMSwxLDEuMjg4NiwxLjA0MzE1LDEuMTUyOTYsMS4zNDE2MywxLDEsMSwxLjEwNzQyLDEuMTA3NDIsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdLFFuPXtsaW5lSGVpZ2h0OjEuMzMwMDgsbGluZUdhcDowfSxlaT1bMS43NjczOCwxLDEsLjk4NTk0LDEuMDIyODUsMS4xMDQ1NCwxLjA2MjM0LC45NjkyNywuOTIwMzcsMS4xOTk4NSwxLjIwNDYsLjkwNjE2LC45MDYxNiwxLjA3MTUyLDEuMTcxNCwuNzgwMzIsMS4yMDA4OCwuNzgwMzIsMS40MDI0NiwuOTY5MjcsLjk2OTI3LC45NjkyNywuOTY5MjcsLjk2OTI3LC45NjkyNywuOTY5MjcsLjk2OTI3LC45NjkyNywuOTY5MjcsLjc4MDMyLC43ODAzMiwxLjE3MTQsMS4xNzE0LDEuMTcxNCwuODA1OTcsLjk0MDg0LC45NjcwNiwuODU5NDQsLjg1NzM0LC45NzA5MywuNzU4NDIsLjc5OTM2LC44ODE5OCwuOTgzMSwuOTU3ODIsLjcxMzg3LC44Njk2OSwuODQ2MzYsMS4wNzc5NiwxLjAzNTg0LC45NjkyNCwuODM5NjgsLjk2OTI0LC44MjgyNiwuNzk2NDksLjg1NzcxLC45NTEzMiwuOTMxMTksLjk4OTY1LC44ODQzMywuODI4NywuOTMzNjUsMS4wODYxMiwxLjM2MzgsMS4wODYxMiwxLjQ1Nzg2LC43NDYyNywuODA0OTksLjkxNDg0LDEuMDU3MDcsLjkyMzgzLDEuMDU4ODIsLjk0MDMsMS4xMjY1NCwxLjA1ODgyLDEuMDE3NTYsMS4wOTAxMSwxLjA5MDExLC45OTQxNCwxLjA5MDExLDEuMDM0LDEuMDE3NTYsMS4wNTM1NiwxLjA1NzA3LDEuMDU4ODIsMS4wNDM5OSwuODQ4NjMsMS4yMTk2OCwxLjAxNzU2LC45NTgwMSwxLjAwMDY4LC45MTc5NywuOTY3NzcsLjkwNDMsLjkwMzUxLC45MjEwNSwuOTAzNTEsMS4xNzE0LC44NTMzNywuOTY5MjcsLjk2OTI3LC45OTkxMiwuOTY5MjcsLjkyMTA1LC44MDU5NywxLjI0MzQsMS4yMDgwOCwxLjA1OTM3LC45MDk1NywxLjE3MTQsMS4yMDgwOCwuNzUxNTUsLjk0MjYxLDEuMjQ2NDQsMS4wOTk3MSwxLjA5OTcxLC44NDc1MSwxLC44NTI3MywuNzgwMzIsLjYxNTg0LDEuMDU0MjUsMS4xNzkxNCwuOTA5NTcsMS4wODY2NSwxLjExNTkzLDEuMTQxNjksLjczMzgxLC45NjcwNiwuOTY3MDYsLjk2NzA2LC45NjcwNiwuOTY3MDYsLjk2NzA2LC44NjAzNSwuODU3MzQsLjc1ODQyLC43NTg0MiwuNzU4NDIsLjc1ODQyLC45NTc4MiwuOTU3ODIsLjk1NzgyLC45NTc4MiwuOTcwOTMsMS4wMzU4NCwuOTY5MjQsLjk2OTI0LC45NjkyNCwuOTY5MjQsLjk2OTI0LDEuMTcxNCwuOTY5MjQsLjk1MTMyLC45NTEzMiwuOTUxMzIsLjk1MTMyLC44Mjg3LC44Mzk2OCwuODkwNDksLjkxNDg0LC45MTQ4NCwuOTE0ODQsLjkxNDg0LC45MTQ4NCwuOTE0ODQsLjkzNTc1LC45MjM4MywuOTQwMywuOTQwMywuOTQwMywuOTQwMywuODcxNywuODcxNywuODcxNywuODcxNywxLjAwNTI3LDEuMDE3NTYsMS4wNTM1NiwxLjA1MzU2LDEuMDUzNTYsMS4wNTM1NiwxLjA1MzU2LDEuMjQ2NDQsLjk1OTIzLDEuMDE3NTYsMS4wMTc1NiwxLjAxNzU2LDEuMDE3NTYsLjk2Nzc3LDEuMDU3MDcsLjk2Nzc3LC45NjcwNiwuOTE0ODQsLjk2NzA2LC45MTQ4NCwuOTY3MDYsLjkxNDg0LC44NTczNCwuOTIzODMsLjg1NzM0LC45MjM4MywuODU3MzQsLjkyMzgzLC44NTczNCwuOTIzODMsLjk3MDkzLDEuMDk2OSwuOTcwOTMsMS4wNTg4MiwuNzU4NDIsLjk0MDMsLjc1ODQyLC45NDAzLC43NTg0MiwuOTQwMywuNzU4NDIsLjk0MDMsLjc1ODQyLC45NDAzLC44ODE5OCwxLjA1ODgyLC44ODE5OCwxLjA1ODgyLC44ODE5OCwxLjA1ODgyLDEsMSwuOTgzMSwxLjAxNzU2LC45ODMxLDEuMDE3NTYsLjk1NzgyLC44NzE3LC45NTc4MiwuODcxNywuOTU3ODIsLjg3MTcsLjk1NzgyLDEuMDkwMTEsLjk1NzgyLC44NzE3LC44NDc4NCwxLjExNTUxLC43MTM4NywxLjA5MDExLDEsMSwuOTk0MTQsLjg0NjM2LDEuMDkwMTEsMSwxLC44NDYzNiwxLjA1MzYsLjg0NjM2LC45NDI5OCwuODQ2MzYsMS4yMzI5NywxLjAzNTg0LDEuMDE3NTYsMSwxLDEuMDM1ODQsMS4wMTc1NiwxLjAwMzIzLDEuMDM0NDQsMS4wMTc1NiwuOTY5MjQsMS4wNTM1NiwuOTY5MjQsMS4wNTM1NiwuOTY5MjQsMS4wNTM1NiwuOTMwNjYsLjk4MjkzLC44MjgyNiwxLjA0Mzk5LDEsMSwuODI4MjYsMS4wNDM5OSwuNzk2NDksLjg0ODYzLC43OTY0OSwuODQ4NjMsLjc5NjQ5LC44NDg2MywuNzk2NDksLjg0ODYzLDEsMSwuODU3NzEsMS4xNzMxOCwuODU3NzEsMS4yMTk2OCwuOTUxMzIsMS4wMTc1NiwuOTUxMzIsMS4wMTc1NiwuOTUxMzIsMS4wMTc1NiwuOTUxMzIsMS4wMTc1NiwuOTUxMzIsMS4wMTc1NiwuOTUxMzIsMS4wMTc1NiwuOTg5NjUsMS4wMDA2OCwuODI4NywuOTY3NzcsLjgyODcsLjkzMzY1LC45MDQzLC45MzM2NSwuOTA0MywuOTMzNjUsLjkwNDMsMS4wODU3MSwuOTY5MjcsLjk2NzA2LC45MTQ4NCwuODYwMzUsLjkzNTc1LC45NjkyNCwuOTU5MjMsMSwxLC44NTc3MSwxLjIxOTY4LDEuMTE0MzcsMS4xMTQzNywuOTMxMDksLjkxMjAyLC42MDQxMSwuODQxNjQsLjU1NTcyLDEuMDExNzMsLjk3MzYxLC44MTgxOCwuODE4MTgsLjk2NjM1LC43ODAzMiwuNzI3MjcsLjkyMzY2LC45ODYwMSwxLjAzNDA1LC43Nzk2OCwxLjA5Nzk5LDEuMiwuOTY3MDYsLjg1OTQ0LC44NTYzOCwuOTY0OTEsLjc1ODQyLC45MzM2NSwuOTgzMSwuOTY5MjQsLjk1NzgyLC44Njk2OSwuOTQxNTIsMS4wNzc5NiwxLjAzNTg0LC43ODQzNywuOTY5MjQsLjk4NzE1LC44Mzk2OCwuODM0OTEsLjg1NzcxLC44Mjg3LC45NDQ5MiwuODg0MzMsLjkyODcsMS4wMDk4LC45NTc4MiwuODI4NywxLjA2MjUsLjk4MjQ4LDEuMDM0MjQsMS4yLDEuMDEwNzEsMS4wNjI1LC45NTI0NiwxLjAzODA5LDEuMDQ5MTIsLjk4MjQ4LDEuMDAyMjEsMS4wMzQyNCwxLjA1NDQzLDEuMiwxLjA0Nzg1LC45OTYwOSwxLjAwMTY5LDEuMDUxNzYsLjk5MzQ2LDEuMDUzNTYsLjkwODcsMS4wMzAwNCwuOTU1NDIsLjkzMTE3LDEuMjMzNjIsMS4wMTA3MSwxLjA3ODMxLDEuMDI1MTIsMS4wNTIwNSwxLjAzNTAyLDEuMiwxLjAxMDcxLDEuMDUzNTYsMS4wMTA3MSwxLjAzNTAyLC43NTg0MiwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLjAzNzE5LDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLC45NDAzLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEuMDQwMjEsMSwxLDEsMSwxLDEsLjk4OTY1LDEuMDAwNjgsLjk4OTY1LDEuMDAwNjgsLjk4OTY1LDEuMDAwNjgsLjgyODcsLjk2Nzc3LDEsMS4yMDA4OCwuODk5MDMsMSwxLC43NTE1NSwxLjAzMDc3LDEuMDMwNzcsMS4wMzA3NywxLjAzMDc3LDEuMTMxOTYsMS4xMzE5NiwxLjEzMTk2LC42NzQyOCwuNjc0MjgsMS4xNjAzOSwuNzMyOTEsMS4yMDk5NiwxLjIyMTM1LDEuMDY0ODMsLjk0ODY4LC45NDg2OCwuOTU5OTYsMS4yNDYzMywxLDEuMDc0OTcsLjg3Nzk2LC45NjkyNywxLjAxNTE4LC45NjkyNywxLDEsMSwuNzcyOTUsMSwxLDEuMTA1MzksMS4xMDUzOSwxLjExMzU4LDEuMDY5NjcsLjg2Mjc5LC45NDQzNCwuODYyNzksLjk0NDM0LC44NjE4MiwxLDEsMS4wODMsMSwuOTE1NzgsLjg2NTA3LDEuMTcxNCwxLjE4NDE2LDEuMTQ1ODksLjY5ODI1LC45NzYyMiwxLjk2OTcsMS4yNDgyMiwxLjI0ODIyLDEuMTcyMzgsMS4yNDgyMiwxLjI0ODIyLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMS40MjYwMywxLC45OTg2MiwuOTk4NjIsMSwuODcwMjUsLjg3MDI1LC44NzAyNSwuODcwMjUsMS4xODA4MywxLjQyNjAzLDEsMS40MjYwMywxLjQyNjAzLC45OTg2MiwxLDEsMSwxLDEsMS4yODg2LDEuMDQzMTUsMS4xNTI5NiwxLjM0MTYzLDEsMSwxLDEuMTA5MzgsMS4xMDkzOCwxLDEsMSwxLjA1NDI1LDEuMDk5NzEsMS4wOTk3MSwxLjA5OTcxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0sdGk9e2xpbmVIZWlnaHQ6MS4zMzAwOCxsaW5lR2FwOjB9LHJpPWdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbihlKXtlWyJNeXJpYWRQcm8tUmVndWxhciJdPWVbIlBkZkpTLUZhbGxiYWNrLVJlZ3VsYXIiXT17bmFtZToiTGliZXJhdGlvblNhbnMtUmVndWxhciIsZmFjdG9yczpHbixiYXNlV2lkdGhzOkxuLGJhc2VNYXBwaW5nOmpuLG1ldHJpY3M6JG59O2VbIk15cmlhZFByby1Cb2xkIl09ZVsiUGRmSlMtRmFsbGJhY2stQm9sZCJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1Cb2xkIixmYWN0b3JzOlVuLGJhc2VXaWR0aHM6Qm4sYmFzZU1hcHBpbmc6Um4sbWV0cmljczpxbn07ZVsiTXlyaWFkUHJvLUl0Il09ZVsiTXlyaWFkUHJvLUl0YWxpYyJdPWVbIlBkZkpTLUZhbGxiYWNrLUl0YWxpYyJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLGZhY3RvcnM6V24sYmFzZVdpZHRoczpQbixiYXNlTWFwcGluZzpfbixtZXRyaWNzOnpufTtlWyJNeXJpYWRQcm8tQm9sZEl0Il09ZVsiTXlyaWFkUHJvLUJvbGRJdGFsaWMiXT1lWyJQZGZKUy1GYWxsYmFjay1Cb2xkSXRhbGljIl09e25hbWU6IkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLGZhY3RvcnM6WG4sYmFzZVdpZHRoczpFbixiYXNlTWFwcGluZzpObixtZXRyaWNzOkhufTtlLkFyaWFsTVQ9ZS5BcmlhbD1lWyJBcmlhbC1SZWd1bGFyIl09e25hbWU6IkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLGJhc2VXaWR0aHM6TG4sYmFzZU1hcHBpbmc6am59O2VbIkFyaWFsLUJvbGRNVCJdPWVbIkFyaWFsLUJvbGQiXT17bmFtZToiTGliZXJhdGlvblNhbnMtQm9sZCIsYmFzZVdpZHRoczpCbixiYXNlTWFwcGluZzpSbn07ZVsiQXJpYWwtSXRhbGljTVQiXT1lWyJBcmlhbC1JdGFsaWMiXT17bmFtZToiTGliZXJhdGlvblNhbnMtSXRhbGljIixiYXNlV2lkdGhzOlBuLGJhc2VNYXBwaW5nOl9ufTtlWyJBcmlhbC1Cb2xkSXRhbGljTVQiXT1lWyJBcmlhbC1Cb2xkSXRhbGljIl09e25hbWU6IkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLGJhc2VXaWR0aHM6RW4sYmFzZU1hcHBpbmc6Tm59O2VbIkNhbGlicmktUmVndWxhciJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIixmYWN0b3JzOkFuLGJhc2VXaWR0aHM6TG4sYmFzZU1hcHBpbmc6am4sbWV0cmljczprbn07ZVsiQ2FsaWJyaS1Cb2xkIl09e25hbWU6IkxpYmVyYXRpb25TYW5zLUJvbGQiLGZhY3RvcnM6bW4sYmFzZVdpZHRoczpCbixiYXNlTWFwcGluZzpSbixtZXRyaWNzOmJufTtlWyJDYWxpYnJpLUl0YWxpYyJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLGZhY3RvcnM6eG4sYmFzZVdpZHRoczpQbixiYXNlTWFwcGluZzpfbixtZXRyaWNzOlNufTtlWyJDYWxpYnJpLUJvbGRJdGFsaWMiXT17bmFtZToiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsZmFjdG9yczp5bixiYXNlV2lkdGhzOkVuLGJhc2VNYXBwaW5nOk5uLG1ldHJpY3M6d259O2VbIlNlZ29ldWktUmVndWxhciJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIixmYWN0b3JzOmVpLGJhc2VXaWR0aHM6TG4sYmFzZU1hcHBpbmc6am4sbWV0cmljczp0aX07ZVsiU2Vnb2V1aS1Cb2xkIl09e25hbWU6IkxpYmVyYXRpb25TYW5zLUJvbGQiLGZhY3RvcnM6Vm4sYmFzZVdpZHRoczpCbixiYXNlTWFwcGluZzpSbixtZXRyaWNzOktufTtlWyJTZWdvZXVpLUl0YWxpYyJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLGZhY3RvcnM6Wm4sYmFzZVdpZHRoczpQbixiYXNlTWFwcGluZzpfbixtZXRyaWNzOlFufTtlWyJTZWdvZXVpLUJvbGRJdGFsaWMiXT17bmFtZToiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsZmFjdG9yczpKbixiYXNlV2lkdGhzOkVuLGJhc2VNYXBwaW5nOk5uLG1ldHJpY3M6WW59O2VbIkhlbHZldGljYS1SZWd1bGFyIl09ZS5IZWx2ZXRpY2E9e25hbWU6IkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLGZhY3RvcnM6TW4sYmFzZVdpZHRoczpMbixiYXNlTWFwcGluZzpqbixtZXRyaWNzOkRufTtlWyJIZWx2ZXRpY2EtQm9sZCJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1Cb2xkIixmYWN0b3JzOkNuLGJhc2VXaWR0aHM6Qm4sYmFzZU1hcHBpbmc6Um4sbWV0cmljczp2bn07ZVsiSGVsdmV0aWNhLUl0YWxpYyJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLGZhY3RvcnM6VG4sYmFzZVdpZHRoczpQbixiYXNlTWFwcGluZzpfbixtZXRyaWNzOk9ufTtlWyJIZWx2ZXRpY2EtQm9sZEl0YWxpYyJdPXtuYW1lOiJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIixmYWN0b3JzOkZuLGJhc2VXaWR0aHM6RW4sYmFzZU1hcHBpbmc6Tm4sbWV0cmljczpJbn19KTtmdW5jdGlvbiBnZXRYZmFGb250TmFtZShlKXtjb25zdCB0PW5vcm1hbGl6ZUZvbnROYW1lKGUpO3JldHVybiByaSgpW3RdfWZ1bmN0aW9uIGdldFhmYUZvbnREaWN0KGUpe2NvbnN0IHQ9ZnVuY3Rpb24gZ2V0WGZhRm9udFdpZHRocyhlKXtjb25zdCB0PWdldFhmYUZvbnROYW1lKGUpO2lmKCF0KXJldHVybiBudWxsO2NvbnN0e2Jhc2VXaWR0aHM6cixiYXNlTWFwcGluZzphLGZhY3RvcnM6bn09dCxpPW4/ci5tYXAoKGUsdCk9PmUqblt0XSk6cjtsZXQgcyxvPS0yO2NvbnN0IGM9W107Zm9yKGNvbnN0W2UsdF1vZiBhLm1hcCgoZSx0KT0+W2UsdF0pLnNvcnQoKFtlXSxbdF0pPT5lLXQpKWlmKC0xIT09ZSlpZihlPT09bysxKXtzLnB1c2goaVt0XSk7bys9MX1lbHNle289ZTtzPVtpW3RdXTtjLnB1c2goZSxzKX1yZXR1cm4gY30oZSkscj1uZXcgRGljdChudWxsKTtyLnNldCgiQmFzZUZvbnQiLE5hbWUuZ2V0KGUpKTtyLnNldCgiVHlwZSIsTmFtZS5nZXQoIkZvbnQiKSk7ci5zZXQoIlN1YnR5cGUiLE5hbWUuZ2V0KCJDSURGb250VHlwZTIiKSk7ci5zZXQoIkVuY29kaW5nIixOYW1lLmdldCgiSWRlbnRpdHktSCIpKTtyLnNldCgiQ0lEVG9HSURNYXAiLE5hbWUuZ2V0KCJJZGVudGl0eSIpKTtyLnNldCgiVyIsdCk7ci5zZXQoIkZpcnN0Q2hhciIsdFswXSk7ci5zZXQoIkxhc3RDaGFyIix0LmF0KC0yKSt0LmF0KC0xKS5sZW5ndGgtMSk7Y29uc3QgYT1uZXcgRGljdChudWxsKTtyLnNldCgiRm9udERlc2NyaXB0b3IiLGEpO2NvbnN0IG49bmV3IERpY3QobnVsbCk7bi5zZXQoIk9yZGVyaW5nIiwiSWRlbnRpdHkiKTtuLnNldCgiUmVnaXN0cnkiLCJBZG9iZSIpO24uc2V0KCJTdXBwbGVtZW50IiwwKTtyLnNldCgiQ0lEU3lzdGVtSW5mbyIsbik7cmV0dXJuIHJ9Y2xhc3MgUG9zdFNjcmlwdFBhcnNlcntjb25zdHJ1Y3RvcihlKXt0aGlzLmxleGVyPWU7dGhpcy5vcGVyYXRvcnM9W107dGhpcy50b2tlbj1udWxsO3RoaXMucHJldj1udWxsfW5leHRUb2tlbigpe3RoaXMucHJldj10aGlzLnRva2VuO3RoaXMudG9rZW49dGhpcy5sZXhlci5nZXRUb2tlbigpfWFjY2VwdChlKXtpZih0aGlzLnRva2VuLnR5cGU9PT1lKXt0aGlzLm5leHRUb2tlbigpO3JldHVybiEwfXJldHVybiExfWV4cGVjdChlKXtpZih0aGlzLmFjY2VwdChlKSlyZXR1cm4hMDt0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVuZXhwZWN0ZWQgc3ltYm9sOiBmb3VuZCAke3RoaXMudG9rZW4udHlwZX0gZXhwZWN0ZWQgJHtlfS5gKX1wYXJzZSgpe3RoaXMubmV4dFRva2VuKCk7dGhpcy5leHBlY3QoYWkuTEJSQUNFKTt0aGlzLnBhcnNlQmxvY2soKTt0aGlzLmV4cGVjdChhaS5SQlJBQ0UpO3JldHVybiB0aGlzLm9wZXJhdG9yc31wYXJzZUJsb2NrKCl7Zm9yKDs7KWlmKHRoaXMuYWNjZXB0KGFpLk5VTUJFUikpdGhpcy5vcGVyYXRvcnMucHVzaCh0aGlzLnByZXYudmFsdWUpO2Vsc2UgaWYodGhpcy5hY2NlcHQoYWkuT1BFUkFUT1IpKXRoaXMub3BlcmF0b3JzLnB1c2godGhpcy5wcmV2LnZhbHVlKTtlbHNle2lmKCF0aGlzLmFjY2VwdChhaS5MQlJBQ0UpKXJldHVybjt0aGlzLnBhcnNlQ29uZGl0aW9uKCl9fXBhcnNlQ29uZGl0aW9uKCl7Y29uc3QgZT10aGlzLm9wZXJhdG9ycy5sZW5ndGg7dGhpcy5vcGVyYXRvcnMucHVzaChudWxsLG51bGwpO3RoaXMucGFyc2VCbG9jaygpO3RoaXMuZXhwZWN0KGFpLlJCUkFDRSk7aWYodGhpcy5hY2NlcHQoYWkuSUYpKXt0aGlzLm9wZXJhdG9yc1tlXT10aGlzLm9wZXJhdG9ycy5sZW5ndGg7dGhpcy5vcGVyYXRvcnNbZSsxXT0ianoifWVsc2V7aWYoIXRoaXMuYWNjZXB0KGFpLkxCUkFDRSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQUyBGdW5jdGlvbjogZXJyb3IgcGFyc2luZyBjb25kaXRpb25hbC4iKTt7Y29uc3QgdD10aGlzLm9wZXJhdG9ycy5sZW5ndGg7dGhpcy5vcGVyYXRvcnMucHVzaChudWxsLG51bGwpO2NvbnN0IHI9dGhpcy5vcGVyYXRvcnMubGVuZ3RoO3RoaXMucGFyc2VCbG9jaygpO3RoaXMuZXhwZWN0KGFpLlJCUkFDRSk7dGhpcy5leHBlY3QoYWkuSUZFTFNFKTt0aGlzLm9wZXJhdG9yc1t0XT10aGlzLm9wZXJhdG9ycy5sZW5ndGg7dGhpcy5vcGVyYXRvcnNbdCsxXT0iaiI7dGhpcy5vcGVyYXRvcnNbZV09cjt0aGlzLm9wZXJhdG9yc1tlKzFdPSJqeiJ9fX19Y29uc3QgYWk9e0xCUkFDRTowLFJCUkFDRToxLE5VTUJFUjoyLE9QRVJBVE9SOjMsSUY6NCxJRkVMU0U6NX07Y2xhc3MgUG9zdFNjcmlwdFRva2Vue3N0YXRpYyBnZXQgb3BDYWNoZSgpe3JldHVybiBzaGFkb3codGhpcywib3BDYWNoZSIsT2JqZWN0LmNyZWF0ZShudWxsKSl9Y29uc3RydWN0b3IoZSx0KXt0aGlzLnR5cGU9ZTt0aGlzLnZhbHVlPXR9c3RhdGljIGdldE9wZXJhdG9yKGUpe3JldHVybiBQb3N0U2NyaXB0VG9rZW4ub3BDYWNoZVtlXXx8PW5ldyBQb3N0U2NyaXB0VG9rZW4oYWkuT1BFUkFUT1IsZSl9c3RhdGljIGdldCBMQlJBQ0UoKXtyZXR1cm4gc2hhZG93KHRoaXMsIkxCUkFDRSIsbmV3IFBvc3RTY3JpcHRUb2tlbihhaS5MQlJBQ0UsInsiKSl9c3RhdGljIGdldCBSQlJBQ0UoKXtyZXR1cm4gc2hhZG93KHRoaXMsIlJCUkFDRSIsbmV3IFBvc3RTY3JpcHRUb2tlbihhaS5SQlJBQ0UsIn0iKSl9c3RhdGljIGdldCBJRigpe3JldHVybiBzaGFkb3codGhpcywiSUYiLG5ldyBQb3N0U2NyaXB0VG9rZW4oYWkuSUYsIklGIikpfXN0YXRpYyBnZXQgSUZFTFNFKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJJRkVMU0UiLG5ldyBQb3N0U2NyaXB0VG9rZW4oYWkuSUZFTFNFLCJJRkVMU0UiKSl9fWNsYXNzIFBvc3RTY3JpcHRMZXhlcntjb25zdHJ1Y3RvcihlKXt0aGlzLnN0cmVhbT1lO3RoaXMubmV4dENoYXIoKTt0aGlzLnN0ckJ1Zj1bXX1uZXh0Q2hhcigpe3JldHVybiB0aGlzLmN1cnJlbnRDaGFyPXRoaXMuc3RyZWFtLmdldEJ5dGUoKX1nZXRUb2tlbigpe2xldCBlPSExLHQ9dGhpcy5jdXJyZW50Q2hhcjtmb3IoOzspe2lmKHQ8MClyZXR1cm4gc3I7aWYoZSkxMCE9PXQmJjEzIT09dHx8KGU9ITEpO2Vsc2UgaWYoMzc9PT10KWU9ITA7ZWxzZSBpZighaXNXaGl0ZVNwYWNlKHQpKWJyZWFrO3Q9dGhpcy5uZXh0Q2hhcigpfXN3aXRjaCgwfHQpe2Nhc2UgNDg6Y2FzZSA0OTpjYXNlIDUwOmNhc2UgNTE6Y2FzZSA1MjpjYXNlIDUzOmNhc2UgNTQ6Y2FzZSA1NTpjYXNlIDU2OmNhc2UgNTc6Y2FzZSA0MzpjYXNlIDQ1OmNhc2UgNDY6cmV0dXJuIG5ldyBQb3N0U2NyaXB0VG9rZW4oYWkuTlVNQkVSLHRoaXMuZ2V0TnVtYmVyKCkpO2Nhc2UgMTIzOnRoaXMubmV4dENoYXIoKTtyZXR1cm4gUG9zdFNjcmlwdFRva2VuLkxCUkFDRTtjYXNlIDEyNTp0aGlzLm5leHRDaGFyKCk7cmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5SQlJBQ0V9Y29uc3Qgcj10aGlzLnN0ckJ1ZjtyLmxlbmd0aD0wO3JbMF09U3RyaW5nLmZyb21DaGFyQ29kZSh0KTtmb3IoOyh0PXRoaXMubmV4dENoYXIoKSk+PTAmJih0Pj02NSYmdDw9OTB8fHQ+PTk3JiZ0PD0xMjIpOylyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSh0KSk7Y29uc3QgYT1yLmpvaW4oIiIpO3N3aXRjaChhLnRvTG93ZXJDYXNlKCkpe2Nhc2UiaWYiOnJldHVybiBQb3N0U2NyaXB0VG9rZW4uSUY7Y2FzZSJpZmVsc2UiOnJldHVybiBQb3N0U2NyaXB0VG9rZW4uSUZFTFNFO2RlZmF1bHQ6cmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5nZXRPcGVyYXRvcihhKX19Z2V0TnVtYmVyKCl7bGV0IGU9dGhpcy5jdXJyZW50Q2hhcjtjb25zdCB0PXRoaXMuc3RyQnVmO3QubGVuZ3RoPTA7dFswXT1TdHJpbmcuZnJvbUNoYXJDb2RlKGUpO2Zvcig7KGU9dGhpcy5uZXh0Q2hhcigpKT49MCYmKGU+PTQ4JiZlPD01N3x8NDU9PT1lfHw0Nj09PWUpOyl0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShlKSk7Y29uc3Qgcj1wYXJzZUZsb2F0KHQuam9pbigiIikpO2lmKGlzTmFOKHIpKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBmbG9hdGluZyBwb2ludCBudW1iZXI6ICR7cn1gKTtyZXR1cm4gcn19Y2xhc3MgQmFzZUxvY2FsQ2FjaGV7Y29uc3RydWN0b3IoZSl7dGhpcy5fb25seVJlZnM9ITA9PT1lPy5vbmx5UmVmcztpZighdGhpcy5fb25seVJlZnMpe3RoaXMuX25hbWVSZWZNYXA9bmV3IE1hcDt0aGlzLl9pbWFnZU1hcD1uZXcgTWFwfXRoaXMuX2ltYWdlQ2FjaGU9bmV3IFJlZlNldENhY2hlfWdldEJ5TmFtZShlKXt0aGlzLl9vbmx5UmVmcyYmdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBgZ2V0QnlOYW1lYCBtZXRob2QuIik7Y29uc3QgdD10aGlzLl9uYW1lUmVmTWFwLmdldChlKTtyZXR1cm4gdD90aGlzLmdldEJ5UmVmKHQpOnRoaXMuX2ltYWdlTWFwLmdldChlKXx8bnVsbH1nZXRCeVJlZihlKXtyZXR1cm4gdGhpcy5faW1hZ2VDYWNoZS5nZXQoZSl8fG51bGx9c2V0KGUsdCxyKXt1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBzZXRgIGNhbGxlZC4iKX19Y2xhc3MgTG9jYWxJbWFnZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGV7c2V0KGUsdD1udWxsLHIpe2lmKCJzdHJpbmciIT10eXBlb2YgZSl0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7aWYodCl7aWYodGhpcy5faW1hZ2VDYWNoZS5oYXModCkpcmV0dXJuO3RoaXMuX25hbWVSZWZNYXAuc2V0KGUsdCk7dGhpcy5faW1hZ2VDYWNoZS5wdXQodCxyKX1lbHNlIHRoaXMuX2ltYWdlTWFwLmhhcyhlKXx8dGhpcy5faW1hZ2VNYXAuc2V0KGUscil9fWNsYXNzIExvY2FsQ29sb3JTcGFjZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGV7c2V0KGU9bnVsbCx0PW51bGwscil7aWYoInN0cmluZyIhPXR5cGVvZiBlJiYhdCl0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJuYW1lIiBhbmQvb3IgInJlZiIgYXJndW1lbnQuJyk7aWYodCl7aWYodGhpcy5faW1hZ2VDYWNoZS5oYXModCkpcmV0dXJuO251bGwhPT1lJiZ0aGlzLl9uYW1lUmVmTWFwLnNldChlLHQpO3RoaXMuX2ltYWdlQ2FjaGUucHV0KHQscil9ZWxzZSB0aGlzLl9pbWFnZU1hcC5oYXMoZSl8fHRoaXMuX2ltYWdlTWFwLnNldChlLHIpfX1jbGFzcyBMb2NhbEZ1bmN0aW9uQ2FjaGUgZXh0ZW5kcyBCYXNlTG9jYWxDYWNoZXtjb25zdHJ1Y3RvcihlKXtzdXBlcih7b25seVJlZnM6ITB9KX1zZXQoZT1udWxsLHQscil7aWYoIXQpdGhyb3cgbmV3IEVycm9yKCdMb2NhbEZ1bmN0aW9uQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7dGhpcy5faW1hZ2VDYWNoZS5oYXModCl8fHRoaXMuX2ltYWdlQ2FjaGUucHV0KHQscil9fWNsYXNzIExvY2FsR1N0YXRlQ2FjaGUgZXh0ZW5kcyBCYXNlTG9jYWxDYWNoZXtzZXQoZSx0PW51bGwscil7aWYoInN0cmluZyIhPXR5cGVvZiBlKXRocm93IG5ldyBFcnJvcignTG9jYWxHU3RhdGVDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7aWYodCl7aWYodGhpcy5faW1hZ2VDYWNoZS5oYXModCkpcmV0dXJuO3RoaXMuX25hbWVSZWZNYXAuc2V0KGUsdCk7dGhpcy5faW1hZ2VDYWNoZS5wdXQodCxyKX1lbHNlIHRoaXMuX2ltYWdlTWFwLmhhcyhlKXx8dGhpcy5faW1hZ2VNYXAuc2V0KGUscil9fWNsYXNzIExvY2FsVGlsaW5nUGF0dGVybkNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGV7Y29uc3RydWN0b3IoZSl7c3VwZXIoe29ubHlSZWZzOiEwfSl9c2V0KGU9bnVsbCx0LHIpe2lmKCF0KXRocm93IG5ldyBFcnJvcignTG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7dGhpcy5faW1hZ2VDYWNoZS5oYXModCl8fHRoaXMuX2ltYWdlQ2FjaGUucHV0KHQscil9fWNsYXNzIFJlZ2lvbmFsSW1hZ2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hle2NvbnN0cnVjdG9yKGUpe3N1cGVyKHtvbmx5UmVmczohMH0pfXNldChlPW51bGwsdCxyKXtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ1JlZ2lvbmFsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAicmVmIiBhcmd1bWVudC4nKTt0aGlzLl9pbWFnZUNhY2hlLmhhcyh0KXx8dGhpcy5faW1hZ2VDYWNoZS5wdXQodCxyKX19Y2xhc3MgR2xvYmFsQ29sb3JTcGFjZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGV7Y29uc3RydWN0b3IoZSl7c3VwZXIoe29ubHlSZWZzOiEwfSl9c2V0KGU9bnVsbCx0LHIpe2lmKCF0KXRocm93IG5ldyBFcnJvcignR2xvYmFsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJyZWYiIGFyZ3VtZW50LicpO3RoaXMuX2ltYWdlQ2FjaGUuaGFzKHQpfHx0aGlzLl9pbWFnZUNhY2hlLnB1dCh0LHIpfWNsZWFyKCl7dGhpcy5faW1hZ2VDYWNoZS5jbGVhcigpfX1jbGFzcyBHbG9iYWxJbWFnZUNhY2hle3N0YXRpYyBOVU1fUEFHRVNfVEhSRVNIT0xEPTI7c3RhdGljIE1JTl9JTUFHRVNfVE9fQ0FDSEU9MTA7c3RhdGljIE1BWF9CWVRFX1NJWkU9NWU3OyNIPW5ldyBSZWZTZXQ7Y29uc3RydWN0b3IoKXt0aGlzLl9yZWZDYWNoZT1uZXcgUmVmU2V0Q2FjaGU7dGhpcy5faW1hZ2VDYWNoZT1uZXcgUmVmU2V0Q2FjaGV9Z2V0I1coKXtsZXQgZT0wO2Zvcihjb25zdCB0IG9mIHRoaXMuX2ltYWdlQ2FjaGUpZSs9dC5ieXRlU2l6ZTtyZXR1cm4gZX1nZXQjeigpe3JldHVybiEodGhpcy5faW1hZ2VDYWNoZS5zaXplPEdsb2JhbEltYWdlQ2FjaGUuTUlOX0lNQUdFU19UT19DQUNIRSkmJiEodGhpcy4jVzxHbG9iYWxJbWFnZUNhY2hlLk1BWF9CWVRFX1NJWkUpfXNob3VsZENhY2hlKGUsdCl7bGV0IHI9dGhpcy5fcmVmQ2FjaGUuZ2V0KGUpO2lmKCFyKXtyPW5ldyBTZXQ7dGhpcy5fcmVmQ2FjaGUucHV0KGUscil9ci5hZGQodCk7cmV0dXJuIShyLnNpemU8R2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKSYmISghdGhpcy5faW1hZ2VDYWNoZS5oYXMoZSkmJnRoaXMuI3opfWFkZERlY29kZUZhaWxlZChlKXt0aGlzLiNILnB1dChlKX1oYXNEZWNvZGVGYWlsZWQoZSl7cmV0dXJuIHRoaXMuI0guaGFzKGUpfWFkZEJ5dGVTaXplKGUsdCl7Y29uc3Qgcj10aGlzLl9pbWFnZUNhY2hlLmdldChlKTtyJiYoci5ieXRlU2l6ZXx8KHIuYnl0ZVNpemU9dCkpfWdldERhdGEoZSx0KXtjb25zdCByPXRoaXMuX3JlZkNhY2hlLmdldChlKTtpZighcilyZXR1cm4gbnVsbDtpZihyLnNpemU8R2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKXJldHVybiBudWxsO2NvbnN0IGE9dGhpcy5faW1hZ2VDYWNoZS5nZXQoZSk7aWYoIWEpcmV0dXJuIG51bGw7ci5hZGQodCk7cmV0dXJuIGF9c2V0RGF0YShlLHQpe2lmKCF0aGlzLl9yZWZDYWNoZS5oYXMoZSkpdGhyb3cgbmV3IEVycm9yKCdHbG9iYWxJbWFnZUNhY2hlLnNldERhdGEgLSBleHBlY3RlZCAic2hvdWxkQ2FjaGUiIHRvIGhhdmUgYmVlbiBjYWxsZWQuJyk7dGhpcy5faW1hZ2VDYWNoZS5oYXMoZSl8fCh0aGlzLiN6P3dhcm4oIkdsb2JhbEltYWdlQ2FjaGUuc2V0RGF0YSAtIGNhY2hlIGxpbWl0IHJlYWNoZWQuIik6dGhpcy5faW1hZ2VDYWNoZS5wdXQoZSx0KSl9Y2xlYXIoZT0hMSl7aWYoIWUpe3RoaXMuI0guY2xlYXIoKTt0aGlzLl9yZWZDYWNoZS5jbGVhcigpfXRoaXMuX2ltYWdlQ2FjaGUuY2xlYXIoKX19Y2xhc3MgUERGRnVuY3Rpb25GYWN0b3J5e2NvbnN0cnVjdG9yKHt4cmVmOmUsaXNFdmFsU3VwcG9ydGVkOnQ9ITB9KXt0aGlzLnhyZWY9ZTt0aGlzLmlzRXZhbFN1cHBvcnRlZD0hMSE9PXR9Y3JlYXRlKGUsdD0hMSl7bGV0IHIsYTtlIGluc3RhbmNlb2YgUmVmP3I9ZTplIGluc3RhbmNlb2YgRGljdD9yPWUub2JqSWQ6ZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0mJihyPWUuZGljdD8ub2JqSWQpO2lmKHIpe2NvbnN0IGU9dGhpcy5fbG9jYWxGdW5jdGlvbkNhY2hlLmdldEJ5UmVmKHIpO2lmKGUpcmV0dXJuIGV9Y29uc3Qgbj10aGlzLnhyZWYuZmV0Y2hJZlJlZihlKTtpZihBcnJheS5pc0FycmF5KG4pKXtpZighdCl0aHJvdyBuZXcgRXJyb3IoJ1BERkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUgLSBleHBlY3RlZCAicGFyc2VBcnJheSIgYXJndW1lbnQuJyk7YT1QREZGdW5jdGlvbi5wYXJzZUFycmF5KHRoaXMsbil9ZWxzZSBhPVBERkZ1bmN0aW9uLnBhcnNlKHRoaXMsbik7ciYmdGhpcy5fbG9jYWxGdW5jdGlvbkNhY2hlLnNldChudWxsLHIsYSk7cmV0dXJuIGF9Z2V0IF9sb2NhbEZ1bmN0aW9uQ2FjaGUoKXtyZXR1cm4gc2hhZG93KHRoaXMsIl9sb2NhbEZ1bmN0aW9uQ2FjaGUiLG5ldyBMb2NhbEZ1bmN0aW9uQ2FjaGUpfX1mdW5jdGlvbiB0b051bWJlckFycmF5KGUpe3JldHVybiBBcnJheS5pc0FycmF5KGUpP2lzTnVtYmVyQXJyYXkoZSxudWxsKT9lOmUubWFwKGU9PitlKTpudWxsfWNsYXNzIFBERkZ1bmN0aW9ue3N0YXRpYyBnZXRTYW1wbGVBcnJheShlLHQscixhKXtsZXQgbixpLHM9MTtmb3Iobj0wLGk9ZS5sZW5ndGg7bjxpO24rKylzKj1lW25dO3MqPXQ7Y29uc3Qgbz1uZXcgQXJyYXkocyk7bGV0IGM9MCxsPTA7Y29uc3QgaD0xLygyKipyLTEpLHU9YS5nZXRCeXRlcygocypyKzcpLzgpO2xldCBkPTA7Zm9yKG49MDtuPHM7bisrKXtmb3IoO2M8cjspe2w8PD04O2x8PXVbZCsrXTtjKz04fWMtPXI7b1tuXT0obD4+YykqaDtsJj0oMTw8YyktMX1yZXR1cm4gb31zdGF0aWMgcGFyc2UoZSx0KXtjb25zdCByPXQuZGljdHx8dDtzd2l0Y2goci5nZXQoIkZ1bmN0aW9uVHlwZSIpKXtjYXNlIDA6cmV0dXJuIHRoaXMuY29uc3RydWN0U2FtcGxlZChlLHQscik7Y2FzZSAxOmJyZWFrO2Nhc2UgMjpyZXR1cm4gdGhpcy5jb25zdHJ1Y3RJbnRlcnBvbGF0ZWQoZSxyKTtjYXNlIDM6cmV0dXJuIHRoaXMuY29uc3RydWN0U3RpY2hlZChlLHIpO2Nhc2UgNDpyZXR1cm4gdGhpcy5jb25zdHJ1Y3RQb3N0U2NyaXB0KGUsdCxyKX10aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZSBvZiBmdW5jdGlvbiIpfXN0YXRpYyBwYXJzZUFycmF5KGUsdCl7Y29uc3R7eHJlZjpyfT1lLGE9W107Zm9yKGNvbnN0IG4gb2YgdClhLnB1c2godGhpcy5wYXJzZShlLHIuZmV0Y2hJZlJlZihuKSkpO3JldHVybiBmdW5jdGlvbihlLHQscixuKXtmb3IobGV0IGk9MCxzPWEubGVuZ3RoO2k8cztpKyspYVtpXShlLHQscixuK2kpfX1zdGF0aWMgY29uc3RydWN0U2FtcGxlZChlLHQscil7ZnVuY3Rpb24gdG9NdWx0aUFycmF5KGUpe2NvbnN0IHQ9ZS5sZW5ndGgscj1bXTtsZXQgYT0wO2ZvcihsZXQgbj0wO248dDtuKz0yKXJbYSsrXT1bZVtuXSxlW24rMV1dO3JldHVybiByfWZ1bmN0aW9uIGludGVycG9sYXRlKGUsdCxyLGEsbil7cmV0dXJuIGErKG4tYSkvKHItdCkqKGUtdCl9bGV0IGE9dG9OdW1iZXJBcnJheShyLmdldEFycmF5KCJEb21haW4iKSksbj10b051bWJlckFycmF5KHIuZ2V0QXJyYXkoIlJhbmdlIikpO2lmKCFhfHwhbil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbiBvciByYW5nZSIpO2NvbnN0IGk9YS5sZW5ndGgvMixzPW4ubGVuZ3RoLzI7YT10b011bHRpQXJyYXkoYSk7bj10b011bHRpQXJyYXkobik7Y29uc3Qgbz10b051bWJlckFycmF5KHIuZ2V0QXJyYXkoIlNpemUiKSksYz1yLmdldCgiQml0c1BlclNhbXBsZSIpLGw9ci5nZXQoIk9yZGVyIil8fDE7MSE9PWwmJmluZm8oIk5vIHN1cHBvcnQgZm9yIGN1YmljIHNwbGluZSBpbnRlcnBvbGF0aW9uOiAiK2wpO2xldCBoPXRvTnVtYmVyQXJyYXkoci5nZXRBcnJheSgiRW5jb2RlIikpO2lmKGgpaD10b011bHRpQXJyYXkoaCk7ZWxzZXtoPVtdO2ZvcihsZXQgZT0wO2U8aTsrK2UpaC5wdXNoKFswLG9bZV0tMV0pfWxldCB1PXRvTnVtYmVyQXJyYXkoci5nZXRBcnJheSgiRGVjb2RlIikpO3U9dT90b011bHRpQXJyYXkodSk6bjtjb25zdCBkPXRoaXMuZ2V0U2FtcGxlQXJyYXkobyxzLGMsdCk7cmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFNhbXBsZWRGbihlLHQscixjKXtjb25zdCBsPTE8PGksZj1uZXcgRmxvYXQ2NEFycmF5KGwpLmZpbGwoMSksZz1uZXcgVWludDMyQXJyYXkobCk7bGV0IHAsbSxiPXMseT0xO2ZvcihwPTA7cDxpOysrcCl7Y29uc3Qgcj1hW3BdWzBdLG49YVtwXVsxXTtsZXQgaT1pbnRlcnBvbGF0ZShNYXRoQ2xhbXAoZVt0K3BdLHIsbikscixuLGhbcF1bMF0saFtwXVsxXSk7Y29uc3Qgcz1vW3BdO2k9TWF0aENsYW1wKGksMCxzLTEpO2NvbnN0IGM9aTxzLTE/TWF0aC5mbG9vcihpKTppLTEsdT1jKzEtaSxkPWktYyx3PWMqYix4PXcrYjtmb3IobT0wO208bDttKyspaWYobSZ5KXtmW21dKj1kO2dbbV0rPXh9ZWxzZXtmW21dKj11O2dbbV0rPXd9Yio9czt5PDw9MX1mb3IobT0wO208czsrK20pe2xldCBlPTA7Zm9yKHA9MDtwPGw7cCsrKWUrPWRbZ1twXSttXSpmW3BdO2U9aW50ZXJwb2xhdGUoZSwwLDEsdVttXVswXSx1W21dWzFdKTtyW2MrbV09TWF0aENsYW1wKGUsblttXVswXSxuW21dWzFdKX19fXN0YXRpYyBjb25zdHJ1Y3RJbnRlcnBvbGF0ZWQoZSx0KXtjb25zdCByPXRvTnVtYmVyQXJyYXkodC5nZXRBcnJheSgiQzAiKSl8fFswXSxhPXRvTnVtYmVyQXJyYXkodC5nZXRBcnJheSgiQzEiKSl8fFsxXSxuPXQuZ2V0KCJOIiksaT1bXTtmb3IobGV0IGU9MCx0PXIubGVuZ3RoO2U8dDsrK2UpaS5wdXNoKGFbZV0tcltlXSk7Y29uc3Qgcz1pLmxlbmd0aDtyZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0SW50ZXJwb2xhdGVkRm4oZSx0LGEsbyl7Y29uc3QgYz0xPT09bj9lW3RdOmVbdF0qKm47Zm9yKGxldCBlPTA7ZTxzOysrZSlhW28rZV09cltlXStjKmlbZV19fXN0YXRpYyBjb25zdHJ1Y3RTdGljaGVkKGUsdCl7Y29uc3Qgcj10b051bWJlckFycmF5KHQuZ2V0QXJyYXkoIkRvbWFpbiIpKTtpZighcil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbiIpO2lmKDEhPT1yLmxlbmd0aC8yKXRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFkIGRvbWFpbiBmb3Igc3RpY2hlZCBmdW5jdGlvbiIpO2NvbnN0e3hyZWY6YX09ZSxuPVtdO2Zvcihjb25zdCByIG9mIHQuZ2V0KCJGdW5jdGlvbnMiKSluLnB1c2godGhpcy5wYXJzZShlLGEuZmV0Y2hJZlJlZihyKSkpO2NvbnN0IGk9dG9OdW1iZXJBcnJheSh0LmdldEFycmF5KCJCb3VuZHMiKSkscz10b051bWJlckFycmF5KHQuZ2V0QXJyYXkoIkVuY29kZSIpKSxvPW5ldyBGbG9hdDMyQXJyYXkoMSk7cmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFN0aWNoZWRGbihlLHQsYSxjKXtjb25zdCBsPU1hdGhDbGFtcChlW3RdLHJbMF0sclsxXSksaD1pLmxlbmd0aDtsZXQgdTtmb3IodT0wO3U8aCYmIShsPGlbdV0pOysrdSk7bGV0IGQ9clswXTt1PjAmJihkPWlbdS0xXSk7bGV0IGY9clsxXTt1PGkubGVuZ3RoJiYoZj1pW3VdKTtjb25zdCBnPXNbMip1XSxwPXNbMip1KzFdO29bMF09ZD09PWY/ZzpnKyhsLWQpKihwLWcpLyhmLWQpO25bdV0obywwLGEsYyl9fXN0YXRpYyBjb25zdHJ1Y3RQb3N0U2NyaXB0KGUsdCxyKXtjb25zdCBhPXRvTnVtYmVyQXJyYXkoci5nZXRBcnJheSgiRG9tYWluIikpLG49dG9OdW1iZXJBcnJheShyLmdldEFycmF5KCJSYW5nZSIpKTtpZighYSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbi4iKTtpZighbil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIHJhbmdlLiIpO2NvbnN0IGk9bmV3IFBvc3RTY3JpcHRMZXhlcih0KSxzPW5ldyBQb3N0U2NyaXB0UGFyc2VyKGkpLnBhcnNlKCk7aWYoZS5pc0V2YWxTdXBwb3J0ZWQmJkZlYXR1cmVUZXN0LmlzRXZhbFN1cHBvcnRlZCl7Y29uc3QgZT0obmV3IFBvc3RTY3JpcHRDb21waWxlcikuY29tcGlsZShzLGEsbik7aWYoZSlyZXR1cm4gbmV3IEZ1bmN0aW9uKCJzcmMiLCJzcmNPZmZzZXQiLCJkZXN0IiwiZGVzdE9mZnNldCIsZSl9aW5mbygiVW5hYmxlIHRvIGNvbXBpbGUgUFMgZnVuY3Rpb24iKTtjb25zdCBvPW4ubGVuZ3RoPj4xLGM9YS5sZW5ndGg+PjEsbD1uZXcgUG9zdFNjcmlwdEV2YWx1YXRvcihzKSxoPU9iamVjdC5jcmVhdGUobnVsbCk7bGV0IHU9ODE5Mjtjb25zdCBkPW5ldyBGbG9hdDMyQXJyYXkoYyk7cmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFBvc3RTY3JpcHRGbihlLHQscixhKXtsZXQgaSxzLGY9IiI7Y29uc3QgZz1kO2ZvcihpPTA7aTxjO2krKyl7cz1lW3QraV07Z1tpXT1zO2YrPXMrIl8ifWNvbnN0IHA9aFtmXTtpZih2b2lkIDAhPT1wKXtyLnNldChwLGEpO3JldHVybn1jb25zdCBtPW5ldyBGbG9hdDMyQXJyYXkobyksYj1sLmV4ZWN1dGUoZykseT1iLmxlbmd0aC1vO2ZvcihpPTA7aTxvO2krKyl7cz1iW3kraV07bGV0IGU9blsyKmldO2lmKHM8ZSlzPWU7ZWxzZXtlPW5bMippKzFdO3M+ZSYmKHM9ZSl9bVtpXT1zfWlmKHU+MCl7dS0tO2hbZl09bX1yLnNldChtLGEpfX19ZnVuY3Rpb24gaXNQREZGdW5jdGlvbihlKXtsZXQgdDtpZihlIGluc3RhbmNlb2YgRGljdCl0PWU7ZWxzZXtpZighKGUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSlyZXR1cm4hMTt0PWUuZGljdH1yZXR1cm4gdC5oYXMoIkZ1bmN0aW9uVHlwZSIpfWNsYXNzIFBvc3RTY3JpcHRTdGFja3tzdGF0aWMgTUFYX1NUQUNLX1NJWkU9MTAwO2NvbnN0cnVjdG9yKGUpe3RoaXMuc3RhY2s9ZT9BcnJheS5mcm9tKGUpOltdfXB1c2goZSl7aWYodGhpcy5zdGFjay5sZW5ndGg+PVBvc3RTY3JpcHRTdGFjay5NQVhfU1RBQ0tfU0laRSl0aHJvdyBuZXcgRXJyb3IoIlBvc3RTY3JpcHQgZnVuY3Rpb24gc3RhY2sgb3ZlcmZsb3cuIik7dGhpcy5zdGFjay5wdXNoKGUpfXBvcCgpe2lmKHRoaXMuc3RhY2subGVuZ3RoPD0wKXRocm93IG5ldyBFcnJvcigiUG9zdFNjcmlwdCBmdW5jdGlvbiBzdGFjayB1bmRlcmZsb3cuIik7cmV0dXJuIHRoaXMuc3RhY2sucG9wKCl9Y29weShlKXtpZih0aGlzLnN0YWNrLmxlbmd0aCtlPj1Qb3N0U2NyaXB0U3RhY2suTUFYX1NUQUNLX1NJWkUpdGhyb3cgbmV3IEVycm9yKCJQb3N0U2NyaXB0IGZ1bmN0aW9uIHN0YWNrIG92ZXJmbG93LiIpO2NvbnN0IHQ9dGhpcy5zdGFjaztmb3IobGV0IHI9dC5sZW5ndGgtZSxhPWUtMTthPj0wO2EtLSxyKyspdC5wdXNoKHRbcl0pfWluZGV4KGUpe3RoaXMucHVzaCh0aGlzLnN0YWNrW3RoaXMuc3RhY2subGVuZ3RoLWUtMV0pfXJvbGwoZSx0KXtjb25zdCByPXRoaXMuc3RhY2ssYT1yLmxlbmd0aC1lLG49ci5sZW5ndGgtMSxpPWErKHQtTWF0aC5mbG9vcih0L2UpKmUpO2ZvcihsZXQgZT1hLHQ9bjtlPHQ7ZSsrLHQtLSl7Y29uc3QgYT1yW2VdO3JbZV09clt0XTtyW3RdPWF9Zm9yKGxldCBlPWEsdD1pLTE7ZTx0O2UrKyx0LS0pe2NvbnN0IGE9cltlXTtyW2VdPXJbdF07clt0XT1hfWZvcihsZXQgZT1pLHQ9bjtlPHQ7ZSsrLHQtLSl7Y29uc3QgYT1yW2VdO3JbZV09clt0XTtyW3RdPWF9fX1jbGFzcyBQb3N0U2NyaXB0RXZhbHVhdG9ye2NvbnN0cnVjdG9yKGUpe3RoaXMub3BlcmF0b3JzPWV9ZXhlY3V0ZShlKXtjb25zdCB0PW5ldyBQb3N0U2NyaXB0U3RhY2soZSk7bGV0IHI9MDtjb25zdCBhPXRoaXMub3BlcmF0b3JzLG49YS5sZW5ndGg7bGV0IGkscyxvO2Zvcig7cjxuOyl7aT1hW3IrK107aWYoIm51bWJlciIhPXR5cGVvZiBpKXN3aXRjaChpKXtjYXNlImp6IjpvPXQucG9wKCk7cz10LnBvcCgpO3N8fChyPW8pO2JyZWFrO2Nhc2UiaiI6cz10LnBvcCgpO3I9czticmVhaztjYXNlImFicyI6cz10LnBvcCgpO3QucHVzaChNYXRoLmFicyhzKSk7YnJlYWs7Y2FzZSJhZGQiOm89dC5wb3AoKTtzPXQucG9wKCk7dC5wdXNoKHMrbyk7YnJlYWs7Y2FzZSJhbmQiOm89dC5wb3AoKTtzPXQucG9wKCk7ImJvb2xlYW4iPT10eXBlb2YgcyYmImJvb2xlYW4iPT10eXBlb2Ygbz90LnB1c2gocyYmbyk6dC5wdXNoKHMmbyk7YnJlYWs7Y2FzZSJhdGFuIjpvPXQucG9wKCk7cz10LnBvcCgpO3M9TWF0aC5hdGFuMihzLG8pL01hdGguUEkqMTgwO3M8MCYmKHMrPTM2MCk7dC5wdXNoKHMpO2JyZWFrO2Nhc2UiYml0c2hpZnQiOm89dC5wb3AoKTtzPXQucG9wKCk7cz4wP3QucHVzaChzPDxvKTp0LnB1c2gocz4+byk7YnJlYWs7Y2FzZSJjZWlsaW5nIjpzPXQucG9wKCk7dC5wdXNoKE1hdGguY2VpbChzKSk7YnJlYWs7Y2FzZSJjb3B5IjpzPXQucG9wKCk7dC5jb3B5KHMpO2JyZWFrO2Nhc2UiY29zIjpzPXQucG9wKCk7dC5wdXNoKE1hdGguY29zKHMlMzYwLzE4MCpNYXRoLlBJKSk7YnJlYWs7Y2FzZSJjdmkiOnM9MHx0LnBvcCgpO3QucHVzaChzKTticmVhaztjYXNlImN2ciI6YnJlYWs7Y2FzZSJkaXYiOm89dC5wb3AoKTtzPXQucG9wKCk7dC5wdXNoKHMvbyk7YnJlYWs7Y2FzZSJkdXAiOnQuY29weSgxKTticmVhaztjYXNlImVxIjpvPXQucG9wKCk7cz10LnBvcCgpO3QucHVzaChzPT09byk7YnJlYWs7Y2FzZSJleGNoIjp0LnJvbGwoMiwxKTticmVhaztjYXNlImV4cCI6bz10LnBvcCgpO3M9dC5wb3AoKTt0LnB1c2gocyoqbyk7YnJlYWs7Y2FzZSJmYWxzZSI6dC5wdXNoKCExKTticmVhaztjYXNlImZsb29yIjpzPXQucG9wKCk7dC5wdXNoKE1hdGguZmxvb3IocykpO2JyZWFrO2Nhc2UiZ2UiOm89dC5wb3AoKTtzPXQucG9wKCk7dC5wdXNoKHM+PW8pO2JyZWFrO2Nhc2UiZ3QiOm89dC5wb3AoKTtzPXQucG9wKCk7dC5wdXNoKHM+byk7YnJlYWs7Y2FzZSJpZGl2IjpvPXQucG9wKCk7cz10LnBvcCgpO3QucHVzaChzL298MCk7YnJlYWs7Y2FzZSJpbmRleCI6cz10LnBvcCgpO3QuaW5kZXgocyk7YnJlYWs7Y2FzZSJsZSI6bz10LnBvcCgpO3M9dC5wb3AoKTt0LnB1c2goczw9byk7YnJlYWs7Y2FzZSJsbiI6cz10LnBvcCgpO3QucHVzaChNYXRoLmxvZyhzKSk7YnJlYWs7Y2FzZSJsb2ciOnM9dC5wb3AoKTt0LnB1c2goTWF0aC5sb2cxMChzKSk7YnJlYWs7Y2FzZSJsdCI6bz10LnBvcCgpO3M9dC5wb3AoKTt0LnB1c2goczxvKTticmVhaztjYXNlIm1vZCI6bz10LnBvcCgpO3M9dC5wb3AoKTt0LnB1c2gocyVvKTticmVhaztjYXNlIm11bCI6bz10LnBvcCgpO3M9dC5wb3AoKTt0LnB1c2gocypvKTticmVhaztjYXNlIm5lIjpvPXQucG9wKCk7cz10LnBvcCgpO3QucHVzaChzIT09byk7YnJlYWs7Y2FzZSJuZWciOnM9dC5wb3AoKTt0LnB1c2goLXMpO2JyZWFrO2Nhc2Uibm90IjpzPXQucG9wKCk7ImJvb2xlYW4iPT10eXBlb2Ygcz90LnB1c2goIXMpOnQucHVzaCh+cyk7YnJlYWs7Y2FzZSJvciI6bz10LnBvcCgpO3M9dC5wb3AoKTsiYm9vbGVhbiI9PXR5cGVvZiBzJiYiYm9vbGVhbiI9PXR5cGVvZiBvP3QucHVzaChzfHxvKTp0LnB1c2goc3xvKTticmVhaztjYXNlInBvcCI6dC5wb3AoKTticmVhaztjYXNlInJvbGwiOm89dC5wb3AoKTtzPXQucG9wKCk7dC5yb2xsKHMsbyk7YnJlYWs7Y2FzZSJyb3VuZCI6cz10LnBvcCgpO3QucHVzaChNYXRoLnJvdW5kKHMpKTticmVhaztjYXNlInNpbiI6cz10LnBvcCgpO3QucHVzaChNYXRoLnNpbihzJTM2MC8xODAqTWF0aC5QSSkpO2JyZWFrO2Nhc2Uic3FydCI6cz10LnBvcCgpO3QucHVzaChNYXRoLnNxcnQocykpO2JyZWFrO2Nhc2Uic3ViIjpvPXQucG9wKCk7cz10LnBvcCgpO3QucHVzaChzLW8pO2JyZWFrO2Nhc2UidHJ1ZSI6dC5wdXNoKCEwKTticmVhaztjYXNlInRydW5jYXRlIjpzPXQucG9wKCk7cz1zPDA/TWF0aC5jZWlsKHMpOk1hdGguZmxvb3Iocyk7dC5wdXNoKHMpO2JyZWFrO2Nhc2UieG9yIjpvPXQucG9wKCk7cz10LnBvcCgpOyJib29sZWFuIj09dHlwZW9mIHMmJiJib29sZWFuIj09dHlwZW9mIG8/dC5wdXNoKHMhPT1vKTp0LnB1c2goc15vKTticmVhaztkZWZhdWx0OnRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBvcGVyYXRvciAke2l9YCl9ZWxzZSB0LnB1c2goaSl9cmV0dXJuIHQuc3RhY2t9fWNsYXNzIEFzdE5vZGV7Y29uc3RydWN0b3IoZSl7dGhpcy50eXBlPWV9dmlzaXQoZSl7dW5yZWFjaGFibGUoImFic3RyYWN0IG1ldGhvZCIpfX1jbGFzcyBBc3RBcmd1bWVudCBleHRlbmRzIEFzdE5vZGV7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKCJhcmdzIik7dGhpcy5pbmRleD1lO3RoaXMubWluPXQ7dGhpcy5tYXg9cn12aXNpdChlKXtlLnZpc2l0QXJndW1lbnQodGhpcyl9fWNsYXNzIEFzdExpdGVyYWwgZXh0ZW5kcyBBc3ROb2Rle2NvbnN0cnVjdG9yKGUpe3N1cGVyKCJsaXRlcmFsIik7dGhpcy5udW1iZXI9ZTt0aGlzLm1pbj1lO3RoaXMubWF4PWV9dmlzaXQoZSl7ZS52aXNpdExpdGVyYWwodGhpcyl9fWNsYXNzIEFzdEJpbmFyeU9wZXJhdGlvbiBleHRlbmRzIEFzdE5vZGV7Y29uc3RydWN0b3IoZSx0LHIsYSxuKXtzdXBlcigiYmluYXJ5Iik7dGhpcy5vcD1lO3RoaXMuYXJnMT10O3RoaXMuYXJnMj1yO3RoaXMubWluPWE7dGhpcy5tYXg9bn12aXNpdChlKXtlLnZpc2l0QmluYXJ5T3BlcmF0aW9uKHRoaXMpfX1jbGFzcyBBc3RNaW4gZXh0ZW5kcyBBc3ROb2Rle2NvbnN0cnVjdG9yKGUsdCl7c3VwZXIoIm1heCIpO3RoaXMuYXJnPWU7dGhpcy5taW49ZS5taW47dGhpcy5tYXg9dH12aXNpdChlKXtlLnZpc2l0TWluKHRoaXMpfX1jbGFzcyBBc3RWYXJpYWJsZSBleHRlbmRzIEFzdE5vZGV7Y29uc3RydWN0b3IoZSx0LHIpe3N1cGVyKCJ2YXIiKTt0aGlzLmluZGV4PWU7dGhpcy5taW49dDt0aGlzLm1heD1yfXZpc2l0KGUpe2UudmlzaXRWYXJpYWJsZSh0aGlzKX19Y2xhc3MgQXN0VmFyaWFibGVEZWZpbml0aW9uIGV4dGVuZHMgQXN0Tm9kZXtjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKCJkZWZpbml0aW9uIik7dGhpcy52YXJpYWJsZT1lO3RoaXMuYXJnPXR9dmlzaXQoZSl7ZS52aXNpdFZhcmlhYmxlRGVmaW5pdGlvbih0aGlzKX19Y2xhc3MgRXhwcmVzc2lvbkJ1aWxkZXJWaXNpdG9ye2NvbnN0cnVjdG9yKCl7dGhpcy5wYXJ0cz1bXX12aXNpdEFyZ3VtZW50KGUpe3RoaXMucGFydHMucHVzaCgiTWF0aC5tYXgoIixlLm1pbiwiLCBNYXRoLm1pbigiLGUubWF4LCIsIHNyY1tzcmNPZmZzZXQgKyAiLGUuaW5kZXgsIl0pKSIpfXZpc2l0VmFyaWFibGUoZSl7dGhpcy5wYXJ0cy5wdXNoKCJ2IixlLmluZGV4KX12aXNpdExpdGVyYWwoZSl7dGhpcy5wYXJ0cy5wdXNoKGUubnVtYmVyKX12aXNpdEJpbmFyeU9wZXJhdGlvbihlKXt0aGlzLnBhcnRzLnB1c2goIigiKTtlLmFyZzEudmlzaXQodGhpcyk7dGhpcy5wYXJ0cy5wdXNoKCIgIixlLm9wLCIgIik7ZS5hcmcyLnZpc2l0KHRoaXMpO3RoaXMucGFydHMucHVzaCgiKSIpfXZpc2l0VmFyaWFibGVEZWZpbml0aW9uKGUpe3RoaXMucGFydHMucHVzaCgidmFyICIpO2UudmFyaWFibGUudmlzaXQodGhpcyk7dGhpcy5wYXJ0cy5wdXNoKCIgPSAiKTtlLmFyZy52aXNpdCh0aGlzKTt0aGlzLnBhcnRzLnB1c2goIjsiKX12aXNpdE1pbihlKXt0aGlzLnBhcnRzLnB1c2goIk1hdGgubWluKCIpO2UuYXJnLnZpc2l0KHRoaXMpO3RoaXMucGFydHMucHVzaCgiLCAiLGUubWF4LCIpIil9dG9TdHJpbmcoKXtyZXR1cm4gdGhpcy5wYXJ0cy5qb2luKCIiKX19ZnVuY3Rpb24gYnVpbGRBZGRPcGVyYXRpb24oZSx0KXtyZXR1cm4ibGl0ZXJhbCI9PT10LnR5cGUmJjA9PT10Lm51bWJlcj9lOiJsaXRlcmFsIj09PWUudHlwZSYmMD09PWUubnVtYmVyP3Q6ImxpdGVyYWwiPT09dC50eXBlJiYibGl0ZXJhbCI9PT1lLnR5cGU/bmV3IEFzdExpdGVyYWwoZS5udW1iZXIrdC5udW1iZXIpOm5ldyBBc3RCaW5hcnlPcGVyYXRpb24oIisiLGUsdCxlLm1pbit0Lm1pbixlLm1heCt0Lm1heCl9ZnVuY3Rpb24gYnVpbGRNdWxPcGVyYXRpb24oZSx0KXtpZigibGl0ZXJhbCI9PT10LnR5cGUpe2lmKDA9PT10Lm51bWJlcilyZXR1cm4gbmV3IEFzdExpdGVyYWwoMCk7aWYoMT09PXQubnVtYmVyKXJldHVybiBlO2lmKCJsaXRlcmFsIj09PWUudHlwZSlyZXR1cm4gbmV3IEFzdExpdGVyYWwoZS5udW1iZXIqdC5udW1iZXIpfWlmKCJsaXRlcmFsIj09PWUudHlwZSl7aWYoMD09PWUubnVtYmVyKXJldHVybiBuZXcgQXN0TGl0ZXJhbCgwKTtpZigxPT09ZS5udW1iZXIpcmV0dXJuIHR9Y29uc3Qgcj1NYXRoLm1pbihlLm1pbip0Lm1pbixlLm1pbip0Lm1heCxlLm1heCp0Lm1pbixlLm1heCp0Lm1heCksYT1NYXRoLm1heChlLm1pbip0Lm1pbixlLm1pbip0Lm1heCxlLm1heCp0Lm1pbixlLm1heCp0Lm1heCk7cmV0dXJuIG5ldyBBc3RCaW5hcnlPcGVyYXRpb24oIioiLGUsdCxyLGEpfWZ1bmN0aW9uIGJ1aWxkU3ViT3BlcmF0aW9uKGUsdCl7aWYoImxpdGVyYWwiPT09dC50eXBlKXtpZigwPT09dC5udW1iZXIpcmV0dXJuIGU7aWYoImxpdGVyYWwiPT09ZS50eXBlKXJldHVybiBuZXcgQXN0TGl0ZXJhbChlLm51bWJlci10Lm51bWJlcil9cmV0dXJuImJpbmFyeSI9PT10LnR5cGUmJiItIj09PXQub3AmJiJsaXRlcmFsIj09PWUudHlwZSYmMT09PWUubnVtYmVyJiYibGl0ZXJhbCI9PT10LmFyZzEudHlwZSYmMT09PXQuYXJnMS5udW1iZXI/dC5hcmcyOm5ldyBBc3RCaW5hcnlPcGVyYXRpb24oIi0iLGUsdCxlLm1pbi10Lm1heCxlLm1heC10Lm1pbil9ZnVuY3Rpb24gYnVpbGRNaW5PcGVyYXRpb24oZSx0KXtyZXR1cm4gZS5taW4+PXQ/bmV3IEFzdExpdGVyYWwodCk6ZS5tYXg8PXQ/ZTpuZXcgQXN0TWluKGUsdCl9Y2xhc3MgUG9zdFNjcmlwdENvbXBpbGVye2NvbXBpbGUoZSx0LHIpe2NvbnN0IGE9W10sbj1bXSxpPXQubGVuZ3RoPj4xLHM9ci5sZW5ndGg+PjE7bGV0IG8sYyxsLGgsdSxkLGYsZyxwPTA7Zm9yKGxldCBlPTA7ZTxpO2UrKylhLnB1c2gobmV3IEFzdEFyZ3VtZW50KGUsdFsyKmVdLHRbMiplKzFdKSk7Zm9yKGxldCB0PTAscj1lLmxlbmd0aDt0PHI7dCsrKXtnPWVbdF07aWYoIm51bWJlciIhPXR5cGVvZiBnKXN3aXRjaChnKXtjYXNlImFkZCI6aWYoYS5sZW5ndGg8MilyZXR1cm4gbnVsbDtoPWEucG9wKCk7bD1hLnBvcCgpO2EucHVzaChidWlsZEFkZE9wZXJhdGlvbihsLGgpKTticmVhaztjYXNlImN2ciI6aWYoYS5sZW5ndGg8MSlyZXR1cm4gbnVsbDticmVhaztjYXNlIm11bCI6aWYoYS5sZW5ndGg8MilyZXR1cm4gbnVsbDtoPWEucG9wKCk7bD1hLnBvcCgpO2EucHVzaChidWlsZE11bE9wZXJhdGlvbihsLGgpKTticmVhaztjYXNlInN1YiI6aWYoYS5sZW5ndGg8MilyZXR1cm4gbnVsbDtoPWEucG9wKCk7bD1hLnBvcCgpO2EucHVzaChidWlsZFN1Yk9wZXJhdGlvbihsLGgpKTticmVhaztjYXNlImV4Y2giOmlmKGEubGVuZ3RoPDIpcmV0dXJuIG51bGw7dT1hLnBvcCgpO2Q9YS5wb3AoKTthLnB1c2godSxkKTticmVhaztjYXNlInBvcCI6aWYoYS5sZW5ndGg8MSlyZXR1cm4gbnVsbDthLnBvcCgpO2JyZWFrO2Nhc2UiaW5kZXgiOmlmKGEubGVuZ3RoPDEpcmV0dXJuIG51bGw7bD1hLnBvcCgpO2lmKCJsaXRlcmFsIiE9PWwudHlwZSlyZXR1cm4gbnVsbDtvPWwubnVtYmVyO2lmKG88MHx8IU51bWJlci5pc0ludGVnZXIobyl8fGEubGVuZ3RoPG8pcmV0dXJuIG51bGw7dT1hW2EubGVuZ3RoLW8tMV07aWYoImxpdGVyYWwiPT09dS50eXBlfHwidmFyIj09PXUudHlwZSl7YS5wdXNoKHUpO2JyZWFrfWY9bmV3IEFzdFZhcmlhYmxlKHArKyx1Lm1pbix1Lm1heCk7YVthLmxlbmd0aC1vLTFdPWY7YS5wdXNoKGYpO24ucHVzaChuZXcgQXN0VmFyaWFibGVEZWZpbml0aW9uKGYsdSkpO2JyZWFrO2Nhc2UiZHVwIjppZihhLmxlbmd0aDwxKXJldHVybiBudWxsO2lmKCJudW1iZXIiPT10eXBlb2YgZVt0KzFdJiYiZ3QiPT09ZVt0KzJdJiZlW3QrM109PT10KzcmJiJqeiI9PT1lW3QrNF0mJiJwb3AiPT09ZVt0KzVdJiZlW3QrNl09PT1lW3QrMV0pe2w9YS5wb3AoKTthLnB1c2goYnVpbGRNaW5PcGVyYXRpb24obCxlW3QrMV0pKTt0Kz02O2JyZWFrfXU9YS5hdCgtMSk7aWYoImxpdGVyYWwiPT09dS50eXBlfHwidmFyIj09PXUudHlwZSl7YS5wdXNoKHUpO2JyZWFrfWY9bmV3IEFzdFZhcmlhYmxlKHArKyx1Lm1pbix1Lm1heCk7YVthLmxlbmd0aC0xXT1mO2EucHVzaChmKTtuLnB1c2gobmV3IEFzdFZhcmlhYmxlRGVmaW5pdGlvbihmLHUpKTticmVhaztjYXNlInJvbGwiOmlmKGEubGVuZ3RoPDIpcmV0dXJuIG51bGw7aD1hLnBvcCgpO2w9YS5wb3AoKTtpZigibGl0ZXJhbCIhPT1oLnR5cGV8fCJsaXRlcmFsIiE9PWwudHlwZSlyZXR1cm4gbnVsbDtjPWgubnVtYmVyO289bC5udW1iZXI7aWYobzw9MHx8IU51bWJlci5pc0ludGVnZXIobyl8fCFOdW1iZXIuaXNJbnRlZ2VyKGMpfHxhLmxlbmd0aDxvKXJldHVybiBudWxsO2M9KGMlbytvKSVvO2lmKDA9PT1jKWJyZWFrO2EucHVzaCguLi5hLnNwbGljZShhLmxlbmd0aC1vLG8tYykpO2JyZWFrO2RlZmF1bHQ6cmV0dXJuIG51bGx9ZWxzZSBhLnB1c2gobmV3IEFzdExpdGVyYWwoZykpfWlmKGEubGVuZ3RoIT09cylyZXR1cm4gbnVsbDtjb25zdCBtPVtdO2Zvcihjb25zdCBlIG9mIG4pe2NvbnN0IHQ9bmV3IEV4cHJlc3Npb25CdWlsZGVyVmlzaXRvcjtlLnZpc2l0KHQpO20ucHVzaCh0LnRvU3RyaW5nKCkpfWZvcihsZXQgZT0wLHQ9YS5sZW5ndGg7ZTx0O2UrKyl7Y29uc3QgdD1hW2VdLG49bmV3IEV4cHJlc3Npb25CdWlsZGVyVmlzaXRvcjt0LnZpc2l0KG4pO2NvbnN0IGk9clsyKmVdLHM9clsyKmUrMV0sbz1bbi50b1N0cmluZygpXTtpZihpPnQubWluKXtvLnVuc2hpZnQoIk1hdGgubWF4KCIsaSwiLCAiKTtvLnB1c2goIikiKX1pZihzPHQubWF4KXtvLnVuc2hpZnQoIk1hdGgubWluKCIscywiLCAiKTtvLnB1c2goIikiKX1vLnVuc2hpZnQoImRlc3RbZGVzdE9mZnNldCArICIsZSwiXSA9ICIpO28ucHVzaCgiOyIpO20ucHVzaChvLmpvaW4oIiIpKX1yZXR1cm4gbS5qb2luKCJcbiIpfX1jb25zdCBuaT1bIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIlMiLCJCIiwiUyIsIldTIiwiQiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCIiwiQiIsIkIiLCJTIiwiV1MiLCJPTiIsIk9OIiwiRVQiLCJFVCIsIkVUIiwiT04iLCJPTiIsIk9OIiwiT04iLCJPTiIsIkVTIiwiQ1MiLCJFUyIsIkNTIiwiQ1MiLCJFTiIsIkVOIiwiRU4iLCJFTiIsIkVOIiwiRU4iLCJFTiIsIkVOIiwiRU4iLCJFTiIsIkNTIiwiT04iLCJPTiIsIk9OIiwiT04iLCJPTiIsIk9OIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJPTiIsIk9OIiwiT04iLCJPTiIsIk9OIiwiT04iLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIk9OIiwiT04iLCJPTiIsIk9OIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJCTiIsIkJOIiwiQk4iLCJDUyIsIk9OIiwiRVQiLCJFVCIsIkVUIiwiRVQiLCJPTiIsIk9OIiwiT04iLCJPTiIsIkwiLCJPTiIsIk9OIiwiQk4iLCJPTiIsIk9OIiwiRVQiLCJFVCIsIkVOIiwiRU4iLCJPTiIsIkwiLCJPTiIsIk9OIiwiT04iLCJFTiIsIkwiLCJPTiIsIk9OIiwiT04iLCJPTiIsIk9OIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJPTiIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJPTiIsIkwiLCJMIiwiTCIsIkwiLCJMIiwiTCIsIkwiLCJMIl0saWk9WyJBTiIsIkFOIiwiQU4iLCJBTiIsIkFOIiwiQU4iLCJPTiIsIk9OIiwiQUwiLCJFVCIsIkVUIiwiQUwiLCJDUyIsIkFMIiwiT04iLCJPTiIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIk5TTSIsIkFMIiwiQUwiLCIiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJBTiIsIkFOIiwiQU4iLCJBTiIsIkFOIiwiQU4iLCJBTiIsIkFOIiwiQU4iLCJBTiIsIkVUIiwiQU4iLCJBTiIsIkFMIiwiQUwiLCJBTCIsIk5TTSIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJOU00iLCJBTiIsIk9OIiwiTlNNIiwiTlNNIiwiTlNNIiwiTlNNIiwiTlNNIiwiTlNNIiwiQUwiLCJBTCIsIk5TTSIsIk5TTSIsIk9OIiwiTlNNIiwiTlNNIiwiTlNNIiwiTlNNIiwiQUwiLCJBTCIsIkVOIiwiRU4iLCJFTiIsIkVOIiwiRU4iLCJFTiIsIkVOIiwiRU4iLCJFTiIsIkVOIiwiQUwiLCJBTCIsIkFMIiwiQUwiLCJBTCIsIkFMIl07ZnVuY3Rpb24gaXNPZGQoZSl7cmV0dXJuISEoMSZlKX1mdW5jdGlvbiBpc0V2ZW4oZSl7cmV0dXJuISgxJmUpfWZ1bmN0aW9uIGZpbmRVbmVxdWFsKGUsdCxyKXtsZXQgYSxuO2ZvcihhPXQsbj1lLmxlbmd0aDthPG47KythKWlmKGVbYV0hPT1yKXJldHVybiBhO3JldHVybiBhfWZ1bmN0aW9uIHJldmVyc2VWYWx1ZXMoZSx0LHIpe2ZvcihsZXQgYT10LG49ci0xO2E8bjsrK2EsLS1uKXtjb25zdCB0PWVbYV07ZVthXT1lW25dO2Vbbl09dH19ZnVuY3Rpb24gY3JlYXRlQmlkaVRleHQoZSx0LHI9ITEpe2xldCBhPSJsdHIiO3I/YT0idHRiIjp0fHwoYT0icnRsIik7cmV0dXJue3N0cjplLGRpcjphfX1jb25zdCBzaT1bXSxvaT1bXTtmdW5jdGlvbiBiaWRpKGUsdD0tMSxyPSExKXtsZXQgYT0hMDtjb25zdCBuPWUubGVuZ3RoO2lmKDA9PT1ufHxyKXJldHVybiBjcmVhdGVCaWRpVGV4dChlLGEscik7c2kubGVuZ3RoPW47b2kubGVuZ3RoPW47bGV0IGkscyxvPTA7Zm9yKGk9MDtpPG47KytpKXtzaVtpXT1lLmNoYXJBdChpKTtjb25zdCB0PWUuY2hhckNvZGVBdChpKTtsZXQgcj0iTCI7aWYodDw9MjU1KXI9bmlbdF07ZWxzZSBpZigxNDI0PD10JiZ0PD0xNTI0KXI9IlIiO2Vsc2UgaWYoMTUzNjw9dCYmdDw9MTc5MSl7cj1paVsyNTUmdF07cnx8d2FybigiQmlkaTogaW52YWxpZCBVbmljb2RlIGNoYXJhY3RlciAiK3QudG9TdHJpbmcoMTYpKX1lbHNlKDE3OTI8PXQmJnQ8PTIyMjB8fDY0MzM2PD10JiZ0PD02NTAyM3x8NjUxMzY8PXQmJnQ8PTY1Mjc5KSYmKHI9IkFMIik7IlIiIT09ciYmIkFMIiE9PXImJiJBTiIhPT1yfHxvKys7b2lbaV09cn1pZigwPT09byl7YT0hMDtyZXR1cm4gY3JlYXRlQmlkaVRleHQoZSxhKX1pZigtMT09PXQpaWYoby9uPC4zJiZuPjQpe2E9ITA7dD0wfWVsc2V7YT0hMTt0PTF9Y29uc3QgYz1bXTtmb3IoaT0wO2k8bjsrK2kpY1tpXT10O2NvbnN0IGw9aXNPZGQodCk/IlIiOiJMIixoPWwsdT1oO2xldCBkLGY9aDtmb3IoaT0wO2k8bjsrK2kpIk5TTSI9PT1vaVtpXT9vaVtpXT1mOmY9b2lbaV07Zj1oO2ZvcihpPTA7aTxuOysraSl7ZD1vaVtpXTsiRU4iPT09ZD9vaVtpXT0iQUwiPT09Zj8iQU4iOiJFTiI6IlIiIT09ZCYmIkwiIT09ZCYmIkFMIiE9PWR8fChmPWQpfWZvcihpPTA7aTxuOysraSl7ZD1vaVtpXTsiQUwiPT09ZCYmKG9pW2ldPSJSIil9Zm9yKGk9MTtpPG4tMTsrK2kpeyJFUyI9PT1vaVtpXSYmIkVOIj09PW9pW2ktMV0mJiJFTiI9PT1vaVtpKzFdJiYob2lbaV09IkVOIik7IkNTIiE9PW9pW2ldfHwiRU4iIT09b2lbaS0xXSYmIkFOIiE9PW9pW2ktMV18fG9pW2krMV0hPT1vaVtpLTFdfHwob2lbaV09b2lbaS0xXSl9Zm9yKGk9MDtpPG47KytpKWlmKCJFTiI9PT1vaVtpXSl7Zm9yKGxldCBlPWktMTtlPj0wJiYiRVQiPT09b2lbZV07LS1lKW9pW2VdPSJFTiI7Zm9yKGxldCBlPWkrMTtlPG4mJiJFVCI9PT1vaVtlXTsrK2Upb2lbZV09IkVOIn1mb3IoaT0wO2k8bjsrK2kpe2Q9b2lbaV07IldTIiE9PWQmJiJFUyIhPT1kJiYiRVQiIT09ZCYmIkNTIiE9PWR8fChvaVtpXT0iT04iKX1mPWg7Zm9yKGk9MDtpPG47KytpKXtkPW9pW2ldOyJFTiI9PT1kP29pW2ldPSJMIj09PWY/IkwiOiJFTiI6IlIiIT09ZCYmIkwiIT09ZHx8KGY9ZCl9Zm9yKGk9MDtpPG47KytpKWlmKCJPTiI9PT1vaVtpXSl7Y29uc3QgZT1maW5kVW5lcXVhbChvaSxpKzEsIk9OIik7bGV0IHQ9aDtpPjAmJih0PW9pW2ktMV0pO2xldCByPXU7ZSsxPG4mJihyPW9pW2UrMV0pOyJMIiE9PXQmJih0PSJSIik7IkwiIT09ciYmKHI9IlIiKTt0PT09ciYmb2kuZmlsbCh0LGksZSk7aT1lLTF9Zm9yKGk9MDtpPG47KytpKSJPTiI9PT1vaVtpXSYmKG9pW2ldPWwpO2ZvcihpPTA7aTxuOysraSl7ZD1vaVtpXTtpc0V2ZW4oY1tpXSk/IlIiPT09ZD9jW2ldKz0xOiJBTiIhPT1kJiYiRU4iIT09ZHx8KGNbaV0rPTIpOiJMIiE9PWQmJiJBTiIhPT1kJiYiRU4iIT09ZHx8KGNbaV0rPTEpfWxldCBnLHA9LTEsbT05OTtmb3IoaT0wLHM9Yy5sZW5ndGg7aTxzOysraSl7Zz1jW2ldO3A8ZyYmKHA9Zyk7bT5nJiZpc09kZChnKSYmKG09Zyl9Zm9yKGc9cDtnPj1tOy0tZyl7bGV0IGU9LTE7Zm9yKGk9MCxzPWMubGVuZ3RoO2k8czsrK2kpaWYoY1tpXTxnKXtpZihlPj0wKXtyZXZlcnNlVmFsdWVzKHNpLGUsaSk7ZT0tMX19ZWxzZSBlPDAmJihlPWkpO2U+PTAmJnJldmVyc2VWYWx1ZXMoc2ksZSxjLmxlbmd0aCl9Zm9yKGk9MCxzPXNpLmxlbmd0aDtpPHM7KytpKXtjb25zdCBlPXNpW2ldOyI8IiE9PWUmJiI+IiE9PWV8fChzaVtpXT0iIil9cmV0dXJuIGNyZWF0ZUJpZGlUZXh0KHNpLmpvaW4oIiIpLGEpfWNsYXNzIENzc0ZvbnRJbmZveyNOOyNHOyMkO3N0YXRpYyBzdHJpbmdzPVsiZm9udEZhbWlseSIsImZvbnRXZWlnaHQiLCJpdGFsaWNBbmdsZSJdO3N0YXRpYyB3cml0ZShlKXtjb25zdCB0PW5ldyBUZXh0RW5jb2RlcixyPXt9O2xldCBhPTA7Zm9yKGNvbnN0IG4gb2YgQ3NzRm9udEluZm8uc3RyaW5ncyl7Y29uc3QgaT10LmVuY29kZShlW25dKTtyW25dPWk7YSs9NCtpLmxlbmd0aH1jb25zdCBuPW5ldyBBcnJheUJ1ZmZlcihhKSxpPW5ldyBVaW50OEFycmF5KG4pLHM9bmV3IERhdGFWaWV3KG4pO2xldCBvPTA7Zm9yKGNvbnN0IGUgb2YgQ3NzRm9udEluZm8uc3RyaW5ncyl7Y29uc3QgdD1yW2VdLGE9dC5sZW5ndGg7cy5zZXRVaW50MzIobyxhKTtpLnNldCh0LG8rNCk7bys9NCthfWFzc2VydChvPT09bi5ieXRlTGVuZ3RoLCJDc3NGb250SW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7cmV0dXJuIG59Y29uc3RydWN0b3IoZSl7dGhpcy4jTj1lO3RoaXMuI0c9bmV3IERhdGFWaWV3KHRoaXMuI04pO3RoaXMuIyQ9bmV3IFRleHREZWNvZGVyfSNWKGUpe2Fzc2VydChlPENzc0ZvbnRJbmZvLnN0cmluZ3MubGVuZ3RoLCJJbnZhbGlkIHN0cmluZyBpbmRleCIpO2xldCB0PTA7Zm9yKGxldCByPTA7cjxlO3IrKyl0Kz10aGlzLiNHLmdldFVpbnQzMih0KSs0O2NvbnN0IHI9dGhpcy4jRy5nZXRVaW50MzIodCk7cmV0dXJuIHRoaXMuIyQuZGVjb2RlKG5ldyBVaW50OEFycmF5KHRoaXMuI04sdCs0LHIpKX1nZXQgZm9udEZhbWlseSgpe3JldHVybiB0aGlzLiNWKDApfWdldCBmb250V2VpZ2h0KCl7cmV0dXJuIHRoaXMuI1YoMSl9Z2V0IGl0YWxpY0FuZ2xlKCl7cmV0dXJuIHRoaXMuI1YoMil9fWNsYXNzIFN5c3RlbUZvbnRJbmZveyNOOyNHOyMkO3N0YXRpYyBzdHJpbmdzPVsiY3NzIiwibG9hZGVkTmFtZSIsImJhc2VGb250TmFtZSIsInNyYyJdO3N0YXRpYyB3cml0ZShlKXtjb25zdCB0PW5ldyBUZXh0RW5jb2RlcixyPXt9O2xldCBhPTA7Zm9yKGNvbnN0IG4gb2YgU3lzdGVtRm9udEluZm8uc3RyaW5ncyl7Y29uc3QgaT10LmVuY29kZShlW25dKTtyW25dPWk7YSs9NCtpLmxlbmd0aH1hKz00O2xldCBuLGkscz0xK2E7aWYoZS5zdHlsZSl7bj10LmVuY29kZShlLnN0eWxlLnN0eWxlKTtpPXQuZW5jb2RlKGUuc3R5bGUud2VpZ2h0KTtzKz00K24ubGVuZ3RoKzQraS5sZW5ndGh9Y29uc3Qgbz1uZXcgQXJyYXlCdWZmZXIocyksYz1uZXcgVWludDhBcnJheShvKSxsPW5ldyBEYXRhVmlldyhvKTtsZXQgaD0wO2wuc2V0VWludDgoaCsrLGUuZ3Vlc3NGYWxsYmFjaz8xOjApO2wuc2V0VWludDMyKGgsMCk7aCs9NDthPTA7Zm9yKGNvbnN0IGUgb2YgU3lzdGVtRm9udEluZm8uc3RyaW5ncyl7Y29uc3QgdD1yW2VdLG49dC5sZW5ndGg7YSs9NCtuO2wuc2V0VWludDMyKGgsbik7Yy5zZXQodCxoKzQpO2grPTQrbn1sLnNldFVpbnQzMihoLWEtNCxhKTtpZihlLnN0eWxlKXtsLnNldFVpbnQzMihoLG4ubGVuZ3RoKTtjLnNldChuLGgrNCk7aCs9NCtuLmxlbmd0aDtsLnNldFVpbnQzMihoLGkubGVuZ3RoKTtjLnNldChpLGgrNCk7aCs9NCtpLmxlbmd0aH1hc3NlcnQoaDw9by5ieXRlTGVuZ3RoLCJTdWJzdGl0aW9uSW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7cmV0dXJuIG8udHJhbnNmZXJUb0ZpeGVkTGVuZ3RoKGgpfWNvbnN0cnVjdG9yKGUpe3RoaXMuI049ZTt0aGlzLiNHPW5ldyBEYXRhVmlldyh0aGlzLiNOKTt0aGlzLiMkPW5ldyBUZXh0RGVjb2Rlcn1nZXQgZ3Vlc3NGYWxsYmFjaygpe3JldHVybiAwIT09dGhpcy4jRy5nZXRVaW50OCgwKX0jVihlKXthc3NlcnQoZTxTeXN0ZW1Gb250SW5mby5zdHJpbmdzLmxlbmd0aCwiSW52YWxpZCBzdHJpbmcgaW5kZXgiKTtsZXQgdD01O2ZvcihsZXQgcj0wO3I8ZTtyKyspdCs9dGhpcy4jRy5nZXRVaW50MzIodCkrNDtjb25zdCByPXRoaXMuI0cuZ2V0VWludDMyKHQpO3JldHVybiB0aGlzLiMkLmRlY29kZShuZXcgVWludDhBcnJheSh0aGlzLiNOLHQrNCxyKSl9Z2V0IGNzcygpe3JldHVybiB0aGlzLiNWKDApfWdldCBsb2FkZWROYW1lKCl7cmV0dXJuIHRoaXMuI1YoMSl9Z2V0IGJhc2VGb250TmFtZSgpe3JldHVybiB0aGlzLiNWKDIpfWdldCBzcmMoKXtyZXR1cm4gdGhpcy4jVigzKX1nZXQgc3R5bGUoKXtsZXQgZT0xO2UrPTQrdGhpcy4jRy5nZXRVaW50MzIoZSk7Y29uc3QgdD10aGlzLiNHLmdldFVpbnQzMihlKSxyPXRoaXMuIyQuZGVjb2RlKG5ldyBVaW50OEFycmF5KHRoaXMuI04sZSs0LHQpKTtlKz00K3Q7Y29uc3QgYT10aGlzLiNHLmdldFVpbnQzMihlKTtyZXR1cm57c3R5bGU6cix3ZWlnaHQ6dGhpcy4jJC5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jTixlKzQsYSkpfX19Y2xhc3MgRm9udEluZm97c3RhdGljIGJvb2xzPVsiYmxhY2siLCJib2xkIiwiZGlzYWJsZUZvbnRGYWNlIiwiZm9udEV4dHJhUHJvcGVydGllcyIsImlzSW52YWxpZFBERmpzRm9udCIsImlzVHlwZTNGb250IiwiaXRhbGljIiwibWlzc2luZ0ZpbGUiLCJyZW1lYXN1cmUiLCJ2ZXJ0aWNhbCJdO3N0YXRpYyBudW1iZXJzPVsiYXNjZW50IiwiZGVmYXVsdFdpZHRoIiwiZGVzY2VudCJdO3N0YXRpYyBzdHJpbmdzPVsiZmFsbGJhY2tOYW1lIiwibG9hZGVkTmFtZSIsIm1pbWV0eXBlIiwibmFtZSJdO3N0YXRpYyNLPU1hdGguY2VpbCgyKnRoaXMuYm9vbHMubGVuZ3RoLzgpO3N0YXRpYyNKPXRoaXMuI0srOCp0aGlzLm51bWJlcnMubGVuZ3RoO3N0YXRpYyNZPXRoaXMuI0orMSs4O3N0YXRpYyNaPXRoaXMuI1krMSs0ODtzdGF0aWMjUT10aGlzLiNaKzErNjsjTjsjJDsjRztjb25zdHJ1Y3Rvcih7ZGF0YTplLGV4dHJhOnR9KXt0aGlzLiNOPWU7dGhpcy4jJD1uZXcgVGV4dERlY29kZXI7dGhpcy4jRz1uZXcgRGF0YVZpZXcodGhpcy4jTik7dCYmT2JqZWN0LmFzc2lnbih0aGlzLHQpfSNlZShlKXthc3NlcnQoZTxGb250SW5mby5ib29scy5sZW5ndGgsIkludmFsaWQgYm9vbGVhbiBpbmRleCIpO2NvbnN0IHQ9TWF0aC5mbG9vcihlLzQpLHI9MiplJTgsYT10aGlzLiNHLmdldFVpbnQ4KHQpPj5yJjM7cmV0dXJuIDA9PT1hP3ZvaWQgMDoyPT09YX1nZXQgYmxhY2soKXtyZXR1cm4gdGhpcy4jZWUoMCl9Z2V0IGJvbGQoKXtyZXR1cm4gdGhpcy4jZWUoMSl9Z2V0IGRpc2FibGVGb250RmFjZSgpe3JldHVybiB0aGlzLiNlZSgyKX1nZXQgZm9udEV4dHJhUHJvcGVydGllcygpe3JldHVybiB0aGlzLiNlZSgzKX1nZXQgaXNJbnZhbGlkUERGanNGb250KCl7cmV0dXJuIHRoaXMuI2VlKDQpfWdldCBpc1R5cGUzRm9udCgpe3JldHVybiB0aGlzLiNlZSg1KX1nZXQgaXRhbGljKCl7cmV0dXJuIHRoaXMuI2VlKDYpfWdldCBtaXNzaW5nRmlsZSgpe3JldHVybiB0aGlzLiNlZSg3KX1nZXQgcmVtZWFzdXJlKCl7cmV0dXJuIHRoaXMuI2VlKDgpfWdldCB2ZXJ0aWNhbCgpe3JldHVybiB0aGlzLiNlZSg5KX0jdGUoZSl7YXNzZXJ0KGU8Rm9udEluZm8ubnVtYmVycy5sZW5ndGgsIkludmFsaWQgbnVtYmVyIGluZGV4Iik7cmV0dXJuIHRoaXMuI0cuZ2V0RmxvYXQ2NChGb250SW5mby4jSys4KmUpfWdldCBhc2NlbnQoKXtyZXR1cm4gdGhpcy4jdGUoMCl9Z2V0IGRlZmF1bHRXaWR0aCgpe3JldHVybiB0aGlzLiN0ZSgxKX1nZXQgZGVzY2VudCgpe3JldHVybiB0aGlzLiN0ZSgyKX1nZXQgYmJveCgpe2xldCBlPUZvbnRJbmZvLiNKO2lmKDA9PT10aGlzLiNHLmdldFVpbnQ4KGUpKXJldHVybjtlKz0xO2NvbnN0IHQ9W107Zm9yKGxldCByPTA7cjw0O3IrKyl7dC5wdXNoKHRoaXMuI0cuZ2V0SW50MTYoZSwhMCkpO2UrPTJ9cmV0dXJuIHR9Z2V0IGZvbnRNYXRyaXgoKXtsZXQgZT1Gb250SW5mby4jWTtpZigwPT09dGhpcy4jRy5nZXRVaW50OChlKSlyZXR1cm47ZSs9MTtjb25zdCB0PVtdO2ZvcihsZXQgcj0wO3I8NjtyKyspe3QucHVzaCh0aGlzLiNHLmdldEZsb2F0NjQoZSwhMCkpO2UrPTh9cmV0dXJuIHR9Z2V0IGRlZmF1bHRWTWV0cmljcygpe2xldCBlPUZvbnRJbmZvLiNaO2lmKDA9PT10aGlzLiNHLmdldFVpbnQ4KGUpKXJldHVybjtlKz0xO2NvbnN0IHQ9W107Zm9yKGxldCByPTA7cjwzO3IrKyl7dC5wdXNoKHRoaXMuI0cuZ2V0SW50MTYoZSwhMCkpO2UrPTJ9cmV0dXJuIHR9I1YoZSl7YXNzZXJ0KGU8Rm9udEluZm8uc3RyaW5ncy5sZW5ndGgsIkludmFsaWQgc3RyaW5nIGluZGV4Iik7bGV0IHQ9Rm9udEluZm8uI1ErNDtmb3IobGV0IHI9MDtyPGU7cisrKXQrPXRoaXMuI0cuZ2V0VWludDMyKHQpKzQ7Y29uc3Qgcj10aGlzLiNHLmdldFVpbnQzMih0KSxhPW5ldyBVaW50OEFycmF5KHIpO2Euc2V0KG5ldyBVaW50OEFycmF5KHRoaXMuI04sdCs0LHIpKTtyZXR1cm4gdGhpcy4jJC5kZWNvZGUoYSl9Z2V0IGZhbGxiYWNrTmFtZSgpe3JldHVybiB0aGlzLiNWKDApfWdldCBsb2FkZWROYW1lKCl7cmV0dXJuIHRoaXMuI1YoMSl9Z2V0IG1pbWV0eXBlKCl7cmV0dXJuIHRoaXMuI1YoMil9Z2V0IG5hbWUoKXtyZXR1cm4gdGhpcy4jVigzKX1nZXQgZGF0YSgpe2xldCBlPUZvbnRJbmZvLiNRO2UrPTQrdGhpcy4jRy5nZXRVaW50MzIoZSk7ZSs9NCt0aGlzLiNHLmdldFVpbnQzMihlKTtlKz00K3RoaXMuI0cuZ2V0VWludDMyKGUpO2NvbnN0IHQ9dGhpcy4jRy5nZXRVaW50MzIoZSk7aWYoMCE9PXQpcmV0dXJuIG5ldyBVaW50OEFycmF5KHRoaXMuI04sZSs0LHQpfWNsZWFyRGF0YSgpe2xldCBlPUZvbnRJbmZvLiNRO2UrPTQrdGhpcy4jRy5nZXRVaW50MzIoZSk7ZSs9NCt0aGlzLiNHLmdldFVpbnQzMihlKTtlKz00K3RoaXMuI0cuZ2V0VWludDMyKGUpO2NvbnN0IHQ9dGhpcy4jRy5nZXRVaW50MzIoZSk7bmV3IFVpbnQ4QXJyYXkodGhpcy4jTixlKzQsdCkuZmlsbCgwKTt0aGlzLiNHLnNldFVpbnQzMihlLDApfWdldCBjc3NGb250SW5mbygpe2xldCBlPUZvbnRJbmZvLiNRO2UrPTQrdGhpcy4jRy5nZXRVaW50MzIoZSk7ZSs9NCt0aGlzLiNHLmdldFVpbnQzMihlKTtjb25zdCB0PXRoaXMuI0cuZ2V0VWludDMyKGUpO2lmKDA9PT10KXJldHVybiBudWxsO2NvbnN0IHI9bmV3IFVpbnQ4QXJyYXkodCk7ci5zZXQobmV3IFVpbnQ4QXJyYXkodGhpcy4jTixlKzQsdCkpO3JldHVybiBuZXcgQ3NzRm9udEluZm8oci5idWZmZXIpfWdldCBzeXN0ZW1Gb250SW5mbygpe2xldCBlPUZvbnRJbmZvLiNRO2UrPTQrdGhpcy4jRy5nZXRVaW50MzIoZSk7Y29uc3QgdD10aGlzLiNHLmdldFVpbnQzMihlKTtpZigwPT09dClyZXR1cm4gbnVsbDtjb25zdCByPW5ldyBVaW50OEFycmF5KHQpO3Iuc2V0KG5ldyBVaW50OEFycmF5KHRoaXMuI04sZSs0LHQpKTtyZXR1cm4gbmV3IFN5c3RlbUZvbnRJbmZvKHIuYnVmZmVyKX1zdGF0aWMgd3JpdGUoZSl7Y29uc3QgdD1lLnN5c3RlbUZvbnRJbmZvP1N5c3RlbUZvbnRJbmZvLndyaXRlKGUuc3lzdGVtRm9udEluZm8pOm51bGwscj1lLmNzc0ZvbnRJbmZvP0Nzc0ZvbnRJbmZvLndyaXRlKGUuY3NzRm9udEluZm8pOm51bGwsYT1uZXcgVGV4dEVuY29kZXIsbj17fTtsZXQgaT0wO2Zvcihjb25zdCB0IG9mIEZvbnRJbmZvLnN0cmluZ3Mpe25bdF09YS5lbmNvZGUoZVt0XSk7aSs9NCtuW3RdLmxlbmd0aH1jb25zdCBzPUZvbnRJbmZvLiNRKzQraSs0Kyh0P3QuYnl0ZUxlbmd0aDowKSs0KyhyP3IuYnl0ZUxlbmd0aDowKSs0KyhlLmRhdGE/ZS5kYXRhLmxlbmd0aDowKSxvPW5ldyBBcnJheUJ1ZmZlcihzKSxjPW5ldyBVaW50OEFycmF5KG8pLGw9bmV3IERhdGFWaWV3KG8pO2xldCBoPTA7Y29uc3QgdT1Gb250SW5mby5ib29scy5sZW5ndGg7bGV0IGQ9MCxmPTA7Zm9yKGxldCB0PTA7dDx1O3QrKyl7Y29uc3Qgcj1lW0ZvbnRJbmZvLmJvb2xzW3RdXTtkfD0odm9pZCAwPT09cj8wOnI/MjoxKTw8ZjtmKz0yO2lmKDg9PT1mfHx0PT09dS0xKXtsLnNldFVpbnQ4KGgrKyxkKTtkPTA7Zj0wfX1hc3NlcnQoaD09PUZvbnRJbmZvLiNLLCJGb250SW5mby53cml0ZTogQm9vbGVhbiBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpO2Zvcihjb25zdCB0IG9mIEZvbnRJbmZvLm51bWJlcnMpe2wuc2V0RmxvYXQ2NChoLGVbdF0pO2grPTh9YXNzZXJ0KGg9PT1Gb250SW5mby4jSiwiRm9udEluZm8ud3JpdGU6IE51bWJlciBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpO2lmKGUuYmJveCl7bC5zZXRVaW50OChoKyssNCk7Zm9yKGNvbnN0IHQgb2YgZS5iYm94KXtsLnNldEludDE2KGgsdCwhMCk7aCs9Mn19ZWxzZXtsLnNldFVpbnQ4KGgrKywwKTtoKz04fWFzc2VydChoPT09Rm9udEluZm8uI1ksIkZvbnRJbmZvLndyaXRlOiBCQm94IHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7aWYoZS5mb250TWF0cml4KXtsLnNldFVpbnQ4KGgrKyw2KTtmb3IoY29uc3QgdCBvZiBlLmZvbnRNYXRyaXgpe2wuc2V0RmxvYXQ2NChoLHQsITApO2grPTh9fWVsc2V7bC5zZXRVaW50OChoKyssMCk7aCs9NDh9YXNzZXJ0KGg9PT1Gb250SW5mby4jWiwiRm9udEluZm8ud3JpdGU6IEZvbnRNYXRyaXggcHJvcGVydGllcyBvZmZzZXQgbWlzbWF0Y2giKTtpZihlLmRlZmF1bHRWTWV0cmljcyl7bC5zZXRVaW50OChoKyssMSk7Zm9yKGNvbnN0IHQgb2YgZS5kZWZhdWx0Vk1ldHJpY3Mpe2wuc2V0SW50MTYoaCx0LCEwKTtoKz0yfX1lbHNle2wuc2V0VWludDgoaCsrLDApO2grPTZ9YXNzZXJ0KGg9PT1Gb250SW5mby4jUSwiRm9udEluZm8ud3JpdGU6IERlZmF1bHRWTWV0cmljcyBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpO2wuc2V0VWludDMyKEZvbnRJbmZvLiNRLDApO2grPTQ7Zm9yKGNvbnN0IGUgb2YgRm9udEluZm8uc3RyaW5ncyl7Y29uc3QgdD1uW2VdLHI9dC5sZW5ndGg7bC5zZXRVaW50MzIoaCxyKTtjLnNldCh0LGgrNCk7aCs9NCtyfWwuc2V0VWludDMyKEZvbnRJbmZvLiNRLGgtRm9udEluZm8uI1EtNCk7aWYodCl7Y29uc3QgZT10LmJ5dGVMZW5ndGg7bC5zZXRVaW50MzIoaCxlKTthc3NlcnQoaCs0K2U8PW8uYnl0ZUxlbmd0aCwiRm9udEluZm8ud3JpdGU6IEJ1ZmZlciBvdmVyZmxvdyBhdCBzeXN0ZW1Gb250SW5mbyIpO2Muc2V0KG5ldyBVaW50OEFycmF5KHQpLGgrNCk7aCs9NCtlfWVsc2V7bC5zZXRVaW50MzIoaCwwKTtoKz00fWlmKHIpe2NvbnN0IGU9ci5ieXRlTGVuZ3RoO2wuc2V0VWludDMyKGgsZSk7YXNzZXJ0KGgrNCtlPD1vLmJ5dGVMZW5ndGgsIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3cgYXQgY3NzRm9udEluZm8iKTtjLnNldChuZXcgVWludDhBcnJheShyKSxoKzQpO2grPTQrZX1lbHNle2wuc2V0VWludDMyKGgsMCk7aCs9NH1pZih2b2lkIDA9PT1lLmRhdGEpe2wuc2V0VWludDMyKGgsMCk7aCs9NH1lbHNle2wuc2V0VWludDMyKGgsZS5kYXRhLmxlbmd0aCk7Yy5zZXQoZS5kYXRhLGgrNCk7aCs9NCtlLmRhdGEubGVuZ3RofWFzc2VydChoPD1vLmJ5dGVMZW5ndGgsIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3ciKTtyZXR1cm4gby50cmFuc2ZlclRvRml4ZWRMZW5ndGgoaCl9fWNvbnN0IGNpPXtzdHlsZToibm9ybWFsIix3ZWlnaHQ6Im5vcm1hbCJ9LGxpPXtzdHlsZToibm9ybWFsIix3ZWlnaHQ6ImJvbGQifSxoaT17c3R5bGU6Iml0YWxpYyIsd2VpZ2h0OiJub3JtYWwifSx1aT17c3R5bGU6Iml0YWxpYyIsd2VpZ2h0OiJib2xkIn0sZGk9bmV3IE1hcChbWyJUaW1lcy1Sb21hbiIse2xvY2FsOlsiVGltZXMgTmV3IFJvbWFuIiwiVGltZXMtUm9tYW4iLCJUaW1lcyIsIkxpYmVyYXRpb24gU2VyaWYiLCJOaW1idXMgUm9tYW4iLCJOaW1idXMgUm9tYW4gTCIsIlRpbm9zIiwiVGhvcm5kYWxlIiwiVGVYIEd5cmUgVGVybWVzIiwiRnJlZVNlcmlmIiwiTGludXggTGliZXJ0aW5lIE8iLCJMaWJlcnRpbnVzIFNlcmlmIiwiRGVqYVZ1IFNlcmlmIiwiQml0c3RyZWFtIFZlcmEgU2VyaWYiLCJVYnVudHUiXSxzdHlsZTpjaSx1bHRpbWF0ZToic2VyaWYifV0sWyJUaW1lcy1Cb2xkIix7YWxpYXM6IlRpbWVzLVJvbWFuIixzdHlsZTpsaSx1bHRpbWF0ZToic2VyaWYifV0sWyJUaW1lcy1JdGFsaWMiLHthbGlhczoiVGltZXMtUm9tYW4iLHN0eWxlOmhpLHVsdGltYXRlOiJzZXJpZiJ9XSxbIlRpbWVzLUJvbGRJdGFsaWMiLHthbGlhczoiVGltZXMtUm9tYW4iLHN0eWxlOnVpLHVsdGltYXRlOiJzZXJpZiJ9XSxbIkhlbHZldGljYSIse2xvY2FsOlsiSGVsdmV0aWNhIiwiSGVsdmV0aWNhIE5ldWUiLCJBcmlhbCIsIkFyaWFsIE5vdmEiLCJMaWJlcmF0aW9uIFNhbnMiLCJBcmltbyIsIk5pbWJ1cyBTYW5zIiwiTmltYnVzIFNhbnMgTCIsIkEwMzAiLCJUZVggR3lyZSBIZXJvcyIsIkZyZWVTYW5zIiwiRGVqYVZ1IFNhbnMiLCJBbGJhbnkiLCJCaXRzdHJlYW0gVmVyYSBTYW5zIiwiQXJpYWwgVW5pY29kZSBNUyIsIk1pY3Jvc29mdCBTYW5zIFNlcmlmIiwiQXBwbGUgU3ltYm9scyIsIkNhbnRhcmVsbCJdLHBhdGg6IkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIudHRmIixzdHlsZTpjaSx1bHRpbWF0ZToic2Fucy1zZXJpZiJ9XSxbIkhlbHZldGljYS1Cb2xkIix7YWxpYXM6IkhlbHZldGljYSIscGF0aDoiTGliZXJhdGlvblNhbnMtQm9sZC50dGYiLHN0eWxlOmxpLHVsdGltYXRlOiJzYW5zLXNlcmlmIn1dLFsiSGVsdmV0aWNhLU9ibGlxdWUiLHthbGlhczoiSGVsdmV0aWNhIixwYXRoOiJMaWJlcmF0aW9uU2Fucy1JdGFsaWMudHRmIixzdHlsZTpoaSx1bHRpbWF0ZToic2Fucy1zZXJpZiJ9XSxbIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSIse2FsaWFzOiJIZWx2ZXRpY2EiLHBhdGg6IkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMudHRmIixzdHlsZTp1aSx1bHRpbWF0ZToic2Fucy1zZXJpZiJ9XSxbIkNvdXJpZXIiLHtsb2NhbDpbIkNvdXJpZXIiLCJDb3VyaWVyIE5ldyIsIkxpYmVyYXRpb24gTW9ubyIsIk5pbWJ1cyBNb25vIiwiTmltYnVzIE1vbm8gTCIsIkNvdXNpbmUiLCJDdW1iZXJsYW5kIiwiVGVYIEd5cmUgQ3Vyc29yIiwiRnJlZU1vbm8iLCJMaW51eCBMaWJlcnRpbmUgTW9ubyBPIiwiTGliZXJ0aW51cyBNb25vIl0sc3R5bGU6Y2ksdWx0aW1hdGU6Im1vbm9zcGFjZSJ9XSxbIkNvdXJpZXItQm9sZCIse2FsaWFzOiJDb3VyaWVyIixzdHlsZTpsaSx1bHRpbWF0ZToibW9ub3NwYWNlIn1dLFsiQ291cmllci1PYmxpcXVlIix7YWxpYXM6IkNvdXJpZXIiLHN0eWxlOmhpLHVsdGltYXRlOiJtb25vc3BhY2UifV0sWyJDb3VyaWVyLUJvbGRPYmxpcXVlIix7YWxpYXM6IkNvdXJpZXIiLHN0eWxlOnVpLHVsdGltYXRlOiJtb25vc3BhY2UifV0sWyJBcmlhbEJsYWNrIix7bG9jYWw6WyJBcmlhbCBCbGFjayJdLHN0eWxlOntzdHlsZToibm9ybWFsIix3ZWlnaHQ6IjkwMCJ9LGZhbGxiYWNrOiJIZWx2ZXRpY2EtQm9sZCJ9XSxbIkFyaWFsQmxhY2stQm9sZCIse2FsaWFzOiJBcmlhbEJsYWNrIn1dLFsiQXJpYWxCbGFjay1JdGFsaWMiLHthbGlhczoiQXJpYWxCbGFjayIsc3R5bGU6e3N0eWxlOiJpdGFsaWMiLHdlaWdodDoiOTAwIn0sZmFsbGJhY2s6IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJ9XSxbIkFyaWFsQmxhY2stQm9sZEl0YWxpYyIse2FsaWFzOiJBcmlhbEJsYWNrLUl0YWxpYyJ9XSxbIkFyaWFsTmFycm93Iix7bG9jYWw6WyJBcmlhbCBOYXJyb3ciLCJMaWJlcmF0aW9uIFNhbnMgTmFycm93IiwiSGVsdmV0aWNhIENvbmRlbnNlZCIsIk5pbWJ1cyBTYW5zIE5hcnJvdyIsIlRlWCBHeXJlIEhlcm9zIENuIl0sc3R5bGU6Y2ksZmFsbGJhY2s6IkhlbHZldGljYSJ9XSxbIkFyaWFsTmFycm93LUJvbGQiLHthbGlhczoiQXJpYWxOYXJyb3ciLHN0eWxlOmxpLGZhbGxiYWNrOiJIZWx2ZXRpY2EtQm9sZCJ9XSxbIkFyaWFsTmFycm93LUl0YWxpYyIse2FsaWFzOiJBcmlhbE5hcnJvdyIsc3R5bGU6aGksZmFsbGJhY2s6IkhlbHZldGljYS1PYmxpcXVlIn1dLFsiQXJpYWxOYXJyb3ctQm9sZEl0YWxpYyIse2FsaWFzOiJBcmlhbE5hcnJvdyIsc3R5bGU6dWksZmFsbGJhY2s6IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJ9XSxbIkNhbGlicmkiLHtsb2NhbDpbIkNhbGlicmkiLCJDYXJsaXRvIl0sc3R5bGU6Y2ksZmFsbGJhY2s6IkhlbHZldGljYSJ9XSxbIkNhbGlicmktQm9sZCIse2FsaWFzOiJDYWxpYnJpIixzdHlsZTpsaSxmYWxsYmFjazoiSGVsdmV0aWNhLUJvbGQifV0sWyJDYWxpYnJpLUl0YWxpYyIse2FsaWFzOiJDYWxpYnJpIixzdHlsZTpoaSxmYWxsYmFjazoiSGVsdmV0aWNhLU9ibGlxdWUifV0sWyJDYWxpYnJpLUJvbGRJdGFsaWMiLHthbGlhczoiQ2FsaWJyaSIsc3R5bGU6dWksZmFsbGJhY2s6IkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJ9XSxbIldpbmdkaW5ncyIse2xvY2FsOlsiV2luZ2RpbmdzIiwiVVJXIERpbmdiYXRzIl0sc3R5bGU6Y2l9XSxbIldpbmdkaW5ncy1SZWd1bGFyIix7YWxpYXM6IldpbmdkaW5ncyJ9XSxbIldpbmdkaW5ncy1Cb2xkIix7YWxpYXM6IldpbmdkaW5ncyJ9XV0pLGZpPW5ldyBNYXAoW1siQXJpYWwtQmxhY2siLCJBcmlhbEJsYWNrIl1dKTtmdW5jdGlvbiBnZXRGYW1pbHlOYW1lKGUpe2NvbnN0IHQ9bmV3IFNldChbInRoaW4iLCJleHRyYWxpZ2h0IiwidWx0cmFsaWdodCIsImRlbWlsaWdodCIsInNlbWlsaWdodCIsImxpZ2h0IiwiYm9vayIsInJlZ3VsYXIiLCJub3JtYWwiLCJtZWRpdW0iLCJkZW1pYm9sZCIsInNlbWlib2xkIiwiYm9sZCIsImV4dHJhYm9sZCIsInVsdHJhYm9sZCIsImJsYWNrIiwiaGVhdnkiLCJleHRyYWJsYWNrIiwidWx0cmFibGFjayIsInJvbWFuIiwiaXRhbGljIiwib2JsaXF1ZSIsInVsdHJhY29uZGVuc2VkIiwiZXh0cmFjb25kZW5zZWQiLCJjb25kZW5zZWQiLCJzZW1pY29uZGVuc2VkIiwibm9ybWFsIiwic2VtaWV4cGFuZGVkIiwiZXhwYW5kZWQiLCJleHRyYWV4cGFuZGVkIiwidWx0cmFleHBhbmRlZCIsImJvbGRpdGFsaWMiXSk7cmV0dXJuIGUuc3BsaXQoL1stICwrXSsvZykuZmlsdGVyKGU9PiF0LmhhcyhlLnRvTG93ZXJDYXNlKCkpKS5qb2luKCIgIil9ZnVuY3Rpb24gZ2VuZXJhdGVGb250KHthbGlhczplLGxvY2FsOnQscGF0aDpyLGZhbGxiYWNrOmEsc3R5bGU6bix1bHRpbWF0ZTppfSxzLG8sYz0hMCxsPSEwLGg9IiIpe2NvbnN0IHU9e3N0eWxlOm51bGwsdWx0aW1hdGU6bnVsbH07aWYodCl7Y29uc3QgZT1oP2AgJHtofWA6IiI7Zm9yKGNvbnN0IHIgb2YgdClzLnB1c2goYGxvY2FsKCR7cn0ke2V9KWApfWlmKGUpe2NvbnN0IHQ9ZGkuZ2V0KGUpLGk9aHx8ZnVuY3Rpb24gZ2V0U3R5bGVUb0FwcGVuZChlKXtzd2l0Y2goZSl7Y2FzZSBsaTpyZXR1cm4iQm9sZCI7Y2FzZSBoaTpyZXR1cm4iSXRhbGljIjtjYXNlIHVpOnJldHVybiJCb2xkIEl0YWxpYyI7ZGVmYXVsdDppZigiYm9sZCI9PT1lPy53ZWlnaHQpcmV0dXJuIkJvbGQiO2lmKCJpdGFsaWMiPT09ZT8uc3R5bGUpcmV0dXJuIkl0YWxpYyJ9cmV0dXJuIiJ9KG4pO09iamVjdC5hc3NpZ24odSxnZW5lcmF0ZUZvbnQodCxzLG8sYyYmIWEsbCYmIXIsaSkpfW4mJih1LnN0eWxlPW4pO2kmJih1LnVsdGltYXRlPWkpO2lmKGMmJmEpe2NvbnN0IGU9ZGkuZ2V0KGEpLHt1bHRpbWF0ZTp0fT1nZW5lcmF0ZUZvbnQoZSxzLG8sYyxsJiYhcixoKTt1LnVsdGltYXRlfHw9dH1sJiZyJiZvJiZzLnB1c2goYHVybCgke299JHtyfSlgKTtyZXR1cm4gdX1mdW5jdGlvbiBnZXRGb250U3Vic3RpdHV0aW9uKGUsdCxyLGEsbixpKXtpZihhLnN0YXJ0c1dpdGgoIkludmFsaWRQREZqc0ZvbnRfIikpcmV0dXJuIG51bGw7IlRydWVUeXBlIiE9PWkmJiJUeXBlMSIhPT1pfHwhL15bQS1aXXs2fVwrLy50ZXN0KGEpfHwoYT1hLnNsaWNlKDcpKTtjb25zdCBzPWE9bm9ybWFsaXplRm9udE5hbWUoYSk7bGV0IG89ZS5nZXQocyk7aWYobylyZXR1cm4gbztsZXQgYz1kaS5nZXQoYSk7aWYoIWMpZm9yKGNvbnN0W2UsdF1vZiBmaSlpZihhLnN0YXJ0c1dpdGgoZSkpe2E9YCR7dH0ke2Euc3Vic3RyaW5nKGUubGVuZ3RoKX1gO2M9ZGkuZ2V0KGEpO2JyZWFrfWxldCBsPSExO2lmKCFjKXtjPWRpLmdldChuKTtsPSEwfWNvbnN0IGg9YCR7dC5nZXREb2NJZCgpfV9zJHt0LmNyZWF0ZUZvbnRJZCgpfWA7aWYoIWMpe2lmKCF2YWxpZGF0ZUZvbnROYW1lKGEpKXt3YXJuKGBDYW5ub3Qgc3Vic3RpdHV0ZSB0aGUgZm9udCBiZWNhdXNlIG9mIGl0cyBuYW1lOiAke2F9YCk7ZS5zZXQocyxudWxsKTtyZXR1cm4gbnVsbH1jb25zdCB0PS9ib2xkL2dpLnRlc3QoYSkscj0vb2JsaXF1ZXxpdGFsaWMvZ2kudGVzdChhKSxuPXQmJnImJnVpfHx0JiZsaXx8ciYmaGl8fGNpO289e2NzczpgIiR7Z2V0RmFtaWx5TmFtZShhKX0iLCR7aH1gLGd1ZXNzRmFsbGJhY2s6ITAsbG9hZGVkTmFtZTpoLGJhc2VGb250TmFtZTphLHNyYzpgbG9jYWwoJHthfSlgLHN0eWxlOm59O2Uuc2V0KHMsbyk7cmV0dXJuIG99Y29uc3QgdT1bXTtsJiZ2YWxpZGF0ZUZvbnROYW1lKGEpJiZ1LnB1c2goYGxvY2FsKCR7YX0pYCk7Y29uc3R7c3R5bGU6ZCx1bHRpbWF0ZTpmfT1nZW5lcmF0ZUZvbnQoYyx1LHIpLGc9bnVsbD09PWYscD1nPyIiOmAsJHtmfWA7bz17Y3NzOmAiJHtnZXRGYW1pbHlOYW1lKGEpfSIsJHtofSR7cH1gLGd1ZXNzRmFsbGJhY2s6Zyxsb2FkZWROYW1lOmgsYmFzZUZvbnROYW1lOmEsc3JjOnUuam9pbigiLCIpLHN0eWxlOmR9O2Uuc2V0KHMsbyk7cmV0dXJuIG99Y29uc3QgZ2k9MzI4NTM3NzUyMCxwaT00Mjk0OTAxNzYwLG1pPTY1NTM1O2NsYXNzIE11cm11ckhhc2gzXzY0e2NvbnN0cnVjdG9yKGUpe3RoaXMuaDE9ZT80Mjk0OTY3Mjk1JmU6Z2k7dGhpcy5oMj1lPzQyOTQ5NjcyOTUmZTpnaX11cGRhdGUoZSl7bGV0IHQscjtpZigic3RyaW5nIj09dHlwZW9mIGUpe3Q9bmV3IFVpbnQ4QXJyYXkoMiplLmxlbmd0aCk7cj0wO2ZvcihsZXQgYT0wLG49ZS5sZW5ndGg7YTxuO2ErKyl7Y29uc3Qgbj1lLmNoYXJDb2RlQXQoYSk7aWYobjw9MjU1KXRbcisrXT1uO2Vsc2V7dFtyKytdPW4+Pj44O3RbcisrXT0yNTUmbn19fWVsc2V7aWYoIUFycmF5QnVmZmVyLmlzVmlldyhlKSl0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgZGF0YSBmb3JtYXQsIG11c3QgYmUgYSBzdHJpbmcgb3IgVHlwZWRBcnJheS4iKTt0PWUuc2xpY2UoKTtyPXQuYnl0ZUxlbmd0aH1jb25zdCBhPXI+PjIsbj1yLTQqYSxpPW5ldyBVaW50MzJBcnJheSh0LmJ1ZmZlciwwLGEpO2xldCBzPTAsbz0wLGM9dGhpcy5oMSxsPXRoaXMuaDI7Y29uc3QgaD0zNDMyOTE4MzUzLHU9NDYxODQ1OTA3LGQ9MTE2MDEsZj0xMzcxNTtmb3IobGV0IGU9MDtlPGE7ZSsrKWlmKDEmZSl7cz1pW2VdO3M9cypoJnBpfHMqZCZtaTtzPXM8PDE1fHM+Pj4xNztzPXMqdSZwaXxzKmYmbWk7Y149cztjPWM8PDEzfGM+Pj4xOTtjPTUqYyszODY0MjkyMTk2fWVsc2V7bz1pW2VdO289bypoJnBpfG8qZCZtaTtvPW88PDE1fG8+Pj4xNztvPW8qdSZwaXxvKmYmbWk7bF49bztsPWw8PDEzfGw+Pj4xOTtsPTUqbCszODY0MjkyMTk2fXM9MDtzd2l0Y2gobil7Y2FzZSAzOnNePXRbNCphKzJdPDwxNjtjYXNlIDI6c149dFs0KmErMV08PDg7Y2FzZSAxOnNePXRbNCphXTtzPXMqaCZwaXxzKmQmbWk7cz1zPDwxNXxzPj4+MTc7cz1zKnUmcGl8cypmJm1pOzEmYT9jXj1zOmxePXN9dGhpcy5oMT1jO3RoaXMuaDI9bH1oZXhkaWdlc3QoKXtsZXQgZT10aGlzLmgxLHQ9dGhpcy5oMjtlXj10Pj4+MTtlPTM5ODE4MDY3OTcqZSZwaXwzNjA0NSplJm1pO3Q9NDI4MzU0MzUxMSp0JnBpfCgyOTUwMTYzNzk3Kih0PDwxNnxlPj4+MTYpJnBpKT4+PjE2O2VePXQ+Pj4xO2U9NDQ0OTg0NDAzKmUmcGl8NjA0OTkqZSZtaTt0PTMzMDE4ODIzNjYqdCZwaXwoMzEyMDQzNzg5MyoodDw8MTZ8ZT4+PjE2KSZwaSk+Pj4xNjtlXj10Pj4+MTtyZXR1cm4oZT4+PjApLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCIwIikrKHQ+Pj4wKS50b1N0cmluZygxNikucGFkU3RhcnQoOCwiMCIpfX1mdW5jdGlvbiByZXNpemVJbWFnZU1hc2soZSx0LHIsYSxuLGkpe2NvbnN0IHM9bippO2xldCBvO289dDw9OD9uZXcgVWludDhBcnJheShzKTp0PD0xNj9uZXcgVWludDE2QXJyYXkocyk6bmV3IFVpbnQzMkFycmF5KHMpO2NvbnN0IGM9ci9uLGw9YS9pO2xldCBoLHUsZCxmLGc9MDtjb25zdCBwPW5ldyBVaW50MTZBcnJheShuKSxtPXI7Zm9yKGg9MDtoPG47aCsrKXBbaF09TWF0aC5mbG9vcihoKmMpO2ZvcihoPTA7aDxpO2grKyl7ZD1NYXRoLmZsb29yKGgqbCkqbTtmb3IodT0wO3U8bjt1Kyspe2Y9ZCtwW3VdO29bZysrXT1lW2ZdfX1yZXR1cm4gb31jbGFzcyBQREZJbWFnZXtjb25zdHJ1Y3Rvcih7eHJlZjplLHJlczp0LGltYWdlOnIsaXNJbmxpbmU6YT0hMSxzbWFzazpuPW51bGwsbWFzazppPW51bGwsaXNNYXNrOnM9ITEscGRmRnVuY3Rpb25GYWN0b3J5Om8sZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOmMsbG9jYWxDb2xvclNwYWNlQ2FjaGU6bH0pe3RoaXMuaW1hZ2U9cjtjb25zdCBoPXIuZGljdCx1PWguZ2V0KCJGIiwiRmlsdGVyIik7bGV0IGQ7aWYodSBpbnN0YW5jZW9mIE5hbWUpZD11Lm5hbWU7ZWxzZSBpZihBcnJheS5pc0FycmF5KHUpKXtjb25zdCB0PWUuZmV0Y2hJZlJlZih1WzBdKTt0IGluc3RhbmNlb2YgTmFtZSYmKGQ9dC5uYW1lKX1zd2l0Y2goZCl7Y2FzZSJKUFhEZWNvZGUiOih7d2lkdGg6ci53aWR0aCxoZWlnaHQ6ci5oZWlnaHQsY29tcG9uZW50c0NvdW50OnIubnVtQ29tcHMsYml0c1BlckNvbXBvbmVudDpyLmJpdHNQZXJDb21wb25lbnR9PUpweEltYWdlLnBhcnNlSW1hZ2VQcm9wZXJ0aWVzKHIuc3RyZWFtKSk7ci5zdHJlYW0ucmVzZXQoKTtjb25zdCBlPUltYWdlUmVzaXplci5nZXRSZWR1Y2VQb3dlckZvckpQWChyLndpZHRoLHIuaGVpZ2h0LHIubnVtQ29tcHMpO3RoaXMuanB4RGVjb2Rlck9wdGlvbnM9e251bUNvbXBvbmVudHM6MCxpc0luZGV4ZWRDb2xvcm1hcDohMSxzbWFza0luRGF0YTpoLmhhcygiU01hc2tJbkRhdGEiKSxyZWR1Y2VQb3dlcjplfTtpZihlKXtjb25zdCB0PTIqKmU7ci53aWR0aD1NYXRoLmNlaWwoci53aWR0aC90KTtyLmhlaWdodD1NYXRoLmNlaWwoci5oZWlnaHQvdCl9YnJlYWs7Y2FzZSJKQklHMkRlY29kZSI6ci5iaXRzUGVyQ29tcG9uZW50PTE7ci5udW1Db21wcz0xfWxldCBmPWguZ2V0KCJXIiwiV2lkdGgiKSxnPWguZ2V0KCJIIiwiSGVpZ2h0Iik7aWYoTnVtYmVyLmlzSW50ZWdlcihyLndpZHRoKSYmci53aWR0aD4wJiZOdW1iZXIuaXNJbnRlZ2VyKHIuaGVpZ2h0KSYmci5oZWlnaHQ+MCYmKHIud2lkdGghPT1mfHxyLmhlaWdodCE9PWcpKXt3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIGltYWdlIGRhdGEsIHJhdGhlciB0aGFuIHRoZSBpbWFnZSBkaWN0aW9uYXJ5LiIpO2Y9ci53aWR0aDtnPXIuaGVpZ2h0fWVsc2V7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIGYmJmY+MCx0PSJudW1iZXIiPT10eXBlb2YgZyYmZz4wO2lmKCFlfHwhdCl7aWYoIXIuZmFsbGJhY2tEaW1zKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBpbWFnZSB3aWR0aDogJHtmfSBvciBoZWlnaHQ6ICR7Z31gKTt3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIHBhcmVudCBpbWFnZSwgZm9yIFNNYXNrL01hc2sgZGF0YS4iKTtlfHwoZj1yLmZhbGxiYWNrRGltcy53aWR0aCk7dHx8KGc9ci5mYWxsYmFja0RpbXMuaGVpZ2h0KX19dGhpcy53aWR0aD1mO3RoaXMuaGVpZ2h0PWc7dGhpcy5pbnRlcnBvbGF0ZT1oLmdldCgiSSIsIkludGVycG9sYXRlIik7dGhpcy5pbWFnZU1hc2s9aC5nZXQoIklNIiwiSW1hZ2VNYXNrIil8fCExO3RoaXMubWF0dGU9aC5nZXQoIk1hdHRlIil8fCExO2xldCBwPXIuYml0c1BlckNvbXBvbmVudDtpZighcCl7cD1oLmdldCgiQlBDIiwiQml0c1BlckNvbXBvbmVudCIpO2lmKCFwKXtpZighdGhpcy5pbWFnZU1hc2spdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBCaXRzIHBlciBjb21wb25lbnQgbWlzc2luZyBpbiBpbWFnZTogJHt0aGlzLmltYWdlTWFza31gKTtwPTF9fXRoaXMuYnBjPXA7aWYoIXRoaXMuaW1hZ2VNYXNrKXtsZXQgbj1oLmdldFJhdygiQ1MiKXx8aC5nZXRSYXcoIkNvbG9yU3BhY2UiKTtjb25zdCBpPSEhbjtpZihpKXRoaXMuanB4RGVjb2Rlck9wdGlvbnM/LnNtYXNrSW5EYXRhJiYobj1OYW1lLmdldCgiRGV2aWNlUkdCQSIpKTtlbHNlIGlmKHRoaXMuanB4RGVjb2Rlck9wdGlvbnMpbj1OYW1lLmdldCgiRGV2aWNlUkdCQSIpO2Vsc2Ugc3dpdGNoKHIubnVtQ29tcHMpe2Nhc2UgMTpuPU5hbWUuZ2V0KCJEZXZpY2VHcmF5Iik7YnJlYWs7Y2FzZSAzOm49TmFtZS5nZXQoIkRldmljZVJHQiIpO2JyZWFrO2Nhc2UgNDpuPU5hbWUuZ2V0KCJEZXZpY2VDTVlLIik7YnJlYWs7ZGVmYXVsdDp0aHJvdyBuZXcgRXJyb3IoYEltYWdlcyB3aXRoICR7ci5udW1Db21wc30gY29sb3IgY29tcG9uZW50cyBub3Qgc3VwcG9ydGVkLmApfXRoaXMuY29sb3JTcGFjZT1Db2xvclNwYWNlVXRpbHMucGFyc2Uoe2NzOm4seHJlZjplLHJlc291cmNlczphP3Q6bnVsbCxwZGZGdW5jdGlvbkZhY3Rvcnk6byxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6Yyxsb2NhbENvbG9yU3BhY2VDYWNoZTpsfSk7dGhpcy5udW1Db21wcz10aGlzLmNvbG9yU3BhY2UubnVtQ29tcHM7aWYodGhpcy5qcHhEZWNvZGVyT3B0aW9ucyl7dGhpcy5qcHhEZWNvZGVyT3B0aW9ucy5udW1Db21wb25lbnRzPWk/dGhpcy5udW1Db21wczowO3RoaXMuanB4RGVjb2Rlck9wdGlvbnMuaXNJbmRleGVkQ29sb3JtYXA9IkluZGV4ZWQiPT09dGhpcy5jb2xvclNwYWNlLm5hbWV9fXRoaXMuZGVjb2RlPWguZ2V0QXJyYXkoIkQiLCJEZWNvZGUiKTt0aGlzLm5lZWRzRGVjb2RlPSExO2lmKHRoaXMuZGVjb2RlJiYodGhpcy5jb2xvclNwYWNlJiYhdGhpcy5jb2xvclNwYWNlLmlzRGVmYXVsdERlY29kZSh0aGlzLmRlY29kZSxwKXx8cyYmIUNvbG9yU3BhY2UuaXNEZWZhdWx0RGVjb2RlKHRoaXMuZGVjb2RlLDEpKSl7dGhpcy5uZWVkc0RlY29kZT0hMDtjb25zdCBlPSgxPDxwKS0xO3RoaXMuZGVjb2RlQ29lZmZpY2llbnRzPVtdO3RoaXMuZGVjb2RlQWRkZW5kcz1bXTtjb25zdCB0PSJJbmRleGVkIj09PXRoaXMuY29sb3JTcGFjZT8ubmFtZTtmb3IobGV0IHI9MCxhPTA7cjx0aGlzLmRlY29kZS5sZW5ndGg7cis9MiwrK2Epe2NvbnN0IG49dGhpcy5kZWNvZGVbcl0saT10aGlzLmRlY29kZVtyKzFdO3RoaXMuZGVjb2RlQ29lZmZpY2llbnRzW2FdPXQ/KGktbikvZTppLW47dGhpcy5kZWNvZGVBZGRlbmRzW2FdPXQ/bjplKm59fWlmKG4pe24uZmFsbGJhY2tEaW1zPz89e3dpZHRoOmYsaGVpZ2h0Omd9O3RoaXMuc21hc2s9bmV3IFBERkltYWdlKHt4cmVmOmUscmVzOnQsaW1hZ2U6bixpc0lubGluZTphLHBkZkZ1bmN0aW9uRmFjdG9yeTpvLGdsb2JhbENvbG9yU3BhY2VDYWNoZTpjLGxvY2FsQ29sb3JTcGFjZUNhY2hlOmx9KX1lbHNlIGlmKGkpaWYoaSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pe2lmKGkuZGljdC5nZXQoIklNIiwiSW1hZ2VNYXNrIikpe2kuZmFsbGJhY2tEaW1zPz89e3dpZHRoOmYsaGVpZ2h0Omd9O3RoaXMubWFzaz1uZXcgUERGSW1hZ2Uoe3hyZWY6ZSxyZXM6dCxpbWFnZTppLGlzSW5saW5lOmEsaXNNYXNrOiEwLHBkZkZ1bmN0aW9uRmFjdG9yeTpvLGdsb2JhbENvbG9yU3BhY2VDYWNoZTpjLGxvY2FsQ29sb3JTcGFjZUNhY2hlOmx9KX1lbHNlIHdhcm4oIklnbm9yaW5nIC9NYXNrIGluIGltYWdlIHdpdGhvdXQgL0ltYWdlTWFzay4iKX1lbHNlIHRoaXMubWFzaz1pfXN0YXRpYyBhc3luYyBidWlsZEltYWdlKHt4cmVmOmUscmVzOnQsaW1hZ2U6cixpc0lubGluZTphPSExLHBkZkZ1bmN0aW9uRmFjdG9yeTpuLGdsb2JhbENvbG9yU3BhY2VDYWNoZTppLGxvY2FsQ29sb3JTcGFjZUNhY2hlOnN9KXtjb25zdCBvPXI7bGV0IGM9bnVsbCxsPW51bGw7Y29uc3QgaD1yLmRpY3QuZ2V0KCJTTWFzayIpLHU9ci5kaWN0LmdldCgiTWFzayIpO2g/aCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0/Yz1oOndhcm4oIlVuc3VwcG9ydGVkIC9TTWFzayBmb3JtYXQuIik6dSYmKHUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtfHxBcnJheS5pc0FycmF5KHUpP2w9dTp3YXJuKCJVbnN1cHBvcnRlZCAvTWFzayBmb3JtYXQuIikpO3JldHVybiBuZXcgUERGSW1hZ2Uoe3hyZWY6ZSxyZXM6dCxpbWFnZTpvLGlzSW5saW5lOmEsc21hc2s6YyxtYXNrOmwscGRmRnVuY3Rpb25GYWN0b3J5Om4sZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOmksbG9jYWxDb2xvclNwYWNlQ2FjaGU6c30pfXN0YXRpYyBhc3luYyBjcmVhdGVNYXNrKHtpbWFnZTplLGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOnQ9ITF9KXtjb25zdHtkaWN0OnJ9PWUsYT1yLmdldCgiVyIsIldpZHRoIiksbj1yLmdldCgiSCIsIkhlaWdodCIpLGk9ci5nZXQoIkkiLCJJbnRlcnBvbGF0ZSIpLHM9ci5nZXRBcnJheSgiRCIsIkRlY29kZSIpLG89cz8uWzBdPjAsYz0oYSs3Pj4zKSpuLGw9ZS5nZXRCeXRlcyhjKSxoPTE9PT1hJiYxPT09biYmbz09PSgwPT09bC5sZW5ndGh8fCEhKDEyOCZsWzBdKSk7aWYoaClyZXR1cm57aXNTaW5nbGVPcGFxdWVQaXhlbDpofTtpZih0KXtpZihJbWFnZVJlc2l6ZXIubmVlZHNUb0JlUmVzaXplZChhLG4pKXtjb25zdCBlPW5ldyBVaW50OENsYW1wZWRBcnJheShhKm4qNCk7Y29udmVydEJsYWNrQW5kV2hpdGVUb1JHQkEoe3NyYzpsLGRlc3Q6ZSx3aWR0aDphLGhlaWdodDpuLG5vbkJsYWNrQ29sb3I6MCxpbnZlcnNlRGVjb2RlOm99KTtyZXR1cm4gSW1hZ2VSZXNpemVyLmNyZWF0ZUltYWdlKHtraW5kOk8sZGF0YTplLHdpZHRoOmEsaGVpZ2h0Om4saW50ZXJwb2xhdGU6aX0pfWNvbnN0IGU9bmV3IE9mZnNjcmVlbkNhbnZhcyhhLG4pLHQ9ZS5nZXRDb250ZXh0KCIyZCIpLHI9dC5jcmVhdGVJbWFnZURhdGEoYSxuKTtjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7c3JjOmwsZGVzdDpyLmRhdGEsd2lkdGg6YSxoZWlnaHQ6bixub25CbGFja0NvbG9yOjAsaW52ZXJzZURlY29kZTpvfSk7dC5wdXRJbWFnZURhdGEociwwLDApO3JldHVybntkYXRhOm51bGwsd2lkdGg6YSxoZWlnaHQ6bixpbnRlcnBvbGF0ZTppLGJpdG1hcDplLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpfX1jb25zdCB1PWwuYnl0ZUxlbmd0aDtsZXQgZDtpZihlIGluc3RhbmNlb2YgRGVjb2RlU3RyZWFtJiYoIW98fGM9PT11KSlkPWw7ZWxzZSBpZihvKXtkPW5ldyBVaW50OEFycmF5KGMpO2Quc2V0KGwpO2QuZmlsbCgyNTUsdSl9ZWxzZSBkPW5ldyBVaW50OEFycmF5KGwpO2lmKG8pZm9yKGxldCBlPTA7ZTx1O2UrKylkW2VdXj0yNTU7cmV0dXJue2RhdGE6ZCx3aWR0aDphLGhlaWdodDpuLGludGVycG9sYXRlOml9fWdldCBkcmF3V2lkdGgoKXtyZXR1cm4gTWF0aC5tYXgodGhpcy53aWR0aCx0aGlzLnNtYXNrPy53aWR0aHx8MCx0aGlzLm1hc2s/LndpZHRofHwwKX1nZXQgZHJhd0hlaWdodCgpe3JldHVybiBNYXRoLm1heCh0aGlzLmhlaWdodCx0aGlzLnNtYXNrPy5oZWlnaHR8fDAsdGhpcy5tYXNrPy5oZWlnaHR8fDApfWRlY29kZUJ1ZmZlcihlKXtjb25zdCB0PXRoaXMuYnBjLHI9dGhpcy5udW1Db21wcyxhPXRoaXMuZGVjb2RlQWRkZW5kcyxuPXRoaXMuZGVjb2RlQ29lZmZpY2llbnRzLGk9KDE8PHQpLTE7bGV0IHMsbztpZigxPT09dCl7Zm9yKHM9MCxvPWUubGVuZ3RoO3M8bztzKyspZVtzXT0rIWVbc107cmV0dXJufWxldCBjPTA7Zm9yKHM9MCxvPXRoaXMud2lkdGgqdGhpcy5oZWlnaHQ7czxvO3MrKylmb3IobGV0IHQ9MDt0PHI7dCsrKXtlW2NdPU1hdGhDbGFtcChhW3RdK2VbY10qblt0XSwwLGkpO2MrK319Z2V0Q29tcG9uZW50cyhlKXtjb25zdCB0PXRoaXMuYnBjO2lmKDg9PT10KXJldHVybiBlO2NvbnN0IHI9dGhpcy53aWR0aCxhPXRoaXMuaGVpZ2h0LG49dGhpcy5udW1Db21wcyxpPXIqYSpuO2xldCBzLG89MDtzPXQ8PTg/bmV3IFVpbnQ4QXJyYXkoaSk6dDw9MTY/bmV3IFVpbnQxNkFycmF5KGkpOm5ldyBVaW50MzJBcnJheShpKTtjb25zdCBjPXIqbixsPSgxPDx0KS0xO2xldCBoLHUsZD0wO2lmKDE9PT10KXtsZXQgdCxyLG47Zm9yKGxldCBpPTA7aTxhO2krKyl7cj1kKygtOCZjKTtuPWQrYztmb3IoO2Q8cjspe3U9ZVtvKytdO3NbZF09dT4+NyYxO3NbZCsxXT11Pj42JjE7c1tkKzJdPXU+PjUmMTtzW2QrM109dT4+NCYxO3NbZCs0XT11Pj4zJjE7c1tkKzVdPXU+PjImMTtzW2QrNl09dT4+MSYxO3NbZCs3XT0xJnU7ZCs9OH1pZihkPG4pe3U9ZVtvKytdO3Q9MTI4O2Zvcig7ZDxuOyl7c1tkKytdPSshISh1JnQpO3Q+Pj0xfX19fWVsc2V7bGV0IHI9MDt1PTA7Zm9yKGQ9MCxoPWk7ZDxoOysrZCl7aWYoZCVjPT09MCl7dT0wO3I9MH1mb3IoO3I8dDspe3U9dTw8OHxlW28rK107cis9OH1jb25zdCBhPXItdDtsZXQgbj11Pj5hO248MD9uPTA6bj5sJiYobj1sKTtzW2RdPW47dSY9KDE8PGEpLTE7cj1hfX1yZXR1cm4gc31hc3luYyBmaWxsT3BhY2l0eShlLHQscixhLG4pe2NvbnN0IGk9dGhpcy5zbWFzayxzPXRoaXMubWFzaztsZXQgbyxjLGwsaCx1LGQ7aWYoaSl7Yz1pLndpZHRoO2w9aS5oZWlnaHQ7bz1uZXcgVWludDhDbGFtcGVkQXJyYXkoYypsKTthd2FpdCBpLmZpbGxHcmF5QnVmZmVyKG8pO2M9PT10JiZsPT09cnx8KG89cmVzaXplSW1hZ2VNYXNrKG8saS5icGMsYyxsLHQscikpfWVsc2UgaWYocylpZihzIGluc3RhbmNlb2YgUERGSW1hZ2Upe2M9cy53aWR0aDtsPXMuaGVpZ2h0O289bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGMqbCk7cy5udW1Db21wcz0xO2F3YWl0IHMuZmlsbEdyYXlCdWZmZXIobyk7Zm9yKGg9MCx1PWMqbDtoPHU7KytoKW9baF09MjU1LW9baF07Yz09PXQmJmw9PT1yfHwobz1yZXNpemVJbWFnZU1hc2sobyxzLmJwYyxjLGwsdCxyKSl9ZWxzZXtpZighQXJyYXkuaXNBcnJheShzKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gbWFzayBmb3JtYXQuIik7e289bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHQqcik7Y29uc3QgZT10aGlzLm51bUNvbXBzO2ZvcihoPTAsdT10KnI7aDx1OysraCl7bGV0IHQ9MDtjb25zdCByPWgqZTtmb3IoZD0wO2Q8ZTsrK2Qpe2NvbnN0IGU9bltyK2RdLGE9MipkO2lmKGU8c1thXXx8ZT5zW2ErMV0pe3Q9MjU1O2JyZWFrfX1vW2hdPXR9fX1pZihvKWZvcihoPTAsZD0zLHU9dCphO2g8dTsrK2gsZCs9NCllW2RdPW9baF07ZWxzZSBmb3IoaD0wLGQ9Myx1PXQqYTtoPHU7KytoLGQrPTQpZVtkXT0yNTV9dW5kb1ByZWJsZW5kKGUsdCxyKXtjb25zdCBhPXRoaXMuc21hc2s/Lm1hdHRlO2lmKCFhKXJldHVybjtjb25zdCBuPXRoaXMuY29sb3JTcGFjZS5nZXRSZ2IoYSwwKSxpPW5bMF0scz1uWzFdLG89blsyXSxjPXQqcio0O2ZvcihsZXQgdD0wO3Q8Yzt0Kz00KXtjb25zdCByPWVbdCszXTtpZigwPT09cil7ZVt0XT0yNTU7ZVt0KzFdPTI1NTtlW3QrMl09MjU1O2NvbnRpbnVlfWNvbnN0IGE9MjU1L3I7ZVt0XT0oZVt0XS1pKSphK2k7ZVt0KzFdPShlW3QrMV0tcykqYStzO2VbdCsyXT0oZVt0KzJdLW8pKmErb319YXN5bmMgY3JlYXRlSW1hZ2VEYXRhKGU9ITEsdD0hMSl7Y29uc3Qgcj10aGlzLmRyYXdXaWR0aCxhPXRoaXMuZHJhd0hlaWdodCxuPXt3aWR0aDpyLGhlaWdodDphLGludGVycG9sYXRlOnRoaXMuaW50ZXJwb2xhdGUsa2luZDowLGRhdGE6bnVsbH0saT10aGlzLm51bUNvbXBzLHM9dGhpcy53aWR0aCxvPXRoaXMuaGVpZ2h0LGM9dGhpcy5icGMsbD1zKmkqYys3Pj4zLGg9dCYmSW1hZ2VSZXNpemVyLm5lZWRzVG9CZVJlc2l6ZWQocixhKTtpZighdGhpcy5zbWFzayYmIXRoaXMubWFzayYmIkRldmljZVJHQkEiPT09dGhpcy5jb2xvclNwYWNlLm5hbWUpe24ua2luZD1PO2NvbnN0IGU9bi5kYXRhPWF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhvKnMqNCx7fSk7cmV0dXJuIHQ/aD9JbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2UobiwhMSk6dGhpcy5jcmVhdGVCaXRtYXAoTyxyLGEsZSk6bn1pZighZSl7bGV0IGU7IkRldmljZUdyYXkiPT09dGhpcy5jb2xvclNwYWNlLm5hbWUmJjE9PT1jP2U9djoiRGV2aWNlUkdCIiE9PXRoaXMuY29sb3JTcGFjZS5uYW1lfHw4IT09Y3x8dGhpcy5uZWVkc0RlY29kZXx8KGU9VCk7aWYoZSYmIXRoaXMuc21hc2smJiF0aGlzLm1hc2smJnI9PT1zJiZhPT09byl7Y29uc3QgaT1hd2FpdCB0aGlzLiNyZShzLG8pO2lmKGkpcmV0dXJuIGk7Y29uc3QgYz1hd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMobypsLHt9KTtpZih0KXJldHVybiBoP0ltYWdlUmVzaXplci5jcmVhdGVJbWFnZSh7ZGF0YTpjLGtpbmQ6ZSx3aWR0aDpyLGhlaWdodDphLGludGVycG9sYXRlOnRoaXMuaW50ZXJwb2xhdGV9LHRoaXMubmVlZHNEZWNvZGUpOnRoaXMuY3JlYXRlQml0bWFwKGUscyxvLGMpO24ua2luZD1lO24uZGF0YT1jO2lmKHRoaXMubmVlZHNEZWNvZGUpe2Fzc2VydChlPT09diwiUERGSW1hZ2UuY3JlYXRlSW1hZ2VEYXRhOiBUaGUgaW1hZ2UgbXVzdCBiZSBncmF5c2NhbGUuIik7Y29uc3QgdD1uLmRhdGE7Zm9yKGxldCBlPTAscj10Lmxlbmd0aDtlPHI7ZSsrKXRbZV1ePTI1NX1yZXR1cm4gbn1pZih0aGlzLmltYWdlIGluc3RhbmNlb2YgSnBlZ1N0cmVhbSYmIXRoaXMuc21hc2smJiF0aGlzLm1hc2smJiF0aGlzLm5lZWRzRGVjb2RlKXtsZXQgZT1vKmw7aWYodCYmIWgpe2xldCB0PSExO3N3aXRjaCh0aGlzLmNvbG9yU3BhY2UubmFtZSl7Y2FzZSJEZXZpY2VHcmF5IjplKj00O3Q9ITA7YnJlYWs7Y2FzZSJEZXZpY2VSR0IiOmU9ZS8zKjQ7dD0hMDticmVhaztjYXNlIkRldmljZUNNWUsiOnQ9ITB9aWYodCl7Y29uc3QgdD1hd2FpdCB0aGlzLiNyZShyLGEpO2lmKHQpcmV0dXJuIHQ7Y29uc3Qgbj1hd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMoZSx7ZHJhd1dpZHRoOnIsZHJhd0hlaWdodDphLGZvcmNlUkdCQTohMH0pO3JldHVybiB0aGlzLmNyZWF0ZUJpdG1hcChPLHIsYSxuKX19ZWxzZSBzd2l0Y2godGhpcy5jb2xvclNwYWNlLm5hbWUpe2Nhc2UiRGV2aWNlR3JheSI6ZSo9MztjYXNlIkRldmljZVJHQiI6Y2FzZSJEZXZpY2VDTVlLIjpuLmtpbmQ9VDtuLmRhdGE9YXdhaXQgdGhpcy5nZXRJbWFnZUJ5dGVzKGUse2RyYXdXaWR0aDpyLGRyYXdIZWlnaHQ6YSxmb3JjZVJHQjohMH0pO3JldHVybiBoP0ltYWdlUmVzaXplci5jcmVhdGVJbWFnZShuKTpufX19Y29uc3QgdT1hd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMobypsLHtpbnRlcm5hbDohMH0pLGQ9MHx1Lmxlbmd0aC9sKmEvbyxmPXRoaXMuZ2V0Q29tcG9uZW50cyh1KTtsZXQgZyxwLG0sYix5LHc7aWYodCYmIWgpe209bmV3IE9mZnNjcmVlbkNhbnZhcyhyLGEpO2I9bS5nZXRDb250ZXh0KCIyZCIpO3k9Yi5jcmVhdGVJbWFnZURhdGEocixhKTt3PXkuZGF0YX1uLmtpbmQ9TztpZihlfHx0aGlzLnNtYXNrfHx0aGlzLm1hc2spe3QmJiFofHwodz1uZXcgVWludDhDbGFtcGVkQXJyYXkociphKjQpKTtnPTE7cD0hMDthd2FpdCB0aGlzLmZpbGxPcGFjaXR5KHcscixhLGQsZil9ZWxzZXtpZighdHx8aCl7bi5raW5kPVQ7dz1uZXcgVWludDhDbGFtcGVkQXJyYXkociphKjMpO2c9MH1lbHNle25ldyBVaW50MzJBcnJheSh3LmJ1ZmZlcikuZmlsbChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbj80Mjc4MTkwMDgwOjI1NSk7Zz0xfXA9ITF9dGhpcy5uZWVkc0RlY29kZSYmdGhpcy5kZWNvZGVCdWZmZXIoZik7dGhpcy5jb2xvclNwYWNlLmZpbGxSZ2IodyxzLG8scixhLGQsYyxmLGcpO3AmJnRoaXMudW5kb1ByZWJsZW5kKHcscixkKTtpZih0JiYhaCl7Yi5wdXRJbWFnZURhdGEoeSwwLDApO3JldHVybntkYXRhOm51bGwsd2lkdGg6cixoZWlnaHQ6YSxiaXRtYXA6bS50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKSxpbnRlcnBvbGF0ZTp0aGlzLmludGVycG9sYXRlfX1uLmRhdGE9dztyZXR1cm4gaD9JbWFnZVJlc2l6ZXIuY3JlYXRlSW1hZ2Uobik6bn1hc3luYyBmaWxsR3JheUJ1ZmZlcihlKXtjb25zdCB0PXRoaXMubnVtQ29tcHM7aWYoMSE9PXQpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBSZWFkaW5nIGdyYXkgc2NhbGUgZnJvbSBhIGNvbG9yIGltYWdlOiAke3R9YCk7Y29uc3Qgcj10aGlzLndpZHRoLGE9dGhpcy5oZWlnaHQsbj10aGlzLmJwYyxpPXIqdCpuKzc+PjMscz1hd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMoYSppLHtpbnRlcm5hbDohMH0pLG89dGhpcy5nZXRDb21wb25lbnRzKHMpO2xldCBjLGw7aWYoMT09PW4pe2w9ciphO2lmKHRoaXMubmVlZHNEZWNvZGUpZm9yKGM9MDtjPGw7KytjKWVbY109b1tjXS0xJjI1NTtlbHNlIGZvcihjPTA7YzxsOysrYyllW2NdPTI1NSYtb1tjXTtyZXR1cm59dGhpcy5uZWVkc0RlY29kZSYmdGhpcy5kZWNvZGVCdWZmZXIobyk7bD1yKmE7Y29uc3QgaD0yNTUvKCgxPDxuKS0xKTtmb3IoYz0wO2M8bDsrK2MpZVtjXT1oKm9bY119Y3JlYXRlQml0bWFwKGUsdCxyLGEpe2NvbnN0IG49bmV3IE9mZnNjcmVlbkNhbnZhcyh0LHIpLGk9bi5nZXRDb250ZXh0KCIyZCIpO2xldCBzO2lmKGU9PT1PKXM9bmV3IEltYWdlRGF0YShhLHQscik7ZWxzZXtzPWkuY3JlYXRlSW1hZ2VEYXRhKHQscik7Y29udmVydFRvUkdCQSh7a2luZDplLHNyYzphLGRlc3Q6bmV3IFVpbnQzMkFycmF5KHMuZGF0YS5idWZmZXIpLHdpZHRoOnQsaGVpZ2h0OnIsaW52ZXJzZURlY29kZTp0aGlzLm5lZWRzRGVjb2RlfSl9aS5wdXRJbWFnZURhdGEocywwLDApO3JldHVybntkYXRhOm51bGwsd2lkdGg6dCxoZWlnaHQ6cixiaXRtYXA6bi50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKSxpbnRlcnBvbGF0ZTp0aGlzLmludGVycG9sYXRlfX1hc3luYyNyZShlLHQpe2NvbnN0IHI9YXdhaXQgdGhpcy5pbWFnZS5nZXRUcmFuc2ZlcmFibGVJbWFnZSgpO3JldHVybiByP3tkYXRhOm51bGwsd2lkdGg6ZSxoZWlnaHQ6dCxiaXRtYXA6cixpbnRlcnBvbGF0ZTp0aGlzLmludGVycG9sYXRlfTpudWxsfWFzeW5jIGdldEltYWdlQnl0ZXMoZSx7ZHJhd1dpZHRoOnQsZHJhd0hlaWdodDpyLGZvcmNlUkdCQTphPSExLGZvcmNlUkdCOm49ITEsaW50ZXJuYWw6aT0hMX0pe3RoaXMuaW1hZ2UucmVzZXQoKTt0aGlzLmltYWdlLmRyYXdXaWR0aD10fHx0aGlzLndpZHRoO3RoaXMuaW1hZ2UuZHJhd0hlaWdodD1yfHx0aGlzLmhlaWdodDt0aGlzLmltYWdlLmZvcmNlUkdCQT0hIWE7dGhpcy5pbWFnZS5mb3JjZVJHQj0hIW47Y29uc3Qgcz1hd2FpdCB0aGlzLmltYWdlLmdldEltYWdlRGF0YShlLHRoaXMuanB4RGVjb2Rlck9wdGlvbnMpO2lmKGl8fHRoaXMuaW1hZ2UgaW5zdGFuY2VvZiBEZWNvZGVTdHJlYW0pcmV0dXJuIHM7YXNzZXJ0KHMgaW5zdGFuY2VvZiBVaW50OEFycmF5LCdQREZJbWFnZS5nZXRJbWFnZUJ5dGVzOiBVbnN1cHBvcnRlZCAiaW1hZ2VCeXRlcyIgdHlwZS4nKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkocyl9fWNvbnN0IGJpPU9iamVjdC5mcmVlemUoe21heEltYWdlU2l6ZTotMSxkaXNhYmxlRm9udEZhY2U6ITEsaWdub3JlRXJyb3JzOiExLGlzRXZhbFN1cHBvcnRlZDohMCxpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDohMSxpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDohMSxjYW52YXNNYXhBcmVhSW5CeXRlczotMSxmb250RXh0cmFQcm9wZXJ0aWVzOiExLHVzZVN5c3RlbUZvbnRzOiEwLHVzZVdhc206ITAsdXNlV29ya2VyRmV0Y2g6ITAsY01hcFVybDpudWxsLGljY1VybDpudWxsLHN0YW5kYXJkRm9udERhdGFVcmw6bnVsbCx3YXNtVXJsOm51bGx9KSx5aT0xLHdpPTIseGk9UHJvbWlzZS5yZXNvbHZlKCk7ZnVuY3Rpb24gbm9ybWFsaXplQmxlbmRNb2RlKGUsdD0hMSl7aWYoQXJyYXkuaXNBcnJheShlKSl7Zm9yKGNvbnN0IHQgb2YgZSl7Y29uc3QgZT1ub3JtYWxpemVCbGVuZE1vZGUodCwhMCk7aWYoZSlyZXR1cm4gZX13YXJuKGBVbnN1cHBvcnRlZCBibGVuZCBtb2RlIEFycmF5OiAke2V9YCk7cmV0dXJuInNvdXJjZS1vdmVyIn1pZighKGUgaW5zdGFuY2VvZiBOYW1lKSlyZXR1cm4gdD9udWxsOiJzb3VyY2Utb3ZlciI7c3dpdGNoKGUubmFtZSl7Y2FzZSJOb3JtYWwiOmNhc2UiQ29tcGF0aWJsZSI6cmV0dXJuInNvdXJjZS1vdmVyIjtjYXNlIk11bHRpcGx5IjpyZXR1cm4ibXVsdGlwbHkiO2Nhc2UiU2NyZWVuIjpyZXR1cm4ic2NyZWVuIjtjYXNlIk92ZXJsYXkiOnJldHVybiJvdmVybGF5IjtjYXNlIkRhcmtlbiI6cmV0dXJuImRhcmtlbiI7Y2FzZSJMaWdodGVuIjpyZXR1cm4ibGlnaHRlbiI7Y2FzZSJDb2xvckRvZGdlIjpyZXR1cm4iY29sb3ItZG9kZ2UiO2Nhc2UiQ29sb3JCdXJuIjpyZXR1cm4iY29sb3ItYnVybiI7Y2FzZSJIYXJkTGlnaHQiOnJldHVybiJoYXJkLWxpZ2h0IjtjYXNlIlNvZnRMaWdodCI6cmV0dXJuInNvZnQtbGlnaHQiO2Nhc2UiRGlmZmVyZW5jZSI6cmV0dXJuImRpZmZlcmVuY2UiO2Nhc2UiRXhjbHVzaW9uIjpyZXR1cm4iZXhjbHVzaW9uIjtjYXNlIkh1ZSI6cmV0dXJuImh1ZSI7Y2FzZSJTYXR1cmF0aW9uIjpyZXR1cm4ic2F0dXJhdGlvbiI7Y2FzZSJDb2xvciI6cmV0dXJuImNvbG9yIjtjYXNlIkx1bWlub3NpdHkiOnJldHVybiJsdW1pbm9zaXR5In1pZih0KXJldHVybiBudWxsO3dhcm4oYFVuc3VwcG9ydGVkIGJsZW5kIG1vZGU6ICR7ZS5uYW1lfWApO3JldHVybiJzb3VyY2Utb3ZlciJ9ZnVuY3Rpb24gYWRkQ2FjaGVkSW1hZ2VPcHMoZSx7b2JqSWQ6dCxmbjpyLGFyZ3M6YSxvcHRpb25hbENvbnRlbnQ6bixoYXNNYXNrOml9KXt0JiZlLmFkZERlcGVuZGVuY3kodCk7ZS5hZGRJbWFnZU9wcyhyLGEsbixpKTtyPT09TnQmJmFbMF0/LmNvdW50PjAmJmFbMF0uY291bnQrK31jbGFzcyBUaW1lU2xvdE1hbmFnZXJ7c3RhdGljIFRJTUVfU0xPVF9EVVJBVElPTl9NUz0yMDtzdGF0aWMgQ0hFQ0tfVElNRV9FVkVSWT0xMDA7Y29uc3RydWN0b3IoKXt0aGlzLnJlc2V0KCl9Y2hlY2soKXtpZigrK3RoaXMuY2hlY2tlZDxUaW1lU2xvdE1hbmFnZXIuQ0hFQ0tfVElNRV9FVkVSWSlyZXR1cm4hMTt0aGlzLmNoZWNrZWQ9MDtyZXR1cm4gdGhpcy5lbmRUaW1lPD1EYXRlLm5vdygpfXJlc2V0KCl7dGhpcy5lbmRUaW1lPURhdGUubm93KCkrVGltZVNsb3RNYW5hZ2VyLlRJTUVfU0xPVF9EVVJBVElPTl9NUzt0aGlzLmNoZWNrZWQ9MH19Y2xhc3MgUGFydGlhbEV2YWx1YXRvcntjb25zdHJ1Y3Rvcih7eHJlZjplLGhhbmRsZXI6dCxwYWdlSW5kZXg6cixpZEZhY3Rvcnk6YSxmb250Q2FjaGU6bixidWlsdEluQ01hcENhY2hlOmksc3RhbmRhcmRGb250RGF0YUNhY2hlOnMsZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOm8sZ2xvYmFsSW1hZ2VDYWNoZTpjLHN5c3RlbUZvbnRDYWNoZTpsLG9wdGlvbnM6aD1udWxsfSl7dGhpcy54cmVmPWU7dGhpcy5oYW5kbGVyPXQ7dGhpcy5wYWdlSW5kZXg9cjt0aGlzLmlkRmFjdG9yeT1hO3RoaXMuZm9udENhY2hlPW47dGhpcy5idWlsdEluQ01hcENhY2hlPWk7dGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGU9czt0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZT1vO3RoaXMuZ2xvYmFsSW1hZ2VDYWNoZT1jO3RoaXMuc3lzdGVtRm9udENhY2hlPWw7dGhpcy5vcHRpb25zPWh8fGJpO3RoaXMudHlwZTNGb250UmVmcz1udWxsO3RoaXMuX3JlZ2lvbmFsSW1hZ2VDYWNoZT1uZXcgUmVnaW9uYWxJbWFnZUNhY2hlO3RoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZD10aGlzLmZldGNoQnVpbHRJbkNNYXAuYmluZCh0aGlzKX1nZXQgX3BkZkZ1bmN0aW9uRmFjdG9yeSgpe3JldHVybiBzaGFkb3codGhpcywiX3BkZkZ1bmN0aW9uRmFjdG9yeSIsbmV3IFBERkZ1bmN0aW9uRmFjdG9yeSh7eHJlZjp0aGlzLnhyZWYsaXNFdmFsU3VwcG9ydGVkOnRoaXMub3B0aW9ucy5pc0V2YWxTdXBwb3J0ZWR9KSl9Z2V0IHBhcnNpbmdUeXBlM0ZvbnQoKXtyZXR1cm4hIXRoaXMudHlwZTNGb250UmVmc31jbG9uZShlPW51bGwpe2NvbnN0IHQ9T2JqZWN0LmNyZWF0ZSh0aGlzKTt0Lm9wdGlvbnM9T2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLHRoaXMub3B0aW9ucyxlKTtyZXR1cm4gdH1oYXNCbGVuZE1vZGVzKGUsdCl7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuITE7aWYoZS5vYmpJZCYmdC5oYXMoZS5vYmpJZCkpcmV0dXJuITE7Y29uc3Qgcj1uZXcgUmVmU2V0KHQpO2Uub2JqSWQmJnIucHV0KGUub2JqSWQpO2NvbnN0IGE9W2VdLG49dGhpcy54cmVmO2Zvcig7YS5sZW5ndGg7KXtjb25zdCBlPWEuc2hpZnQoKSx0PWUuZ2V0KCJFeHRHU3RhdGUiKTtpZih0IGluc3RhbmNlb2YgRGljdClmb3IobGV0IGUgb2YgdC5nZXRSYXdWYWx1ZXMoKSl7aWYoZSBpbnN0YW5jZW9mIFJlZil7aWYoci5oYXMoZSkpY29udGludWU7dHJ5e2U9bi5mZXRjaChlKX1jYXRjaCh0KXtyLnB1dChlKTtpbmZvKGBoYXNCbGVuZE1vZGVzIC0gaWdub3JpbmcgRXh0R1N0YXRlOiAiJHt0fSIuYCk7Y29udGludWV9fWlmKCEoZSBpbnN0YW5jZW9mIERpY3QpKWNvbnRpbnVlO2Uub2JqSWQmJnIucHV0KGUub2JqSWQpO2NvbnN0IHQ9ZS5nZXQoIkJNIik7aWYodCBpbnN0YW5jZW9mIE5hbWUpe2lmKCJOb3JtYWwiIT09dC5uYW1lKXJldHVybiEwfWVsc2UgaWYodm9pZCAwIT09dCYmQXJyYXkuaXNBcnJheSh0KSlmb3IoY29uc3QgZSBvZiB0KWlmKGUgaW5zdGFuY2VvZiBOYW1lJiYiTm9ybWFsIiE9PWUubmFtZSlyZXR1cm4hMH1jb25zdCBpPWUuZ2V0KCJYT2JqZWN0Iik7aWYoaSBpbnN0YW5jZW9mIERpY3QpZm9yKGxldCBlIG9mIGkuZ2V0UmF3VmFsdWVzKCkpe2lmKGUgaW5zdGFuY2VvZiBSZWYpe2lmKHIuaGFzKGUpKWNvbnRpbnVlO3RyeXtlPW4uZmV0Y2goZSl9Y2F0Y2godCl7ci5wdXQoZSk7aW5mbyhgaGFzQmxlbmRNb2RlcyAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke3R9Ii5gKTtjb250aW51ZX19aWYoIShlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpY29udGludWU7ZS5kaWN0Lm9iaklkJiZyLnB1dChlLmRpY3Qub2JqSWQpO2NvbnN0IHQ9ZS5kaWN0LmdldCgiUmVzb3VyY2VzIik7aWYodCBpbnN0YW5jZW9mIERpY3QmJighdC5vYmpJZHx8IXIuaGFzKHQub2JqSWQpKSl7YS5wdXNoKHQpO3Qub2JqSWQmJnIucHV0KHQub2JqSWQpfX19Zm9yKGNvbnN0IGUgb2Ygcil0LnB1dChlKTtyZXR1cm4hMX1hc3luYyBmZXRjaEJ1aWx0SW5DTWFwKGUpe2NvbnN0IHQ9dGhpcy5idWlsdEluQ01hcENhY2hlLmdldChlKTtpZih0KXJldHVybiB0O2xldCByO3I9dGhpcy5vcHRpb25zLnVzZVdvcmtlckZldGNoP3tjTWFwRGF0YTphd2FpdCBmZXRjaEJpbmFyeURhdGEoYCR7dGhpcy5vcHRpb25zLmNNYXBVcmx9JHtlfS5iY21hcGApLGlzQ29tcHJlc3NlZDohMH06YXdhaXQgdGhpcy5oYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiRmV0Y2hCaW5hcnlEYXRhIix7dHlwZToiY01hcFJlYWRlckZhY3RvcnkiLG5hbWU6ZX0pO3RoaXMuYnVpbHRJbkNNYXBDYWNoZS5zZXQoZSxyKTtyZXR1cm4gcn1hc3luYyBmZXRjaFN0YW5kYXJkRm9udERhdGEoZSl7Y29uc3QgdD10aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZS5nZXQoZSk7aWYodClyZXR1cm4gbmV3IFN0cmVhbSh0KTtpZih0aGlzLm9wdGlvbnMudXNlU3lzdGVtRm9udHMmJiJTeW1ib2wiIT09ZSYmIlphcGZEaW5nYmF0cyIhPT1lKXJldHVybiBudWxsO2NvbnN0IHI9TGEoKVtlXTtsZXQgYTt0cnl7YT10aGlzLm9wdGlvbnMudXNlV29ya2VyRmV0Y2g/YXdhaXQgZmV0Y2hCaW5hcnlEYXRhKGAke3RoaXMub3B0aW9ucy5zdGFuZGFyZEZvbnREYXRhVXJsfSR7cn1gKTphd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJGZXRjaEJpbmFyeURhdGEiLHt0eXBlOiJzdGFuZGFyZEZvbnREYXRhRmFjdG9yeSIsZmlsZW5hbWU6cn0pfWNhdGNoKGUpe3dhcm4oZSk7cmV0dXJuIG51bGx9dGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuc2V0KGUsYSk7cmV0dXJuIG5ldyBTdHJlYW0oYSl9YXN5bmMgYnVpbGRGb3JtWE9iamVjdChlLHQscixhLG4saSxzLG8pe2NvbnN0e2RpY3Q6Y309dCxsPWxvb2t1cE1hdHJpeChjLmdldEFycmF5KCJNYXRyaXgiKSxudWxsKSxoPWxvb2t1cE5vcm1hbFJlY3QoYy5nZXRBcnJheSgiQkJveCIpLG51bGwpO2xldCB1LGQ7Yy5oYXMoIk9DIikmJih1PWF3YWl0IHRoaXMucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoYy5nZXQoIk9DIiksZSkpO3ZvaWQgMCE9PXUmJmEuYWRkT3AodnQsWyJPQyIsdV0pO2NvbnN0IGY9Yy5nZXQoIkdyb3VwIik7aWYoZil7ZD17bWF0cml4OmwsYmJveDpoLHNtYXNrOnIsaXNvbGF0ZWQ6ITEsa25vY2tvdXQ6ITF9O2xldCB0PW51bGw7aWYoaXNOYW1lKGYuZ2V0KCJTIiksIlRyYW5zcGFyZW5jeSIpKXtkLmlzb2xhdGVkPWYuZ2V0KCJJIil8fCExO2Qua25vY2tvdXQ9Zi5nZXQoIksiKXx8ITE7aWYoZi5oYXMoIkNTIikpe2NvbnN0IHI9dGhpcy5fZ2V0Q29sb3JTcGFjZShmLmdldFJhdygiQ1MiKSxlLHMpO3Q9ciBpbnN0YW5jZW9mIENvbG9yU3BhY2U/cjphd2FpdCB0aGlzLl9oYW5kbGVDb2xvclNwYWNlKHIpfX1pZihyPy5iYWNrZHJvcCl7dHx8PUNvbG9yU3BhY2VVdGlscy5yZ2I7ci5iYWNrZHJvcD10LmdldFJnYkhleChyLmJhY2tkcm9wLDApfWEuYWRkT3AoRHQsW2RdKX1jb25zdCBnPVtsJiZuZXcgRmxvYXQzMkFycmF5KGwpLCFmJiZoJiZuZXcgRmxvYXQzMkFycmF5KGgpfHxudWxsXTthLmFkZE9wKE90LGcpO2NvbnN0IHA9Yy5nZXQoIlJlc291cmNlcyIpO2F3YWl0IHRoaXMuZ2V0T3BlcmF0b3JMaXN0KHtzdHJlYW06dCx0YXNrOm4scmVzb3VyY2VzOnAgaW5zdGFuY2VvZiBEaWN0P3A6ZSxvcGVyYXRvckxpc3Q6YSxpbml0aWFsU3RhdGU6aSxwcmV2UmVmczpvfSk7YS5hZGRPcChNdCxbXSk7ZiYmYS5hZGRPcChCdCxbZF0pO3ZvaWQgMCE9PXUmJmEuYWRkT3AoRnQsW10pfV9zZW5kSW1nRGF0YShlLHQscj0hMSl7Y29uc3QgYT10P1t0LmJpdG1hcHx8dC5kYXRhLmJ1ZmZlcl06bnVsbDtyZXR1cm4gdGhpcy5wYXJzaW5nVHlwZTNGb250fHxyP3RoaXMuaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLFtlLCJJbWFnZSIsdF0sYSk6dGhpcy5oYW5kbGVyLnNlbmQoIm9iaiIsW2UsdGhpcy5wYWdlSW5kZXgsIkltYWdlIix0XSxhKX1hc3luYyBidWlsZFBhaW50SW1hZ2VYT2JqZWN0KHtyZXNvdXJjZXM6ZSxpbWFnZTp0LGlzSW5saW5lOnI9ITEsb3BlcmF0b3JMaXN0OmEsY2FjaGVLZXk6bixsb2NhbEltYWdlQ2FjaGU6aSxsb2NhbENvbG9yU3BhY2VDYWNoZTpzfSl7Y29uc3R7bWF4SW1hZ2VTaXplOm8saWdub3JlRXJyb3JzOmMsaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ6bH09dGhpcy5vcHRpb25zLHtkaWN0Omh9PXQsdT1oLm9iaklkLGQ9aC5nZXQoIlciLCJXaWR0aCIpLGY9aC5nZXQoIkgiLCJIZWlnaHQiKTtpZighZHx8Im51bWJlciIhPXR5cGVvZiBkfHwhZnx8Im51bWJlciIhPXR5cGVvZiBmKXt3YXJuKCJJbWFnZSBkaW1lbnNpb25zIGFyZSBtaXNzaW5nLCBvciBub3QgbnVtYmVycy4iKTtyZXR1cm59aWYoLTEhPT1vJiZkKmY+byl7Y29uc3QgZT0iSW1hZ2UgZXhjZWVkZWQgbWF4aW11bSBhbGxvd2VkIHNpemUgYW5kIHdhcyByZW1vdmVkLiI7aWYoIWMpdGhyb3cgbmV3IEVycm9yKGUpO3dhcm4oZSk7cmV0dXJufWxldCBnO2guaGFzKCJPQyIpJiYoZz1hd2FpdCB0aGlzLnBhcnNlTWFya2VkQ29udGVudFByb3BzKGguZ2V0KCJPQyIpLGUpKTtsZXQgcCxtLGI7aWYoaC5nZXQoIklNIiwiSW1hZ2VNYXNrIil8fCExKXtwPWF3YWl0IFBERkltYWdlLmNyZWF0ZU1hc2soe2ltYWdlOnQsaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ6bCYmIXRoaXMucGFyc2luZ1R5cGUzRm9udH0pO2lmKHAuaXNTaW5nbGVPcGFxdWVQaXhlbCl7bT1YdDtiPVtdO2EuYWRkSW1hZ2VPcHMobSxiLGcpO2lmKG4pe2NvbnN0IGU9e2ZuOm0sYXJnczpiLG9wdGlvbmFsQ29udGVudDpnfTtpLnNldChuLHUsZSk7dSYmdGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLHUsZSl9cmV0dXJufWlmKHRoaXMucGFyc2luZ1R5cGUzRm9udCl7Yj1mdW5jdGlvbiBjb21waWxlVHlwZTNHbHlwaCh7ZGF0YTplLHdpZHRoOnQsaGVpZ2h0OnJ9KXtpZih0PjFlM3x8cj4xZTMpcmV0dXJuIG51bGw7Y29uc3QgYT1uZXcgVWludDhBcnJheShbMCwyLDQsMCwxLDAsNSw0LDgsMTAsMCw4LDAsMiwxLDBdKSxuPXQrMSxpPW5ldyBVaW50OEFycmF5KG4qKHIrMSkpO2xldCBzLG8sYztjb25zdCBsPXQrNyYtOCxoPW5ldyBVaW50OEFycmF5KGwqcik7bGV0IHU9MDtmb3IoY29uc3QgdCBvZiBlKXtsZXQgZT0xMjg7Zm9yKDtlPjA7KXtoW3UrK109dCZlPzA6MjU1O2U+Pj0xfX1sZXQgZD0wO3U9MDtpZigwIT09aFt1XSl7aVswXT0xOysrZH1mb3Iobz0xO288dDtvKyspe2lmKGhbdV0hPT1oW3UrMV0pe2lbb109aFt1XT8yOjE7KytkfXUrK31pZigwIT09aFt1XSl7aVtvXT0yOysrZH1mb3Iocz0xO3M8cjtzKyspe3U9cypsO2M9cypuO2lmKGhbdS1sXSE9PWhbdV0pe2lbY109aFt1XT8xOjg7KytkfWxldCBlPShoW3VdPzQ6MCkrKGhbdS1sXT84OjApO2ZvcihvPTE7bzx0O28rKyl7ZT0oZT4+MikrKGhbdSsxXT80OjApKyhoW3UtbCsxXT84OjApO2lmKGFbZV0pe2lbYytvXT1hW2VdOysrZH11Kyt9aWYoaFt1LWxdIT09aFt1XSl7aVtjK29dPWhbdV0/Mjo0OysrZH1pZihkPjFlMylyZXR1cm4gbnVsbH11PWwqKHItMSk7Yz1zKm47aWYoMCE9PWhbdV0pe2lbY109ODsrK2R9Zm9yKG89MTtvPHQ7bysrKXtpZihoW3VdIT09aFt1KzFdKXtpW2Mrb109aFt1XT80Ojg7KytkfXUrK31pZigwIT09aFt1XSl7aVtjK29dPTQ7KytkfWlmKGQ+MWUzKXJldHVybiBudWxsO2NvbnN0IGY9bmV3IEludDMyQXJyYXkoWzAsbiwtMSwwLC1uLDAsMCwwLDFdKSxnPVtdLHthOnAsYjptLGM6YixkOnksZTp3LGY6eH09KG5ldyBET01NYXRyaXgpLnNjYWxlU2VsZigxL3QsLTEvcikudHJhbnNsYXRlU2VsZigwLC1yKTtmb3Iocz0wO2QmJnM8PXI7cysrKXtsZXQgZT1zKm47Y29uc3Qgcj1lK3Q7Zm9yKDtlPHImJiFpW2VdOyllKys7aWYoZT09PXIpY29udGludWU7bGV0IGE9ZSVuLG89cztnLnB1c2goJHQscCphK2Iqbyt3LG0qYSt5Km8reCk7Y29uc3QgYz1lO2xldCBsPWlbZV07ZG97Y29uc3QgdD1mW2xdO2Rve2UrPXR9d2hpbGUoIWlbZV0pO2NvbnN0IHI9aVtlXTtpZig1IT09ciYmMTAhPT1yKXtsPXI7aVtlXT0wfWVsc2V7bD1yJjUxKmw+PjQ7aVtlXSY9bD4+MnxsPDwyfWE9ZSVuO289ZS9ufDA7Zy5wdXNoKFZ0LHAqYStiKm8rdyxtKmEreSpvK3gpO2lbZV18fC0tZH13aGlsZShjIT09ZSk7LS1zfXJldHVybltHdCxbbmV3IEZsb2F0MzJBcnJheShnKV0sbmV3IEZsb2F0MzJBcnJheShbMCwwLHQscl0pXX0ocCk7aWYoYil7YS5hZGRJbWFnZU9wcyhIdCxiLGcpO3JldHVybn13YXJuKCJDYW5ub3QgY29tcGlsZSBUeXBlMyBnbHlwaC4iKTthLmFkZEltYWdlT3BzKE50LFtwXSxnKTtyZXR1cm59Y29uc3QgZT1gbWFza18ke3RoaXMuaWRGYWN0b3J5LmNyZWF0ZU9iaklkKCl9YDthLmFkZERlcGVuZGVuY3koZSk7cC5kYXRhTGVuPXAuYml0bWFwP3Aud2lkdGgqcC5oZWlnaHQqNDpwLmRhdGEubGVuZ3RoO3RoaXMuX3NlbmRJbWdEYXRhKGUscCk7bT1OdDtiPVt7ZGF0YTplLHdpZHRoOnAud2lkdGgsaGVpZ2h0OnAuaGVpZ2h0LGludGVycG9sYXRlOnAuaW50ZXJwb2xhdGUsY291bnQ6MX1dO2EuYWRkSW1hZ2VPcHMobSxiLGcpO2lmKG4pe2NvbnN0IHQ9e29iaklkOmUsZm46bSxhcmdzOmIsb3B0aW9uYWxDb250ZW50Omd9O2kuc2V0KG4sdSx0KTt1JiZ0aGlzLl9yZWdpb25hbEltYWdlQ2FjaGUuc2V0KG51bGwsdSx0KX1yZXR1cm59Y29uc3QgeT1oLmhhcygiU01hc2siKXx8aC5oYXMoIk1hc2siKTtpZihyJiZkK2Y8MjAwJiYheSl7dHJ5e2NvbnN0IG49bmV3IFBERkltYWdlKHt4cmVmOnRoaXMueHJlZixyZXM6ZSxpbWFnZTp0LGlzSW5saW5lOnIscGRmRnVuY3Rpb25GYWN0b3J5OnRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6dGhpcy5nbG9iYWxDb2xvclNwYWNlQ2FjaGUsbG9jYWxDb2xvclNwYWNlQ2FjaGU6c30pO3A9YXdhaXQgbi5jcmVhdGVJbWFnZURhdGEoITAsITEpO2EuYWRkSW1hZ2VPcHMoTHQsW3BdLGcpfWNhdGNoKGUpe2NvbnN0IHQ9YFVuYWJsZSB0byBkZWNvZGUgaW5saW5lIGltYWdlOiAiJHtlfSIuYDtpZighYyl0aHJvdyBuZXcgRXJyb3IodCk7d2Fybih0KX1yZXR1cm59bGV0IHc9YGltZ18ke3RoaXMuaWRGYWN0b3J5LmNyZWF0ZU9iaklkKCl9YCx4PSExLFM9bnVsbDtpZih0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpdz1gJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV90eXBlM18ke3d9YDtlbHNlIGlmKG4mJnUpe3g9dGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNob3VsZENhY2hlKHUsdGhpcy5wYWdlSW5kZXgpO2lmKHgpe2Fzc2VydCghciwiQ2Fubm90IGNhY2hlIGFuIGlubGluZSBpbWFnZSBnbG9iYWxseS4iKTt3PWAke3RoaXMuaWRGYWN0b3J5LmdldERvY0lkKCl9XyR7d31gfX1hLmFkZERlcGVuZGVuY3kodyk7bT1fdDtiPVt3LGQsZl07YS5hZGRJbWFnZU9wcyhtLGIsZyx5KTtpZih4KXtTPXtvYmpJZDp3LGZuOm0sYXJnczpiLG9wdGlvbmFsQ29udGVudDpnLGhhc01hc2s6eSxieXRlU2l6ZTowfTtpZih0aGlzLmdsb2JhbEltYWdlQ2FjaGUuaGFzRGVjb2RlRmFpbGVkKHUpKXt0aGlzLmdsb2JhbEltYWdlQ2FjaGUuc2V0RGF0YSh1LFMpO3RoaXMuX3NlbmRJbWdEYXRhKHcsbnVsbCx4KTtyZXR1cm59aWYoZCpmPjI1ZTR8fHkpe2NvbnN0IGU9YXdhaXQgdGhpcy5oYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiY29tbW9ub2JqIixbdywiQ29weUxvY2FsSW1hZ2UiLHtpbWFnZVJlZjp1fV0pO2lmKGUpe3RoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhKHUsUyk7dGhpcy5nbG9iYWxJbWFnZUNhY2hlLmFkZEJ5dGVTaXplKHUsZSk7cmV0dXJufX19UERGSW1hZ2UuYnVpbGRJbWFnZSh7eHJlZjp0aGlzLnhyZWYscmVzOmUsaW1hZ2U6dCxpc0lubGluZTpyLHBkZkZ1bmN0aW9uRmFjdG9yeTp0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOnRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLGxvY2FsQ29sb3JTcGFjZUNhY2hlOnN9KS50aGVuKGFzeW5jIGU9PntwPWF3YWl0IGUuY3JlYXRlSW1hZ2VEYXRhKCExLGwpO3AuZGF0YUxlbj1wLmJpdG1hcD9wLndpZHRoKnAuaGVpZ2h0KjQ6cC5kYXRhLmxlbmd0aDtwLnJlZj11O3gmJnRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5hZGRCeXRlU2l6ZSh1LHAuZGF0YUxlbik7cmV0dXJuIHRoaXMuX3NlbmRJbWdEYXRhKHcscCx4KX0pLmNhdGNoKGU9Pnt3YXJuKGBVbmFibGUgdG8gZGVjb2RlIGltYWdlICIke3d9IjogIiR7ZX0iLmApO3UmJnRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5hZGREZWNvZGVGYWlsZWQodSk7cmV0dXJuIHRoaXMuX3NlbmRJbWdEYXRhKHcsbnVsbCx4KX0pO2lmKG4pe2NvbnN0IGU9e29iaklkOncsZm46bSxhcmdzOmIsb3B0aW9uYWxDb250ZW50OmcsaGFzTWFzazp5fTtpLnNldChuLHUsZSk7aWYodSl7dGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLHUsZSk7aWYoeCl7YXNzZXJ0KFMsIlRoZSBnbG9iYWwgY2FjaGUtZGF0YSBtdXN0IGJlIGF2YWlsYWJsZS4iKTt0aGlzLmdsb2JhbEltYWdlQ2FjaGUuc2V0RGF0YSh1LFMpfX19fWhhbmRsZVNNYXNrKGUsdCxyLGEsbixpLHMpe2NvbnN0IG89ZS5nZXQoIkciKSxjPXtzdWJ0eXBlOmUuZ2V0KCJTIikubmFtZSxiYWNrZHJvcDplLmdldCgiQkMiKX0sbD1lLmdldCgiVFIiKTtpZihpc1BERkZ1bmN0aW9uKGwpKXtjb25zdCBlPXRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUobCksdD1uZXcgVWludDhBcnJheSgyNTYpLHI9bmV3IEZsb2F0MzJBcnJheSgxKTtmb3IobGV0IGE9MDthPDI1NjthKyspe3JbMF09YS8yNTU7ZShyLDAsciwwKTt0W2FdPTI1NSpyWzBdfDB9Yy50cmFuc2Zlck1hcD10fXJldHVybiB0aGlzLmJ1aWxkRm9ybVhPYmplY3QodCxvLGMscixhLG4uc3RhdGUuY2xvbmUoe25ld1BhdGg6ITB9KSxpLHMpfWhhbmRsZVRyYW5zZmVyRnVuY3Rpb24oZSl7bGV0IHQ7aWYoQXJyYXkuaXNBcnJheShlKSl0PWU7ZWxzZXtpZighaXNQREZGdW5jdGlvbihlKSlyZXR1cm4gbnVsbDt0PVtlXX1jb25zdCByPVtdO2xldCBhPTAsbj0wO2Zvcihjb25zdCBlIG9mIHQpe2NvbnN0IHQ9dGhpcy54cmVmLmZldGNoSWZSZWYoZSk7YSsrO2lmKGlzTmFtZSh0LCJJZGVudGl0eSIpKXtyLnB1c2gobnVsbCk7Y29udGludWV9aWYoIWlzUERGRnVuY3Rpb24odCkpcmV0dXJuIG51bGw7Y29uc3QgaT10aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHQpLHM9bmV3IFVpbnQ4QXJyYXkoMjU2KSxvPW5ldyBGbG9hdDMyQXJyYXkoMSk7Zm9yKGxldCBlPTA7ZTwyNTY7ZSsrKXtvWzBdPWUvMjU1O2kobywwLG8sMCk7c1tlXT0yNTUqb1swXXwwfXIucHVzaChzKTtuKyt9cmV0dXJuIDEhPT1hJiY0IT09YXx8MD09PW4/bnVsbDpyfWhhbmRsZVRpbGluZ1R5cGUoZSx0LHIsYSxuLGkscyxvKXtjb25zdCBjPW5ldyBPcGVyYXRvckxpc3QsbD1EaWN0Lm1lcmdlKHt4cmVmOnRoaXMueHJlZixkaWN0QXJyYXk6W24uZ2V0KCJSZXNvdXJjZXMiKSxyXX0pO3JldHVybiB0aGlzLmdldE9wZXJhdG9yTGlzdCh7c3RyZWFtOmEsdGFzazpzLHJlc291cmNlczpsLG9wZXJhdG9yTGlzdDpjfSkudGhlbihmdW5jdGlvbigpe2NvbnN0IHI9Yy5nZXRJUigpLGE9Z2V0VGlsaW5nUGF0dGVybklSKHIsbix0KTtpLmFkZERlcGVuZGVuY2llcyhjLmRlcGVuZGVuY2llcyk7aS5hZGRPcChlLGEpO24ub2JqSWQmJm8uc2V0KG51bGwsbi5vYmpJZCx7b3BlcmF0b3JMaXN0SVI6cixkaWN0Om59KX0pLmNhdGNoKGU9PntpZighKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikpe2lmKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IGU7d2FybihgaGFuZGxlVGlsaW5nVHlwZSAtIGlnbm9yaW5nIHBhdHRlcm46ICIke2V9Ii5gKX19KX1hc3luYyBoYW5kbGVTZXRGb250KGUsdCxyLGEsbixpLHM9bnVsbCxvPW51bGwpe2NvbnN0IGM9dD8uWzBdaW5zdGFuY2VvZiBOYW1lP3RbMF0ubmFtZTpudWxsLGw9YXdhaXQgdGhpcy5sb2FkRm9udChjLHIsZSxuLHMsbyk7bC5mb250LmlzVHlwZTNGb250JiZhLmFkZERlcGVuZGVuY2llcyhsLnR5cGUzRGVwZW5kZW5jaWVzKTtpLmZvbnQ9bC5mb250O2wuc2VuZCh0aGlzLmhhbmRsZXIpO3JldHVybiBsLmxvYWRlZE5hbWV9aGFuZGxlVGV4dChlLHQpe2NvbnN0IHI9dC5mb250LGE9ci5jaGFyc1RvR2x5cGhzKGUpO2lmKHIuZGF0YSl7KCEhKHQudGV4dFJlbmRlcmluZ01vZGUmQyl8fCJQYXR0ZXJuIj09PXQuZmlsbENvbG9yU3BhY2UubmFtZXx8ci5kaXNhYmxlRm9udEZhY2UpJiZQYXJ0aWFsRXZhbHVhdG9yLmJ1aWxkRm9udFBhdGhzKHIsYSx0aGlzLmhhbmRsZXIsdGhpcy5vcHRpb25zKX1yZXR1cm4gYX1lbnN1cmVTdGF0ZUZvbnQoZSl7aWYoZS5mb250KXJldHVybjtjb25zdCB0PW5ldyBGb3JtYXRFcnJvcigiTWlzc2luZyBzZXRGb250IChUZikgb3BlcmF0b3IgYmVmb3JlIHRleHQgcmVuZGVyaW5nIG9wZXJhdG9yLiIpO2lmKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IHQ7d2FybihgZW5zdXJlU3RhdGVGb250OiAiJHt0fSIuYCl9YXN5bmMgc2V0R1N0YXRlKHtyZXNvdXJjZXM6ZSxnU3RhdGU6dCxvcGVyYXRvckxpc3Q6cixjYWNoZUtleTphLHRhc2s6bixzdGF0ZU1hbmFnZXI6aSxsb2NhbEdTdGF0ZUNhY2hlOnMsbG9jYWxDb2xvclNwYWNlQ2FjaGU6byxzZWVuUmVmczpjfSl7Y29uc3QgbD10Lm9iaklkO2xldCBoPSEwO2NvbnN0IHU9W107bGV0IGQ9UHJvbWlzZS5yZXNvbHZlKCk7Zm9yKGNvbnN0W2Esc11vZiB0KXN3aXRjaChhKXtjYXNlIlR5cGUiOmJyZWFrO2Nhc2UiTFciOmlmKCJudW1iZXIiIT10eXBlb2Ygcyl7d2FybihgSW52YWxpZCBMVyAobGluZSB3aWR0aCk6ICR7c31gKTticmVha311LnB1c2goW2EsTWF0aC5hYnMocyldKTticmVhaztjYXNlIkxDIjpjYXNlIkxKIjpjYXNlIk1MIjpjYXNlIkQiOmNhc2UiUkkiOmNhc2UiRkwiOmNhc2UiQ0EiOmNhc2UiY2EiOnUucHVzaChbYSxzXSk7YnJlYWs7Y2FzZSJGb250IjpoPSExO2Q9ZC50aGVuKCgpPT50aGlzLmhhbmRsZVNldEZvbnQoZSxudWxsLHNbMF0scixuLGkuc3RhdGUpLnRoZW4oZnVuY3Rpb24oZSl7ci5hZGREZXBlbmRlbmN5KGUpO3UucHVzaChbYSxbZSxzWzFdXV0pfSkpO2JyZWFrO2Nhc2UiQk0iOnUucHVzaChbYSxub3JtYWxpemVCbGVuZE1vZGUocyldKTticmVhaztjYXNlIlNNYXNrIjppZihpc05hbWUocywiTm9uZSIpKXt1LnB1c2goW2EsITFdKTticmVha31pZihzIGluc3RhbmNlb2YgRGljdCl7aD0hMTtkPWQudGhlbigoKT0+dGhpcy5oYW5kbGVTTWFzayhzLGUscixuLGksbyxjKSk7dS5wdXNoKFthLCEwXSl9ZWxzZSB3YXJuKCJVbnN1cHBvcnRlZCBTTWFzayB0eXBlIik7YnJlYWs7Y2FzZSJUUiI6Y29uc3QgdD10aGlzLmhhbmRsZVRyYW5zZmVyRnVuY3Rpb24ocyk7dS5wdXNoKFthLHRdKTticmVhaztjYXNlIk9QIjpjYXNlIm9wIjpjYXNlIk9QTSI6Y2FzZSJCRyI6Y2FzZSJCRzIiOmNhc2UiVUNSIjpjYXNlIlVDUjIiOmNhc2UiVFIyIjpjYXNlIkhUIjpjYXNlIlNNIjpjYXNlIlNBIjpjYXNlIkFJUyI6Y2FzZSJUSyI6aW5mbygiZ3JhcGhpYyBzdGF0ZSBvcGVyYXRvciAiK2EpO2JyZWFrO2RlZmF1bHQ6aW5mbygiVW5rbm93biBncmFwaGljIHN0YXRlIG9wZXJhdG9yICIrYSl9YXdhaXQgZDt1Lmxlbmd0aD4wJiZyLmFkZE9wKGJlLFt1XSk7aCYmcy5zZXQoYSxsLHUpfWxvYWRGb250KGUsdCxyLGEsbj1udWxsLGk9bnVsbCl7Y29uc3QgZXJyb3JGb250PWFzeW5jKCk9Pm5ldyBUcmFuc2xhdGVkRm9udCh7bG9hZGVkTmFtZToiZ19mb250X2Vycm9yIixmb250Om5ldyBFcnJvckZvbnQoYEZvbnQgIiR7ZX0iIGlzIG5vdCBhdmFpbGFibGUuYCksZGljdDp0fSk7bGV0IHM7aWYodCl0IGluc3RhbmNlb2YgUmVmJiYocz10KTtlbHNle2NvbnN0IHQ9ci5nZXQoIkZvbnQiKTt0JiYocz10LmdldFJhdyhlKSl9aWYocyl7aWYodGhpcy50eXBlM0ZvbnRSZWZzPy5oYXMocykpcmV0dXJuIGVycm9yRm9udCgpO2lmKHRoaXMuZm9udENhY2hlLmhhcyhzKSlyZXR1cm4gdGhpcy5mb250Q2FjaGUuZ2V0KHMpO3RyeXt0PXRoaXMueHJlZi5mZXRjaElmUmVmKHMpfWNhdGNoKGUpe3dhcm4oYGxvYWRGb250IC0gbG9va3VwIGZhaWxlZDogIiR7ZX0iLmApfX1pZighKHQgaW5zdGFuY2VvZiBEaWN0KSl7aWYoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMmJiF0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpe3dhcm4oYEZvbnQgIiR7ZX0iIGlzIG5vdCBhdmFpbGFibGUuYCk7cmV0dXJuIGVycm9yRm9udCgpfXdhcm4oYEZvbnQgIiR7ZX0iIGlzIG5vdCBhdmFpbGFibGUgLS0gYXR0ZW1wdGluZyB0byBmYWxsYmFjayB0byBhIGRlZmF1bHQgZm9udC5gKTt0PW58fFBhcnRpYWxFdmFsdWF0b3IuZmFsbGJhY2tGb250RGljdH1pZih0LmNhY2hlS2V5JiZ0aGlzLmZvbnRDYWNoZS5oYXModC5jYWNoZUtleSkpcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldCh0LmNhY2hlS2V5KTtjb25zdHtwcm9taXNlOm8scmVzb2x2ZTpjfT1Qcm9taXNlLndpdGhSZXNvbHZlcnMoKTtsZXQgbDt0cnl7bD10aGlzLnByZUV2YWx1YXRlRm9udCh0KTtsLmNzc0ZvbnRJbmZvPWl9Y2F0Y2goZSl7d2FybihgbG9hZEZvbnQgLSBwcmVFdmFsdWF0ZUZvbnQgZmFpbGVkOiAiJHtlfSIuYCk7cmV0dXJuIGVycm9yRm9udCgpfWNvbnN0e2Rlc2NyaXB0b3I6aCxoYXNoOnV9PWwsZD1zIGluc3RhbmNlb2YgUmVmO2xldCBmO2lmKHUmJmggaW5zdGFuY2VvZiBEaWN0KXtjb25zdCBlPWguZm9udEFsaWFzZXN8fD1PYmplY3QuY3JlYXRlKG51bGwpO2lmKGVbdV0pe2NvbnN0IHQ9ZVt1XS5hbGlhc1JlZjtpZihkJiZ0JiZ0aGlzLmZvbnRDYWNoZS5oYXModCkpe3RoaXMuZm9udENhY2hlLnB1dEFsaWFzKHMsdCk7cmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChzKX19ZWxzZSBlW3VdPXtmb250SUQ6dGhpcy5pZEZhY3RvcnkuY3JlYXRlRm9udElkKCl9O2QmJihlW3VdLmFsaWFzUmVmPXMpO2Y9ZVt1XS5mb250SUR9ZWxzZSBmPXRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpO2Fzc2VydChmPy5zdGFydHNXaXRoKCJmIiksJ1RoZSAiZm9udElEIiBtdXN0IGJlIChjb3JyZWN0bHkpIGRlZmluZWQuJyk7aWYoZCl0aGlzLmZvbnRDYWNoZS5wdXQocyxvKTtlbHNle3QuY2FjaGVLZXk9YGNhY2hlS2V5XyR7Zn1gO3RoaXMuZm9udENhY2hlLnB1dCh0LmNhY2hlS2V5LG8pfXQubG9hZGVkTmFtZT1gJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV8ke2Z9YDt0aGlzLnRyYW5zbGF0ZUZvbnQobCkudGhlbihhc3luYyBlPT57Y29uc3Qgbj1uZXcgVHJhbnNsYXRlZEZvbnQoe2xvYWRlZE5hbWU6dC5sb2FkZWROYW1lLGZvbnQ6ZSxkaWN0OnR9KTtpZihlLmlzVHlwZTNGb250KXRyeXthd2FpdCBuLmxvYWRUeXBlM0RhdGEodGhpcyxyLGEpfWNhdGNoKGUpe3Rocm93IG5ldyBFcnJvcihgVHlwZTMgZm9udCBsb2FkIGVycm9yOiAke2V9YCl9YyhuKX0pLmNhdGNoKGU9Pnt3YXJuKGBsb2FkRm9udCAtIHRyYW5zbGF0ZUZvbnQgZmFpbGVkOiAiJHtlfSIuYCk7YyhuZXcgVHJhbnNsYXRlZEZvbnQoe2xvYWRlZE5hbWU6dC5sb2FkZWROYW1lLGZvbnQ6bmV3IEVycm9yRm9udChlPy5tZXNzYWdlKSxkaWN0OnR9KSl9KTtyZXR1cm4gb31idWlsZFBhdGgoZSx0LHIpe2NvbnN0e3BhdGhNaW5NYXg6YSxwYXRoQnVmZmVyOm59PXI7c3dpdGNoKDB8ZSl7Y2FzZSBJZTp7Y29uc3QgZT1yLmN1cnJlbnRQb2ludFg9dFswXSxpPXIuY3VycmVudFBvaW50WT10WzFdLHM9dFsyXSxvPXRbM10sYz1lK3MsbD1pK287MD09PXN8fDA9PT1vP24ucHVzaCgkdCxlLGksVnQsYyxsLEp0KTpuLnB1c2goJHQsZSxpLFZ0LGMsaSxWdCxjLGwsVnQsZSxsLEp0KTtVdGlsLnJlY3RCb3VuZGluZ0JveChlLGksYyxsLGEpO2JyZWFrfWNhc2UgU2U6e2NvbnN0IGU9ci5jdXJyZW50UG9pbnRYPXRbMF0saT1yLmN1cnJlbnRQb2ludFk9dFsxXTtuLnB1c2goJHQsZSxpKTtVdGlsLnBvaW50Qm91bmRpbmdCb3goZSxpLGEpO2JyZWFrfWNhc2UgQWU6e2NvbnN0IGU9ci5jdXJyZW50UG9pbnRYPXRbMF0saT1yLmN1cnJlbnRQb2ludFk9dFsxXTtuLnB1c2goVnQsZSxpKTtVdGlsLnBvaW50Qm91bmRpbmdCb3goZSxpLGEpO2JyZWFrfWNhc2Uga2U6e2NvbnN0IGU9ci5jdXJyZW50UG9pbnRYLGk9ci5jdXJyZW50UG9pbnRZLFtzLG8sYyxsLGgsdV09dDtyLmN1cnJlbnRQb2ludFg9aDtyLmN1cnJlbnRQb2ludFk9dTtuLnB1c2goS3QscyxvLGMsbCxoLHUpO1V0aWwuYmV6aWVyQm91bmRpbmdCb3goZSxpLHMsbyxjLGwsaCx1LGEpO2JyZWFrfWNhc2UgQ2U6e2NvbnN0IGU9ci5jdXJyZW50UG9pbnRYLGk9ci5jdXJyZW50UG9pbnRZLFtzLG8sYyxsXT10O3IuY3VycmVudFBvaW50WD1jO3IuY3VycmVudFBvaW50WT1sO24ucHVzaChLdCxlLGkscyxvLGMsbCk7VXRpbC5iZXppZXJCb3VuZGluZ0JveChlLGksZSxpLHMsbyxjLGwsYSk7YnJlYWt9Y2FzZSB2ZTp7Y29uc3QgZT1yLmN1cnJlbnRQb2ludFgsaT1yLmN1cnJlbnRQb2ludFksW3MsbyxjLGxdPXQ7ci5jdXJyZW50UG9pbnRYPWM7ci5jdXJyZW50UG9pbnRZPWw7bi5wdXNoKEt0LHMsbyxjLGwsYyxsKTtVdGlsLmJlemllckJvdW5kaW5nQm94KGUsaSxzLG8sYyxsLGMsbCxhKTticmVha31jYXNlIEZlOm4ucHVzaChKdCl9fV9nZXRDb2xvclNwYWNlKGUsdCxyKXtyZXR1cm4gQ29sb3JTcGFjZVV0aWxzLnBhcnNlKHtjczplLHhyZWY6dGhpcy54cmVmLHJlc291cmNlczp0LHBkZkZ1bmN0aW9uRmFjdG9yeTp0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOnRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLGxvY2FsQ29sb3JTcGFjZUNhY2hlOnIsYXN5bmNJZk5vdENhY2hlZDohMH0pfWFzeW5jIF9oYW5kbGVDb2xvclNwYWNlKGUpe3RyeXtyZXR1cm4gYXdhaXQgZX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pcmV0dXJuIG51bGw7aWYodGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycyl7d2FybihgX2hhbmRsZUNvbG9yU3BhY2UgLSBpZ25vcmluZyBDb2xvclNwYWNlOiAiJHtlfSIuYCk7cmV0dXJuIG51bGx9dGhyb3cgZX19cGFyc2VTaGFkaW5nKHtzaGFkaW5nOmUscmVzb3VyY2VzOnQsbG9jYWxDb2xvclNwYWNlQ2FjaGU6cixsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGU6YX0pe2xldCBuLGk9YS5nZXQoZSk7aWYoaSlyZXR1cm4gaTt0cnl7bj1QYXR0ZXJuLnBhcnNlU2hhZGluZyhlLHRoaXMueHJlZix0LHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSx0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSxyKS5nZXRJUigpfWNhdGNoKHQpe2lmKHQgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbilyZXR1cm4gbnVsbDtpZih0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXt3YXJuKGBwYXJzZVNoYWRpbmcgLSBpZ25vcmluZyBzaGFkaW5nOiAiJHt0fSIuYCk7YS5zZXQoZSxudWxsKTtyZXR1cm4gbnVsbH10aHJvdyB0fWk9YHBhdHRlcm5fJHt0aGlzLmlkRmFjdG9yeS5jcmVhdGVPYmpJZCgpfWA7dGhpcy5wYXJzaW5nVHlwZTNGb250JiYoaT1gJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV90eXBlM18ke2l9YCk7YS5zZXQoZSxpKTt0aGlzLnBhcnNpbmdUeXBlM0ZvbnQ/dGhpcy5oYW5kbGVyLnNlbmQoImNvbW1vbm9iaiIsW2ksIlBhdHRlcm4iLG5dKTp0aGlzLmhhbmRsZXIuc2VuZCgib2JqIixbaSx0aGlzLnBhZ2VJbmRleCwiUGF0dGVybiIsbl0pO3JldHVybiBpfWhhbmRsZUNvbG9yTihlLHQscixhLG4saSxzLG8sYyxsKXtjb25zdCBoPXIucG9wKCk7aWYoaCBpbnN0YW5jZW9mIE5hbWUpe2NvbnN0IHU9bi5nZXRSYXcoaC5uYW1lKSxkPXUgaW5zdGFuY2VvZiBSZWYmJmMuZ2V0QnlSZWYodSk7aWYoZCl0cnl7Y29uc3Qgbj1hLmJhc2U/YS5iYXNlLmdldFJnYkhleChyLDApOm51bGwsaT1nZXRUaWxpbmdQYXR0ZXJuSVIoZC5vcGVyYXRvckxpc3RJUixkLmRpY3Qsbik7ZS5hZGRPcCh0LGkpO3JldHVybn1jYXRjaHt9Y29uc3QgZj10aGlzLnhyZWYuZmV0Y2hJZlJlZih1KTtpZihmKXtjb25zdCBuPWYgaW5zdGFuY2VvZiBCYXNlU3RyZWFtP2YuZGljdDpmLGg9bi5nZXQoIlBhdHRlcm5UeXBlIik7aWYoaD09PXlpKXtjb25zdCBvPWEuYmFzZT9hLmJhc2UuZ2V0UmdiSGV4KHIsMCk6bnVsbDtyZXR1cm4gdGhpcy5oYW5kbGVUaWxpbmdUeXBlKHQsbyxpLGYsbixlLHMsYyl9aWYoaD09PXdpKXtjb25zdCByPW4uZ2V0KCJTaGFkaW5nIiksYT10aGlzLnBhcnNlU2hhZGluZyh7c2hhZGluZzpyLHJlc291cmNlczppLGxvY2FsQ29sb3JTcGFjZUNhY2hlOm8sbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlOmx9KTtpZihhKXtjb25zdCByPWxvb2t1cE1hdHJpeChuLmdldEFycmF5KCJNYXRyaXgiKSxudWxsKTtlLmFkZE9wKHQsWyJTaGFkaW5nIixhLHJdKX1yZXR1cm59dGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbmtub3duIFBhdHRlcm5UeXBlOiAke2h9YCl9fXRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBQYXR0ZXJuTmFtZTogJHtofWApfV9wYXJzZVZpc2liaWxpdHlFeHByZXNzaW9uKGUsdCxyKXtpZigrK3Q+MTApe3dhcm4oIlZpc2liaWxpdHkgZXhwcmVzc2lvbiBpcyB0b28gZGVlcGx5IG5lc3RlZCIpO3JldHVybn1jb25zdCBhPWUubGVuZ3RoLG49dGhpcy54cmVmLmZldGNoSWZSZWYoZVswXSk7aWYoIShhPDIpJiZuIGluc3RhbmNlb2YgTmFtZSl7c3dpdGNoKG4ubmFtZSl7Y2FzZSJBbmQiOmNhc2UiT3IiOmNhc2UiTm90IjpyLnB1c2gobi5uYW1lKTticmVhaztkZWZhdWx0Ondhcm4oYEludmFsaWQgb3BlcmF0b3IgJHtuLm5hbWV9IGluIHZpc2liaWxpdHkgZXhwcmVzc2lvbmApO3JldHVybn1mb3IobGV0IG49MTtuPGE7bisrKXtjb25zdCBhPWVbbl0saT10aGlzLnhyZWYuZmV0Y2hJZlJlZihhKTtpZihBcnJheS5pc0FycmF5KGkpKXtjb25zdCBlPVtdO3IucHVzaChlKTt0aGlzLl9wYXJzZVZpc2liaWxpdHlFeHByZXNzaW9uKGksdCxlKX1lbHNlIGEgaW5zdGFuY2VvZiBSZWYmJnIucHVzaChhLnRvU3RyaW5nKCkpfX1lbHNlIHdhcm4oIkludmFsaWQgdmlzaWJpbGl0eSBleHByZXNzaW9uIil9YXN5bmMgcGFyc2VNYXJrZWRDb250ZW50UHJvcHMoZSx0KXtsZXQgcjtpZihlIGluc3RhbmNlb2YgTmFtZSl7cj10LmdldCgiUHJvcGVydGllcyIpLmdldChlLm5hbWUpfWVsc2V7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJPcHRpb25hbCBjb250ZW50IHByb3BlcnRpZXMgbWFsZm9ybWVkLiIpO3I9ZX1jb25zdCBhPXIuZ2V0KCJUeXBlIik/Lm5hbWU7aWYoIk9DRyI9PT1hKXJldHVybnt0eXBlOmEsaWQ6ci5vYmpJZH07aWYoIk9DTUQiPT09YSl7Y29uc3QgZT1yLmdldCgiVkUiKTtpZihBcnJheS5pc0FycmF5KGUpKXtjb25zdCB0PVtdO3RoaXMuX3BhcnNlVmlzaWJpbGl0eUV4cHJlc3Npb24oZSwwLHQpO2lmKHQubGVuZ3RoPjApcmV0dXJue3R5cGU6Ik9DTUQiLGV4cHJlc3Npb246dH19Y29uc3QgdD1yLmdldCgiT0NHcyIpO2lmKEFycmF5LmlzQXJyYXkodCl8fHQgaW5zdGFuY2VvZiBEaWN0KXtjb25zdCBlPVtdO2lmKEFycmF5LmlzQXJyYXkodCkpZm9yKGNvbnN0IHIgb2YgdCllLnB1c2goci50b1N0cmluZygpKTtlbHNlIGUucHVzaCh0Lm9iaklkKTtyZXR1cm57dHlwZTphLGlkczplLHBvbGljeTpyLmdldCgiUCIpaW5zdGFuY2VvZiBOYW1lP3IuZ2V0KCJQIikubmFtZTpudWxsLGV4cHJlc3Npb246bnVsbH19aWYodCBpbnN0YW5jZW9mIFJlZilyZXR1cm57dHlwZTphLGlkOnQudG9TdHJpbmcoKX19cmV0dXJuIG51bGx9Z2V0T3BlcmF0b3JMaXN0KHtzdHJlYW06ZSx0YXNrOnQscmVzb3VyY2VzOnIsb3BlcmF0b3JMaXN0OmEsaW5pdGlhbFN0YXRlOm49bnVsbCxmYWxsYmFja0ZvbnREaWN0Omk9bnVsbCxwcmV2UmVmczpzPW51bGx9KXtjb25zdCBvPWUuZGljdD8ub2JqSWQsYz1uZXcgUmVmU2V0KHMpO2lmKG8pe2lmKHM/LmhhcyhvKSl0aHJvdyBuZXcgRXJyb3IoYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtvfWApO2MucHV0KG8pfXJ8fD1EaWN0LmVtcHR5O258fD1uZXcgRXZhbFN0YXRlO2lmKCFhKXRocm93IG5ldyBFcnJvcignZ2V0T3BlcmF0b3JMaXN0OiBtaXNzaW5nICJvcGVyYXRvckxpc3QiIHBhcmFtZXRlcicpO2NvbnN0IGw9dGhpcyxoPXRoaXMueHJlZix1PW5ldyBMb2NhbEltYWdlQ2FjaGUsZD1uZXcgTG9jYWxDb2xvclNwYWNlQ2FjaGUsZj1uZXcgTG9jYWxHU3RhdGVDYWNoZSxnPW5ldyBMb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSxwPW5ldyBNYXAsbT1yLmdldCgiWE9iamVjdCIpfHxEaWN0LmVtcHR5LGI9ci5nZXQoIlBhdHRlcm4iKXx8RGljdC5lbXB0eSx5PW5ldyBTdGF0ZU1hbmFnZXIobiksdz1uZXcgRXZhbHVhdG9yUHJlcHJvY2Vzc29yKGUsaCx5KSx4PW5ldyBUaW1lU2xvdE1hbmFnZXI7ZnVuY3Rpb24gY2xvc2VQZW5kaW5nUmVzdG9yZU9QUyhlKXtmb3IobGV0IGU9MCx0PXcuc2F2ZWRTdGF0ZXNEZXB0aDtlPHQ7ZSsrKWEuYWRkT3Aod2UsW10pfXJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBwcm9taXNlQm9keShlLG4pe2NvbnN0IG5leHQ9ZnVuY3Rpb24odCl7UHJvbWlzZS5hbGwoW3QsYS5yZWFkeV0pLnRoZW4oZnVuY3Rpb24oKXt0cnl7cHJvbWlzZUJvZHkoZSxuKX1jYXRjaChlKXtuKGUpfX0sbil9O3QuZW5zdXJlTm90VGVybWluYXRlZCgpO3gucmVzZXQoKTtjb25zdCBzPXt9O2xldCBvLFMsayxDLHYsVDtmb3IoOyEobz14LmNoZWNrKCkpOyl7cy5hcmdzPW51bGw7aWYoIXcucmVhZChzKSlicmVhaztsZXQgZT1zLmFyZ3Msbj1zLmZuO3N3aXRjaCgwfG4pe2Nhc2UgU3Q6VD1lWzBdaW5zdGFuY2VvZiBOYW1lO3Y9ZVswXS5uYW1lO2lmKFQpe2NvbnN0IHQ9dS5nZXRCeU5hbWUodik7aWYodCl7YWRkQ2FjaGVkSW1hZ2VPcHMoYSx0KTtlPW51bGw7Y29udGludWV9fW5leHQobmV3IFByb21pc2UoZnVuY3Rpb24oZSxuKXtpZighVCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlhPYmplY3QgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpO2xldCBpPW0uZ2V0UmF3KHYpO2lmKGkgaW5zdGFuY2VvZiBSZWYpe2NvbnN0IHQ9dS5nZXRCeVJlZihpKXx8bC5fcmVnaW9uYWxJbWFnZUNhY2hlLmdldEJ5UmVmKGkpfHxsLmdsb2JhbEltYWdlQ2FjaGUuZ2V0RGF0YShpLGwucGFnZUluZGV4KTtpZih0KXthZGRDYWNoZWRJbWFnZU9wcyhhLHQpO2UoKTtyZXR1cm59aT1oLmZldGNoKGkpfWlmKCEoaSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pKXRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgYmUgYSBzdHJlYW0iKTtjb25zdCBzPWkuZGljdC5nZXQoIlN1YnR5cGUiKTtpZighKHMgaW5zdGFuY2VvZiBOYW1lKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlhPYmplY3Qgc2hvdWxkIGhhdmUgYSBOYW1lIHN1YnR5cGUiKTtpZigiRm9ybSIhPT1zLm5hbWUpaWYoIkltYWdlIiE9PXMubmFtZSl7aWYoIlBTIiE9PXMubmFtZSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVuaGFuZGxlZCBYT2JqZWN0IHN1YnR5cGUgJHtzLm5hbWV9YCk7aW5mbygiSWdub3JlZCBYT2JqZWN0IHN1YnR5cGUgUFMiKTtlKCl9ZWxzZSBsLmJ1aWxkUGFpbnRJbWFnZVhPYmplY3Qoe3Jlc291cmNlczpyLGltYWdlOmksb3BlcmF0b3JMaXN0OmEsY2FjaGVLZXk6dixsb2NhbEltYWdlQ2FjaGU6dSxsb2NhbENvbG9yU3BhY2VDYWNoZTpkfSkudGhlbihlLG4pO2Vsc2V7eS5zYXZlKCk7bC5idWlsZEZvcm1YT2JqZWN0KHIsaSxudWxsLGEsdCx5LnN0YXRlLmNsb25lKHtuZXdQYXRoOiEwfSksZCxjKS50aGVuKGZ1bmN0aW9uKCl7eS5yZXN0b3JlKCk7ZSgpfSxuKX19KS5jYXRjaChmdW5jdGlvbihlKXtpZighKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikpe2lmKCFsLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IGU7d2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgWE9iamVjdDogIiR7ZX0iLmApfX0pKTtyZXR1cm47Y2FzZSB6ZTpjb25zdCBzPWVbMV07bmV4dChsLmhhbmRsZVNldEZvbnQocixlLG51bGwsYSx0LHkuc3RhdGUsaSkudGhlbihmdW5jdGlvbihlKXthLmFkZERlcGVuZGVuY3koZSk7YS5hZGRPcCh6ZSxbZSxzXSl9KSk7cmV0dXJuO2Nhc2UgeHQ6Y29uc3Qgbz1lWzBdLmNhY2hlS2V5O2lmKG8pe2NvbnN0IHQ9dS5nZXRCeU5hbWUobyk7aWYodCl7YWRkQ2FjaGVkSW1hZ2VPcHMoYSx0KTtlPW51bGw7Y29udGludWV9fW5leHQobC5idWlsZFBhaW50SW1hZ2VYT2JqZWN0KHtyZXNvdXJjZXM6cixpbWFnZTplWzBdLGlzSW5saW5lOiEwLG9wZXJhdG9yTGlzdDphLGNhY2hlS2V5Om8sbG9jYWxJbWFnZUNhY2hlOnUsbG9jYWxDb2xvclNwYWNlQ2FjaGU6ZH0pKTtyZXR1cm47Y2FzZSBaZTppZigheS5zdGF0ZS5mb250KXtsLmVuc3VyZVN0YXRlRm9udCh5LnN0YXRlKTtjb250aW51ZX1lWzBdPWwuaGFuZGxlVGV4dChlWzBdLHkuc3RhdGUpO2JyZWFrO2Nhc2UgUWU6aWYoIXkuc3RhdGUuZm9udCl7bC5lbnN1cmVTdGF0ZUZvbnQoeS5zdGF0ZSk7Y29udGludWV9Y29uc3Qgdz1bXSx4PXkuc3RhdGU7Zm9yKGNvbnN0IHQgb2YgZVswXSkic3RyaW5nIj09dHlwZW9mIHQ/dy5wdXNoKC4uLmwuaGFuZGxlVGV4dCh0LHgpKToibnVtYmVyIj09dHlwZW9mIHQmJncucHVzaCh0KTtlWzBdPXc7bj1aZTticmVhaztjYXNlIGV0OmlmKCF5LnN0YXRlLmZvbnQpe2wuZW5zdXJlU3RhdGVGb250KHkuc3RhdGUpO2NvbnRpbnVlfWEuYWRkT3AoWWUpO2VbMF09bC5oYW5kbGVUZXh0KGVbMF0seS5zdGF0ZSk7bj1aZTticmVhaztjYXNlIHR0OmlmKCF5LnN0YXRlLmZvbnQpe2wuZW5zdXJlU3RhdGVGb250KHkuc3RhdGUpO2NvbnRpbnVlfWEuYWRkT3AoWWUpO2EuYWRkT3AoWGUsW2Uuc2hpZnQoKV0pO2EuYWRkT3AocWUsW2Uuc2hpZnQoKV0pO2VbMF09bC5oYW5kbGVUZXh0KGVbMF0seS5zdGF0ZSk7bj1aZTticmVhaztjYXNlIEdlOnkuc3RhdGUudGV4dFJlbmRlcmluZ01vZGU9ZVswXTticmVhaztjYXNlIHN0Ontjb25zdCB0PWwuX2dldENvbG9yU3BhY2UoZVswXSxyLGQpO2lmKHQgaW5zdGFuY2VvZiBDb2xvclNwYWNlKXt5LnN0YXRlLmZpbGxDb2xvclNwYWNlPXQ7Y29udGludWV9bmV4dChsLl9oYW5kbGVDb2xvclNwYWNlKHQpLnRoZW4oZT0+e3kuc3RhdGUuZmlsbENvbG9yU3BhY2U9ZXx8Q29sb3JTcGFjZVV0aWxzLmdyYXl9KSk7cmV0dXJufWNhc2UgaXQ6e2NvbnN0IHQ9bC5fZ2V0Q29sb3JTcGFjZShlWzBdLHIsZCk7aWYodCBpbnN0YW5jZW9mIENvbG9yU3BhY2Upe3kuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZT10O2NvbnRpbnVlfW5leHQobC5faGFuZGxlQ29sb3JTcGFjZSh0KS50aGVuKGU9Pnt5LnN0YXRlLnN0cm9rZUNvbG9yU3BhY2U9ZXx8Q29sb3JTcGFjZVV0aWxzLmdyYXl9KSk7cmV0dXJufWNhc2UgbHQ6Qz15LnN0YXRlLmZpbGxDb2xvclNwYWNlO2U9W0MuZ2V0UmdiSGV4KGUsMCldO249Z3Q7YnJlYWs7Y2FzZSBvdDpDPXkuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZTtlPVtDLmdldFJnYkhleChlLDApXTtuPWZ0O2JyZWFrO2Nhc2UgZHQ6eS5zdGF0ZS5maWxsQ29sb3JTcGFjZT1Db2xvclNwYWNlVXRpbHMuZ3JheTtlPVtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoZSwwKV07bj1ndDticmVhaztjYXNlIHV0Onkuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZT1Db2xvclNwYWNlVXRpbHMuZ3JheTtlPVtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoZSwwKV07bj1mdDticmVhaztjYXNlIG10Onkuc3RhdGUuZmlsbENvbG9yU3BhY2U9Q29sb3JTcGFjZVV0aWxzLmNteWs7ZT1bQ29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiSGV4KGUsMCldO249Z3Q7YnJlYWs7Y2FzZSBwdDp5LnN0YXRlLnN0cm9rZUNvbG9yU3BhY2U9Q29sb3JTcGFjZVV0aWxzLmNteWs7ZT1bQ29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiSGV4KGUsMCldO249ZnQ7YnJlYWs7Y2FzZSBndDp5LnN0YXRlLmZpbGxDb2xvclNwYWNlPUNvbG9yU3BhY2VVdGlscy5yZ2I7ZT1bQ29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JIZXgoZSwwKV07YnJlYWs7Y2FzZSBmdDp5LnN0YXRlLnN0cm9rZUNvbG9yU3BhY2U9Q29sb3JTcGFjZVV0aWxzLnJnYjtlPVtDb2xvclNwYWNlVXRpbHMucmdiLmdldFJnYkhleChlLDApXTticmVhaztjYXNlIGh0OkM9eS5zdGF0ZS5wYXR0ZXJuRmlsbENvbG9yU3BhY2U7aWYoIUMpe2lmKGlzTnVtYmVyQXJyYXkoZSxudWxsKSl7ZT1bQ29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSGV4KGUsMCldO249Z3Q7YnJlYWt9ZT1bXTtuPXp0O2JyZWFrfWlmKCJQYXR0ZXJuIj09PUMubmFtZSl7bmV4dChsLmhhbmRsZUNvbG9yTihhLGh0LGUsQyxiLHIsdCxkLGcscCkpO3JldHVybn1lPVtDLmdldFJnYkhleChlLDApXTtuPWd0O2JyZWFrO2Nhc2UgY3Q6Qz15LnN0YXRlLnBhdHRlcm5TdHJva2VDb2xvclNwYWNlO2lmKCFDKXtpZihpc051bWJlckFycmF5KGUsbnVsbCkpe2U9W0NvbG9yU3BhY2VVdGlscy5ncmF5LmdldFJnYkhleChlLDApXTtuPWZ0O2JyZWFrfWU9W107bj1XdDticmVha31pZigiUGF0dGVybiI9PT1DLm5hbWUpe25leHQobC5oYW5kbGVDb2xvck4oYSxjdCxlLEMsYixyLHQsZCxnLHApKTtyZXR1cm59ZT1bQy5nZXRSZ2JIZXgoZSwwKV07bj1mdDticmVhaztjYXNlIGJ0OmxldCBPO3RyeXtjb25zdCB0PXIuZ2V0KCJTaGFkaW5nIik7aWYoIXQpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJObyBzaGFkaW5nIHJlc291cmNlIGZvdW5kIik7Tz10LmdldChlWzBdLm5hbWUpO2lmKCFPKXRocm93IG5ldyBGb3JtYXRFcnJvcigiTm8gc2hhZGluZyBvYmplY3QgZm91bmQiKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pY29udGludWU7aWYobC5vcHRpb25zLmlnbm9yZUVycm9ycyl7d2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgU2hhZGluZzogIiR7ZX0iLmApO2NvbnRpbnVlfXRocm93IGV9Y29uc3QgTT1sLnBhcnNlU2hhZGluZyh7c2hhZGluZzpPLHJlc291cmNlczpyLGxvY2FsQ29sb3JTcGFjZUNhY2hlOmQsbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlOnB9KTtpZighTSljb250aW51ZTtlPVtNXTtuPWJ0O2JyZWFrO2Nhc2UgYmU6VD1lWzBdaW5zdGFuY2VvZiBOYW1lO3Y9ZVswXS5uYW1lO2lmKFQpe2NvbnN0IHQ9Zi5nZXRCeU5hbWUodik7aWYodCl7dC5sZW5ndGg+MCYmYS5hZGRPcChiZSxbdF0pO2U9bnVsbDtjb250aW51ZX19bmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbihlLG4pe2lmKCFUKXRocm93IG5ldyBGb3JtYXRFcnJvcigiR1N0YXRlIG11c3QgYmUgcmVmZXJyZWQgdG8gYnkgbmFtZS4iKTtjb25zdCBpPXIuZ2V0KCJFeHRHU3RhdGUiKTtpZighKGkgaW5zdGFuY2VvZiBEaWN0KSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkV4dEdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpO2NvbnN0IHM9aS5nZXQodik7aWYoIShzIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTtsLnNldEdTdGF0ZSh7cmVzb3VyY2VzOnIsZ1N0YXRlOnMsb3BlcmF0b3JMaXN0OmEsY2FjaGVLZXk6dix0YXNrOnQsc3RhdGVNYW5hZ2VyOnksbG9jYWxHU3RhdGVDYWNoZTpmLGxvY2FsQ29sb3JTcGFjZUNhY2hlOmQsc2VlblJlZnM6Y30pLnRoZW4oZSxuKX0pLmNhdGNoKGZ1bmN0aW9uKGUpe2lmKCEoZSBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSl7aWYoIWwub3B0aW9ucy5pZ25vcmVFcnJvcnMpdGhyb3cgZTt3YXJuKGBnZXRPcGVyYXRvckxpc3QgLSBpZ25vcmluZyBFeHRHU3RhdGU6ICIke2V9Ii5gKX19KSk7cmV0dXJuO2Nhc2UgaGU6e2NvbnN0W3RdPWU7aWYoIm51bWJlciIhPXR5cGVvZiB0KXt3YXJuKGBJbnZhbGlkIHNldExpbmVXaWR0aDogJHt0fWApO2NvbnRpbnVlfWVbMF09TWF0aC5hYnModCk7YnJlYWt9Y2FzZSBnZTp7Y29uc3QgdD1lWzFdO2lmKCJudW1iZXIiIT10eXBlb2YgdCl7d2FybihgSW52YWxpZCBzZXREYXNoOiAke3R9YCk7Y29udGludWV9Y29uc3Qgcj1lWzBdO2lmKCFBcnJheS5pc0FycmF5KHIpKXt3YXJuKGBJbnZhbGlkIHNldERhc2g6ICR7cn1gKTtjb250aW51ZX1yLnNvbWUoZT0+Im51bWJlciIhPXR5cGVvZiBlKSYmKGVbMF09ci5maWx0ZXIoZT0+Im51bWJlciI9PXR5cGVvZiBlKSk7YnJlYWt9Y2FzZSBTZTpjYXNlIEFlOmNhc2Uga2U6Y2FzZSBDZTpjYXNlIHZlOmNhc2UgRmU6Y2FzZSBJZTpsLmJ1aWxkUGF0aChuLGUseS5zdGF0ZSk7Y29udGludWU7Y2FzZSBUZTpjYXNlIE9lOmNhc2UgTWU6Y2FzZSBEZTpjYXNlIEJlOmNhc2UgUmU6Y2FzZSBFZTpjYXNlIE5lOmNhc2UgUGU6e2NvbnN0e3N0YXRlOntwYXRoQnVmZmVyOmUscGF0aE1pbk1heDp0fX09eTtuIT09T2UmJm4hPT1FZSYmbiE9PU5lfHxlLnB1c2goSnQpO2lmKDA9PT1lLmxlbmd0aClhLmFkZE9wKEh0LFtuLFtudWxsXSxudWxsXSk7ZWxzZXthLmFkZE9wKEh0LFtuLFtuZXcgRmxvYXQzMkFycmF5KGUpXSx0LnNsaWNlKCldKTtlLmxlbmd0aD0wO3Quc2V0KFsxLzAsMS8wLC0xLzAsLTEvMF0sMCl9Y29udGludWV9Y2FzZSBKZTphLmFkZE9wKG4sW25ldyBGbG9hdDMyQXJyYXkoZSldKTtjb250aW51ZTtjYXNlIEF0OmNhc2Uga3Q6Y2FzZSBJdDpjYXNlIFR0OmNvbnRpbnVlO2Nhc2UgdnQ6aWYoIShlWzBdaW5zdGFuY2VvZiBOYW1lKSl7d2FybihgRXhwZWN0ZWQgbmFtZSBmb3IgYmVnaW5NYXJrZWRDb250ZW50UHJvcHMgYXJnMD0ke2VbMF19YCk7YS5hZGRPcCh2dCxbIk9DIixudWxsXSk7Y29udGludWV9aWYoIk9DIj09PWVbMF0ubmFtZSl7bmV4dChsLnBhcnNlTWFya2VkQ29udGVudFByb3BzKGVbMV0scikudGhlbihlPT57YS5hZGRPcCh2dCxbIk9DIixlXSl9KS5jYXRjaChlPT57aWYoIShlIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pKXtpZighbC5vcHRpb25zLmlnbm9yZUVycm9ycyl0aHJvdyBlO3dhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIGJlZ2luTWFya2VkQ29udGVudFByb3BzOiAiJHtlfSIuYCk7YS5hZGRPcCh2dCxbIk9DIixudWxsXSl9fSkpO3JldHVybn1lPVtlWzBdLm5hbWUsZVsxXWluc3RhbmNlb2YgRGljdD9lWzFdLmdldCgiTUNJRCIpOm51bGxdO2JyZWFrO2RlZmF1bHQ6aWYobnVsbCE9PWUpe2ZvcihTPTAsaz1lLmxlbmd0aDtTPGsmJiEoZVtTXWluc3RhbmNlb2YgRGljdCk7UysrKTtpZihTPGspe3dhcm4oImdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIG9wZXJhdG9yOiAiK24pO2NvbnRpbnVlfX19YS5hZGRPcChuLGUpfWlmKG8pbmV4dCh4aSk7ZWxzZXtjbG9zZVBlbmRpbmdSZXN0b3JlT1BTKCk7ZSgpfX0pLmNhdGNoKGU9PntpZighKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikpe2lmKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IGU7d2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgZXJyb3JzIGR1cmluZyAiJHt0Lm5hbWV9IiB0YXNrOiAiJHtlfSIuYCk7Y2xvc2VQZW5kaW5nUmVzdG9yZU9QUygpfX0pfWdldFRleHRDb250ZW50KHtzdHJlYW06ZSx0YXNrOnQscmVzb3VyY2VzOnIsc3RhdGVNYW5hZ2VyOm49bnVsbCxpbmNsdWRlTWFya2VkQ29udGVudDppPSExLHNpbms6cyxzZWVuU3R5bGVzOm89bmV3IFNldCx2aWV3Qm94OmMsbGFuZzpsPW51bGwsbWFya2VkQ29udGVudERhdGE6aD1udWxsLGRpc2FibGVOb3JtYWxpemF0aW9uOnU9ITEsa2VlcFdoaXRlU3BhY2U6ZD0hMSxwcmV2UmVmczpmPW51bGwsaW50ZXJzZWN0b3I6Zz1udWxsfSl7Y29uc3QgcD1lLmRpY3Q/Lm9iaklkLG09bmV3IFJlZlNldChmKTtpZihwKXtpZihmPy5oYXMocCkpdGhyb3cgbmV3IEVycm9yKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtwfWApO20ucHV0KHApfXJ8fD1EaWN0LmVtcHR5O258fD1uZXcgU3RhdGVNYW5hZ2VyKG5ldyBUZXh0U3RhdGUpO2kmJihofHw9e2xldmVsOjB9KTtjb25zdCBiPXtpdGVtczpbXSxzdHlsZXM6T2JqZWN0LmNyZWF0ZShudWxsKSxsYW5nOmx9LHk9e2luaXRpYWxpemVkOiExLHN0cjpbXSx0b3RhbFdpZHRoOjAsdG90YWxIZWlnaHQ6MCx3aWR0aDowLGhlaWdodDowLHZlcnRpY2FsOiExLHByZXZUcmFuc2Zvcm06bnVsbCx0ZXh0QWR2YW5jZVNjYWxlOjAsc3BhY2VJbkZsb3dNaW46MCxzcGFjZUluRmxvd01heDowLHRyYWNraW5nU3BhY2VNaW46MS8wLG5lZ2F0aXZlU3BhY2VNYXg6LTEvMCxub3RBU3BhY2U6LTEvMCx0cmFuc2Zvcm06bnVsbCxmb250TmFtZTpudWxsLGhhc0VPTDohMX0sdz1bIiAiLCIgIl07bGV0IHg9MDtmdW5jdGlvbiBzYXZlTGFzdENoYXIoZSl7Y29uc3QgdD0oeCsxKSUyLHI9IiAiIT09d1t4XSYmIiAiPT09d1t0XTt3W3hdPWU7eD10O3JldHVybiFkJiZyfWZ1bmN0aW9uIHNob3VsZEFkZFdoaXRlcHNhY2UoKXtyZXR1cm4hZCYmIiAiIT09d1t4XSYmIiAiPT09d1soeCsxKSUyXX1mdW5jdGlvbiByZXNldExhc3RDaGFycygpe3dbMF09d1sxXT0iICI7eD0wfWNvbnN0IFM9dGhpcyxrPXRoaXMueHJlZixDPVtdO2xldCB2PW51bGw7Y29uc3QgVD1uZXcgTG9jYWxJbWFnZUNhY2hlLE89bmV3IExvY2FsR1N0YXRlQ2FjaGUsTT1uZXcgRXZhbHVhdG9yUHJlcHJvY2Vzc29yKGUsayxuKTtsZXQgRDtmdW5jdGlvbiBwdXNoV2hpdGVzcGFjZSh7d2lkdGg6ZT0wLGhlaWdodDp0PTAsdHJhbnNmb3JtOnI9eS5wcmV2VHJhbnNmb3JtLGZvbnROYW1lOmE9eS5mb250TmFtZX0pe2c/LmFkZEV4dHJhQ2hhcigiICIpO2IuaXRlbXMucHVzaCh7c3RyOiIgIixkaXI6Imx0ciIsd2lkdGg6ZSxoZWlnaHQ6dCx0cmFuc2Zvcm06cixmb250TmFtZTphLGhhc0VPTDohMX0pfWZ1bmN0aW9uIGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCl7Y29uc3QgZT1ELmZvbnQsdD1bRC5mb250U2l6ZSpELnRleHRIU2NhbGUsMCwwLEQuZm9udFNpemUsMCxELnRleHRSaXNlXTtpZihlLmlzVHlwZTNGb250JiYoRC5mb250U2l6ZTw9MXx8ZS5pc0NoYXJCQm94KSYmIWlzQXJyYXlFcXVhbChELmZvbnRNYXRyaXgsYSkpe2NvbnN0IHI9ZS5iYm94WzNdLWUuYmJveFsxXTtyPjAmJih0WzNdKj1yKkQuZm9udE1hdHJpeFszXSl9cmV0dXJuIFV0aWwudHJhbnNmb3JtKEQuY3RtLFV0aWwudHJhbnNmb3JtKEQudGV4dE1hdHJpeCx0KSl9ZnVuY3Rpb24gZW5zdXJlVGV4dENvbnRlbnRJdGVtKCl7aWYoeS5pbml0aWFsaXplZClyZXR1cm4geTtjb25zdHtmb250OmUsbG9hZGVkTmFtZTp0fT1EO2lmKCFvLmhhcyh0KSl7by5hZGQodCk7Yi5zdHlsZXNbdF09e2ZvbnRGYW1pbHk6ZS5mYWxsYmFja05hbWUsYXNjZW50OmUuYXNjZW50LGRlc2NlbnQ6ZS5kZXNjZW50LHZlcnRpY2FsOmUudmVydGljYWx9O2lmKFMub3B0aW9ucy5mb250RXh0cmFQcm9wZXJ0aWVzJiZlLnN5c3RlbUZvbnRJbmZvKXtjb25zdCByPWIuc3R5bGVzW3RdO3IuZm9udFN1YnN0aXR1dGlvbj1lLnN5c3RlbUZvbnRJbmZvLmNzcztyLmZvbnRTdWJzdGl0dXRpb25Mb2FkZWROYW1lPWUuc3lzdGVtRm9udEluZm8ubG9hZGVkTmFtZX19eS5mb250TmFtZT10O2NvbnN0IHI9eS50cmFuc2Zvcm09Z2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKTtpZihlLnZlcnRpY2FsKXt5LndpZHRoPXkudG90YWxXaWR0aD1NYXRoLmh5cG90KHJbMF0sclsxXSk7eS5oZWlnaHQ9eS50b3RhbEhlaWdodD0wO3kudmVydGljYWw9ITB9ZWxzZXt5LndpZHRoPXkudG90YWxXaWR0aD0wO3kuaGVpZ2h0PXkudG90YWxIZWlnaHQ9TWF0aC5oeXBvdChyWzJdLHJbM10pO3kudmVydGljYWw9ITF9Y29uc3QgYT1NYXRoLmh5cG90KEQudGV4dExpbmVNYXRyaXhbMF0sRC50ZXh0TGluZU1hdHJpeFsxXSksbj1NYXRoLmh5cG90KEQuY3RtWzBdLEQuY3RtWzFdKTt5LnRleHRBZHZhbmNlU2NhbGU9biphO2NvbnN0e2ZvbnRTaXplOml9PUQ7eS50cmFja2luZ1NwYWNlTWluPS4xMDIqaTt5Lm5vdEFTcGFjZT0uMDMqaTt5Lm5lZ2F0aXZlU3BhY2VNYXg9LS4yKmk7eS5zcGFjZUluRmxvd01pbj0uMTAyKmk7eS5zcGFjZUluRmxvd01heD0uNippO3kuaGFzRU9MPSExO3kuaW5pdGlhbGl6ZWQ9ITA7cmV0dXJuIHl9ZnVuY3Rpb24gdXBkYXRlQWR2YW5jZVNjYWxlKCl7aWYoIXkuaW5pdGlhbGl6ZWQpcmV0dXJuO2NvbnN0IGU9TWF0aC5oeXBvdChELnRleHRMaW5lTWF0cml4WzBdLEQudGV4dExpbmVNYXRyaXhbMV0pLHQ9TWF0aC5oeXBvdChELmN0bVswXSxELmN0bVsxXSkqZTtpZih0IT09eS50ZXh0QWR2YW5jZVNjYWxlKXtpZih5LnZlcnRpY2FsKXt5LnRvdGFsSGVpZ2h0Kz15LmhlaWdodCp5LnRleHRBZHZhbmNlU2NhbGU7eS5oZWlnaHQ9MH1lbHNle3kudG90YWxXaWR0aCs9eS53aWR0aCp5LnRleHRBZHZhbmNlU2NhbGU7eS53aWR0aD0wfXkudGV4dEFkdmFuY2VTY2FsZT10fX1mdW5jdGlvbiBydW5CaWRpVHJhbnNmb3JtKGUpe2xldCB0PWUuc3RyLmpvaW4oIiIpO3V8fCh0PWZ1bmN0aW9uIG5vcm1hbGl6ZVVuaWNvZGUoZSl7aWYoIWFyKXthcj0vKFtcdTAwYTBcdTAwYjVcdTAzN2VcdTBlYjNcdTIwMDAtXHUyMDBhXHUyMDJmXHUyMTI2XHVmYjAwLVx1ZmIwNFx1ZmIwNlx1ZmIyMC1cdWZiMzZcdWZiMzgtXHVmYjNjXHVmYjNlXHVmYjQwLVx1ZmI0MVx1ZmI0My1cdWZiNDRcdWZiNDYtXHVmYmExXHVmYmE0LVx1ZmJhOVx1ZmJhZS1cdWZiYjFcdWZiZDMtXHVmYmRjXHVmYmRlLVx1ZmJlN1x1ZmJlYS1cdWZiZjhcdWZiZmMtXHVmYmZkXHVmYzAwLVx1ZmM1ZFx1ZmM2NC1cdWZjZjFcdWZjZjUtXHVmZDNkXHVmZDg4XHVmZGY0XHVmZGZhLVx1ZmRmYlx1ZmU3MVx1ZmU3N1x1ZmU3OVx1ZmU3Ylx1ZmU3ZF0rKXwoXHVmYjA1KykvZ3U7bnI9bmV3IE1hcChbWyLvrIUiLCLFv3QiXV0pfXJldHVybiBlLnJlcGxhY2VBbGwoYXIsKGUsdCxyKT0+dD90Lm5vcm1hbGl6ZSgiTkZLQyIpOm5yLmdldChyKSl9KHQpKTtjb25zdCByPWJpZGkodCwtMSxlLnZlcnRpY2FsKTtyZXR1cm57c3RyOnIuc3RyLGRpcjpyLmRpcix3aWR0aDpNYXRoLmFicyhlLnRvdGFsV2lkdGgpLGhlaWdodDpNYXRoLmFicyhlLnRvdGFsSGVpZ2h0KSx0cmFuc2Zvcm06ZS50cmFuc2Zvcm0sZm9udE5hbWU6ZS5mb250TmFtZSxoYXNFT0w6ZS5oYXNFT0x9fWFzeW5jIGZ1bmN0aW9uIGhhbmRsZVNldEZvbnQoZSxuKXtjb25zdCBpPWF3YWl0IFMubG9hZEZvbnQoZSxuLHIsdCk7RC5sb2FkZWROYW1lPWkubG9hZGVkTmFtZTtELmZvbnQ9aS5mb250O0QuZm9udE1hdHJpeD1pLmZvbnQuZm9udE1hdHJpeHx8YX1mdW5jdGlvbiBhcHBseUludmVyc2VSb3RhdGlvbihlLHQscil7Y29uc3QgYT1NYXRoLmh5cG90KHJbMF0sclsxXSk7cmV0dXJuWyhyWzBdKmUrclsxXSp0KS9hLChyWzJdKmUrclszXSp0KS9hXX1mdW5jdGlvbiBjb21wYXJlV2l0aExhc3RQb3NpdGlvbihlKXtjb25zdCB0PWdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCk7bGV0IHI9dFs0XSxhPXRbNV07aWYoRC5mb250Py52ZXJ0aWNhbCl7aWYocjxjWzBdfHxyPmNbMl18fGErZTxjWzFdfHxhPmNbM10pcmV0dXJuITF9ZWxzZSBpZihyK2U8Y1swXXx8cj5jWzJdfHxhPGNbMV18fGE+Y1szXSlyZXR1cm4hMTtpZighRC5mb250fHwheS5wcmV2VHJhbnNmb3JtKXJldHVybiEwO2xldCBuPXkucHJldlRyYW5zZm9ybVs0XSxpPXkucHJldlRyYW5zZm9ybVs1XTtpZihuPT09ciYmaT09PWEpcmV0dXJuITA7bGV0IHM9LTE7dFswXSYmMD09PXRbMV0mJjA9PT10WzJdP3M9dFswXT4wPzA6MTgwOnRbMV0mJjA9PT10WzBdJiYwPT09dFszXSYmKHM9dFsxXT4wPzkwOjI3MCk7c3dpdGNoKHMpe2Nhc2UgMDpicmVhaztjYXNlIDkwOltyLGFdPVthLHJdO1tuLGldPVtpLG5dO2JyZWFrO2Nhc2UgMTgwOltyLGEsbixpXT1bLXIsLWEsLW4sLWldO2JyZWFrO2Nhc2UgMjcwOltyLGFdPVstYSwtcl07W24saV09Wy1pLC1uXTticmVhaztkZWZhdWx0OltyLGFdPWFwcGx5SW52ZXJzZVJvdGF0aW9uKHIsYSx0KTtbbixpXT1hcHBseUludmVyc2VSb3RhdGlvbihuLGkseS5wcmV2VHJhbnNmb3JtKX1pZihELmZvbnQudmVydGljYWwpe2NvbnN0IGU9KGktYSkveS50ZXh0QWR2YW5jZVNjYWxlLHQ9ci1uLHM9TWF0aC5zaWduKHkuaGVpZ2h0KTtpZihlPHMqeS5uZWdhdGl2ZVNwYWNlTWF4KXtpZihNYXRoLmFicyh0KT4uNSp5LndpZHRoKXthcHBlbmRFT0woKTtyZXR1cm4hMH1yZXNldExhc3RDaGFycygpO2ZsdXNoVGV4dENvbnRlbnRJdGVtKCk7cmV0dXJuITB9aWYoTWF0aC5hYnModCk+eS53aWR0aCl7YXBwZW5kRU9MKCk7cmV0dXJuITB9ZTw9cyp5Lm5vdEFTcGFjZSYmcmVzZXRMYXN0Q2hhcnMoKTtpZihlPD1zKnkudHJhY2tpbmdTcGFjZU1pbilpZihzaG91bGRBZGRXaGl0ZXBzYWNlKCkpe3Jlc2V0TGFzdENoYXJzKCk7Zmx1c2hUZXh0Q29udGVudEl0ZW0oKTtwdXNoV2hpdGVzcGFjZSh7aGVpZ2h0Ok1hdGguYWJzKGUpfSl9ZWxzZSB5LmhlaWdodCs9ZTtlbHNlIGlmKCFhZGRGYWtlU3BhY2VzKGUseS5wcmV2VHJhbnNmb3JtLHMpKWlmKDA9PT15LnN0ci5sZW5ndGgpe3Jlc2V0TGFzdENoYXJzKCk7cHVzaFdoaXRlc3BhY2Uoe2hlaWdodDpNYXRoLmFicyhlKX0pfWVsc2UgeS5oZWlnaHQrPWU7TWF0aC5hYnModCk+LjI1Knkud2lkdGgmJmZsdXNoVGV4dENvbnRlbnRJdGVtKCk7cmV0dXJuITB9Y29uc3Qgbz0oci1uKS95LnRleHRBZHZhbmNlU2NhbGUsbD1hLWksaD1NYXRoLnNpZ24oeS53aWR0aCk7aWYobzxoKnkubmVnYXRpdmVTcGFjZU1heCl7aWYoTWF0aC5hYnMobCk+LjUqeS5oZWlnaHQpe2FwcGVuZEVPTCgpO3JldHVybiEwfXJlc2V0TGFzdENoYXJzKCk7Zmx1c2hUZXh0Q29udGVudEl0ZW0oKTtyZXR1cm4hMH1pZihNYXRoLmFicyhsKT55LmhlaWdodCl7YXBwZW5kRU9MKCk7cmV0dXJuITB9bzw9aCp5Lm5vdEFTcGFjZSYmcmVzZXRMYXN0Q2hhcnMoKTtpZihvPD1oKnkudHJhY2tpbmdTcGFjZU1pbilpZihzaG91bGRBZGRXaGl0ZXBzYWNlKCkpe3Jlc2V0TGFzdENoYXJzKCk7Zmx1c2hUZXh0Q29udGVudEl0ZW0oKTtwdXNoV2hpdGVzcGFjZSh7d2lkdGg6TWF0aC5hYnMobyl9KX1lbHNlIHkud2lkdGgrPW87ZWxzZSBpZighYWRkRmFrZVNwYWNlcyhvLHkucHJldlRyYW5zZm9ybSxoKSlpZigwPT09eS5zdHIubGVuZ3RoKXtyZXNldExhc3RDaGFycygpO3B1c2hXaGl0ZXNwYWNlKHt3aWR0aDpNYXRoLmFicyhvKX0pfWVsc2UgeS53aWR0aCs9bztNYXRoLmFicyhsKT4uMjUqeS5oZWlnaHQmJmZsdXNoVGV4dENvbnRlbnRJdGVtKCk7cmV0dXJuITB9ZnVuY3Rpb24gYnVpbGRUZXh0Q29udGVudEl0ZW0oe2NoYXJzOmUsZXh0cmFTcGFjaW5nOnR9KXtjb25zdCByPUQuZm9udDtpZighZSl7Y29uc3QgZT1ELmNoYXJTcGFjaW5nK3Q7ZSYmKHIudmVydGljYWw/RC50cmFuc2xhdGVUZXh0TWF0cml4KDAsLWUpOkQudHJhbnNsYXRlVGV4dE1hdHJpeChlKkQudGV4dEhTY2FsZSwwKSk7ZCYmY29tcGFyZVdpdGhMYXN0UG9zaXRpb24oMCk7cmV0dXJufWNvbnN0IGE9ci5jaGFyc1RvR2x5cGhzKGUpLG49RC5mb250TWF0cml4WzBdKkQuZm9udFNpemU7Zm9yKGxldCBlPTAsaT1hLmxlbmd0aDtlPGk7ZSsrKXtjb25zdCBzPWFbZV0se2NhdGVnb3J5Om8sb3JpZ2luYWxDaGFyQ29kZTpjfT1zO2lmKG8uaXNJbnZpc2libGVGb3JtYXRNYXJrKWNvbnRpbnVlO2xldCBsPUQuY2hhclNwYWNpbmcrKGUrMT09PWk/dDowKSxoPXMud2lkdGg7ci52ZXJ0aWNhbCYmKGg9cy52bWV0cmljP3Mudm1ldHJpY1swXTotaCk7bGV0IHU9aCpuOzMyPT09YyYmKGwrPUQud29yZFNwYWNpbmcpO2lmKCFkJiZvLmlzV2hpdGVzcGFjZSl7aWYoci52ZXJ0aWNhbCl7bCs9LXU7RC50cmFuc2xhdGVUZXh0TWF0cml4KDAsLWwpfWVsc2V7bCs9dTtELnRyYW5zbGF0ZVRleHRNYXRyaXgobCpELnRleHRIU2NhbGUsMCl9c2F2ZUxhc3RDaGFyKCIgIik7Y29udGludWV9aWYoIW8uaXNaZXJvV2lkdGhEaWFjcml0aWMmJiFjb21wYXJlV2l0aExhc3RQb3NpdGlvbih1KSl7ci52ZXJ0aWNhbD9ELnRyYW5zbGF0ZVRleHRNYXRyaXgoMCx1KTpELnRyYW5zbGF0ZVRleHRNYXRyaXgodSpELnRleHRIU2NhbGUsMCk7Y29udGludWV9Y29uc3QgZj1lbnN1cmVUZXh0Q29udGVudEl0ZW0oKTtvLmlzWmVyb1dpZHRoRGlhY3JpdGljJiYodT0wKTtpZihyLnZlcnRpY2FsKXtnPy5hZGRHbHlwaChnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpLDAsdSxzLnVuaWNvZGUpO0QudHJhbnNsYXRlVGV4dE1hdHJpeCgwLHUpO3U9TWF0aC5hYnModSk7Zi5oZWlnaHQrPXV9ZWxzZXt1Kj1ELnRleHRIU2NhbGU7Zz8uYWRkR2x5cGgoZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSx1LDAscy51bmljb2RlKTtELnRyYW5zbGF0ZVRleHRNYXRyaXgodSwwKTtmLndpZHRoKz11fXUmJihmLnByZXZUcmFuc2Zvcm09Z2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSk7Y29uc3QgcD1zLnVuaWNvZGU7aWYoc2F2ZUxhc3RDaGFyKHApKXtmLnN0ci5wdXNoKCIgIik7Zz8uYWRkRXh0cmFDaGFyKCIgIil9Z3x8Zi5zdHIucHVzaChwKTtsJiYoci52ZXJ0aWNhbD9ELnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwtbCk6RC50cmFuc2xhdGVUZXh0TWF0cml4KGwqRC50ZXh0SFNjYWxlLDApKX19ZnVuY3Rpb24gYXBwZW5kRU9MKCl7Zz8uYWRkRXh0cmFDaGFyKCJcbiIpO3Jlc2V0TGFzdENoYXJzKCk7aWYoeS5pbml0aWFsaXplZCl7eS5oYXNFT0w9ITA7Zmx1c2hUZXh0Q29udGVudEl0ZW0oKX1lbHNlIGIuaXRlbXMucHVzaCh7c3RyOiIiLGRpcjoibHRyIix3aWR0aDowLGhlaWdodDowLHRyYW5zZm9ybTpnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpLGZvbnROYW1lOkQubG9hZGVkTmFtZSxoYXNFT0w6ITB9KX1mdW5jdGlvbiBhZGRGYWtlU3BhY2VzKGUsdCxyKXtpZihyKnkuc3BhY2VJbkZsb3dNaW48PWUmJmU8PXIqeS5zcGFjZUluRmxvd01heCl7aWYoeS5pbml0aWFsaXplZCl7cmVzZXRMYXN0Q2hhcnMoKTt5LnN0ci5wdXNoKCIgIik7Zz8uYWRkRXh0cmFDaGFyKCIgIil9cmV0dXJuITF9Y29uc3QgYT15LmZvbnROYW1lO2xldCBuPTA7aWYoeS52ZXJ0aWNhbCl7bj1lO2U9MH1mbHVzaFRleHRDb250ZW50SXRlbSgpO3Jlc2V0TGFzdENoYXJzKCk7cHVzaFdoaXRlc3BhY2Uoe3dpZHRoOk1hdGguYWJzKGUpLGhlaWdodDpNYXRoLmFicyhuKSx0cmFuc2Zvcm06dHx8Z2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSxmb250TmFtZTphfSk7cmV0dXJuITB9ZnVuY3Rpb24gZmx1c2hUZXh0Q29udGVudEl0ZW0oKXtpZih5LmluaXRpYWxpemVkJiZ5LnN0cil7eS52ZXJ0aWNhbD95LnRvdGFsSGVpZ2h0Kz15LmhlaWdodCp5LnRleHRBZHZhbmNlU2NhbGU6eS50b3RhbFdpZHRoKz15LndpZHRoKnkudGV4dEFkdmFuY2VTY2FsZTtiLml0ZW1zLnB1c2gocnVuQmlkaVRyYW5zZm9ybSh5KSk7eS5pbml0aWFsaXplZD0hMTt5LnN0ci5sZW5ndGg9MH19ZnVuY3Rpb24gZW5xdWV1ZUNodW5rKGU9ITEpe2NvbnN0IHQ9Yi5pdGVtcy5sZW5ndGg7aWYoMCE9PXQmJiEoZSYmdDwxMCkpe3M/LmVucXVldWUoYix0KTtiLml0ZW1zPVtdO2Iuc3R5bGVzPU9iamVjdC5jcmVhdGUobnVsbCl9fWNvbnN0IFI9bmV3IFRpbWVTbG90TWFuYWdlcjtyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gcHJvbWlzZUJvZHkoZSxhKXtjb25zdCBuZXh0PWZ1bmN0aW9uKHQpe2VucXVldWVDaHVuayghMCk7UHJvbWlzZS5hbGwoW3Qscz8ucmVhZHldKS50aGVuKGZ1bmN0aW9uKCl7dHJ5e3Byb21pc2VCb2R5KGUsYSl9Y2F0Y2goZSl7YShlKX19LGEpfTt0LmVuc3VyZU5vdFRlcm1pbmF0ZWQoKTtSLnJlc2V0KCk7Y29uc3QgZj17fTtsZXQgZyxwLHksdz1bXTtmb3IoOyEoZz1SLmNoZWNrKCkpOyl7dy5sZW5ndGg9MDtmLmFyZ3M9dztpZighTS5yZWFkKGYpKWJyZWFrO2NvbnN0IGU9RDtEPW4uc3RhdGU7Y29uc3QgYT1mLmZuO3c9Zi5hcmdzO3N3aXRjaCgwfGEpe2Nhc2UgemU6Y29uc3QgYT13WzBdLm5hbWUsZj13WzFdO2lmKEQuZm9udCYmYT09PUQuZm9udE5hbWUmJmY9PT1ELmZvbnRTaXplKWJyZWFrO2ZsdXNoVGV4dENvbnRlbnRJdGVtKCk7RC5mb250TmFtZT1hO0QuZm9udFNpemU9ZjtuZXh0KGhhbmRsZVNldEZvbnQoYSxudWxsKSk7cmV0dXJuO2Nhc2UgJGU6RC50ZXh0UmlzZT13WzBdO2JyZWFrO2Nhc2UgSGU6RC50ZXh0SFNjYWxlPXdbMF0vMTAwO2JyZWFrO2Nhc2UgV2U6RC5sZWFkaW5nPXdbMF07YnJlYWs7Y2FzZSBWZTpELnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KHdbMF0sd1sxXSk7RC50ZXh0TWF0cml4PUQudGV4dExpbmVNYXRyaXguc2xpY2UoKTticmVhaztjYXNlIEtlOkQubGVhZGluZz0td1sxXTtELnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KHdbMF0sd1sxXSk7RC50ZXh0TWF0cml4PUQudGV4dExpbmVNYXRyaXguc2xpY2UoKTticmVhaztjYXNlIFllOkQuY2FycmlhZ2VSZXR1cm4oKTticmVhaztjYXNlIEplOkQuc2V0VGV4dE1hdHJpeCh3WzBdLHdbMV0sd1syXSx3WzNdLHdbNF0sd1s1XSk7RC5zZXRUZXh0TGluZU1hdHJpeCh3WzBdLHdbMV0sd1syXSx3WzNdLHdbNF0sd1s1XSk7dXBkYXRlQWR2YW5jZVNjYWxlKCk7YnJlYWs7Y2FzZSBxZTpELmNoYXJTcGFjaW5nPXdbMF07YnJlYWs7Y2FzZSBYZTpELndvcmRTcGFjaW5nPXdbMF07YnJlYWs7Y2FzZSBqZTpELnRleHRNYXRyaXg9ZnIuc2xpY2UoKTtELnRleHRMaW5lTWF0cml4PWZyLnNsaWNlKCk7YnJlYWs7Y2FzZSBRZTppZighbi5zdGF0ZS5mb250KXtTLmVuc3VyZVN0YXRlRm9udChuLnN0YXRlKTtjb250aW51ZX1jb25zdCBnPShELmZvbnQudmVydGljYWw/MTotMSkqRC5mb250U2l6ZS8xZTMseD13WzBdO2ZvcihsZXQgZT0wLHQ9eC5sZW5ndGg7ZTx0O2UrKyl7Y29uc3QgdD14W2VdO2lmKCJzdHJpbmciPT10eXBlb2YgdClDLnB1c2godCk7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIHQmJjAhPT10KXtjb25zdCBlPUMuam9pbigiIik7Qy5sZW5ndGg9MDtidWlsZFRleHRDb250ZW50SXRlbSh7Y2hhcnM6ZSxleHRyYVNwYWNpbmc6dCpnfSl9fWlmKEMubGVuZ3RoPjApe2NvbnN0IGU9Qy5qb2luKCIiKTtDLmxlbmd0aD0wO2J1aWxkVGV4dENvbnRlbnRJdGVtKHtjaGFyczplLGV4dHJhU3BhY2luZzowfSl9YnJlYWs7Y2FzZSBaZTppZighbi5zdGF0ZS5mb250KXtTLmVuc3VyZVN0YXRlRm9udChuLnN0YXRlKTtjb250aW51ZX1idWlsZFRleHRDb250ZW50SXRlbSh7Y2hhcnM6d1swXSxleHRyYVNwYWNpbmc6MH0pO2JyZWFrO2Nhc2UgZXQ6aWYoIW4uc3RhdGUuZm9udCl7Uy5lbnN1cmVTdGF0ZUZvbnQobi5zdGF0ZSk7Y29udGludWV9RC5jYXJyaWFnZVJldHVybigpO2J1aWxkVGV4dENvbnRlbnRJdGVtKHtjaGFyczp3WzBdLGV4dHJhU3BhY2luZzowfSk7YnJlYWs7Y2FzZSB0dDppZighbi5zdGF0ZS5mb250KXtTLmVuc3VyZVN0YXRlRm9udChuLnN0YXRlKTtjb250aW51ZX1ELndvcmRTcGFjaW5nPXdbMF07RC5jaGFyU3BhY2luZz13WzFdO0QuY2FycmlhZ2VSZXR1cm4oKTtidWlsZFRleHRDb250ZW50SXRlbSh7Y2hhcnM6d1syXSxleHRyYVNwYWNpbmc6MH0pO2JyZWFrO2Nhc2UgU3Q6Zmx1c2hUZXh0Q29udGVudEl0ZW0oKTt2Pz89ci5nZXQoIlhPYmplY3QiKXx8RGljdC5lbXB0eTt5PXdbMF1pbnN0YW5jZW9mIE5hbWU7cD13WzBdLm5hbWU7aWYoeSYmVC5nZXRCeU5hbWUocCkpYnJlYWs7bmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbihlLGEpe2lmKCF5KXRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7bGV0IGY9di5nZXRSYXcocCk7aWYoZiBpbnN0YW5jZW9mIFJlZil7aWYoVC5nZXRCeVJlZihmKSl7ZSgpO3JldHVybn1pZihTLmdsb2JhbEltYWdlQ2FjaGUuZ2V0RGF0YShmLFMucGFnZUluZGV4KSl7ZSgpO3JldHVybn1mPWsuZmV0Y2goZil9aWYoIShmIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBiZSBhIHN0cmVhbSIpO2NvbnN0e2RpY3Q6Z309ZixiPWcuZ2V0KCJTdWJ0eXBlIik7aWYoIShiIGluc3RhbmNlb2YgTmFtZSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBoYXZlIGEgTmFtZSBzdWJ0eXBlIik7aWYoIkZvcm0iIT09Yi5uYW1lKXtULnNldChwLGcub2JqSWQsITApO2UoKTtyZXR1cm59Y29uc3Qgdz1uLnN0YXRlLmNsb25lKCkseD1uZXcgU3RhdGVNYW5hZ2VyKHcpLEM9bG9va3VwTWF0cml4KGcuZ2V0QXJyYXkoIk1hdHJpeCIpLG51bGwpO0MmJngudHJhbnNmb3JtKEMpO2NvbnN0IE89Zy5nZXQoIlJlc291cmNlcyIpO2VucXVldWVDaHVuaygpO2NvbnN0IE09e2VucXVldWVJbnZva2VkOiExLGVucXVldWUoZSx0KXt0aGlzLmVucXVldWVJbnZva2VkPSEwO3MuZW5xdWV1ZShlLHQpfSxnZXQgZGVzaXJlZFNpemUoKXtyZXR1cm4gcy5kZXNpcmVkU2l6ZT8/MH0sZ2V0IHJlYWR5KCl7cmV0dXJuIHMucmVhZHl9fTtTLmdldFRleHRDb250ZW50KHtzdHJlYW06Zix0YXNrOnQscmVzb3VyY2VzOk8gaW5zdGFuY2VvZiBEaWN0P086cixzdGF0ZU1hbmFnZXI6eCxpbmNsdWRlTWFya2VkQ29udGVudDppLHNpbms6cyYmTSxzZWVuU3R5bGVzOm8sdmlld0JveDpjLGxhbmc6bCxtYXJrZWRDb250ZW50RGF0YTpoLGRpc2FibGVOb3JtYWxpemF0aW9uOnUsa2VlcFdoaXRlU3BhY2U6ZCxwcmV2UmVmczptfSkudGhlbihmdW5jdGlvbigpe00uZW5xdWV1ZUludm9rZWR8fFQuc2V0KHAsZy5vYmpJZCwhMCk7ZSgpfSxhKX0pLmNhdGNoKGZ1bmN0aW9uKGUpe2lmKCEoZSBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSl7aWYoIVMub3B0aW9ucy5pZ25vcmVFcnJvcnMpdGhyb3cgZTt3YXJuKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIFhPYmplY3Q6ICIke2V9Ii5gKX19KSk7cmV0dXJuO2Nhc2UgYmU6eT13WzBdaW5zdGFuY2VvZiBOYW1lO3A9d1swXS5uYW1lO2lmKHkmJk8uZ2V0QnlOYW1lKHApKWJyZWFrO25leHQobmV3IFByb21pc2UoZnVuY3Rpb24oZSx0KXtpZigheSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkdTdGF0ZSBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7Y29uc3QgYT1yLmdldCgiRXh0R1N0YXRlIik7aWYoIShhIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJFeHRHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTtjb25zdCBuPWEuZ2V0KHApO2lmKCEobiBpbnN0YW5jZW9mIERpY3QpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiR1N0YXRlIHNob3VsZCBiZSBhIGRpY3Rpb25hcnkuIik7Y29uc3QgaT1uLmdldCgiRm9udCIpO2lmKGkpe2ZsdXNoVGV4dENvbnRlbnRJdGVtKCk7RC5mb250TmFtZT1udWxsO0QuZm9udFNpemU9aVsxXTtoYW5kbGVTZXRGb250KG51bGwsaVswXSkudGhlbihlLHQpfWVsc2V7Ty5zZXQocCxuLm9iaklkLCEwKTtlKCl9fSkuY2F0Y2goZnVuY3Rpb24oZSl7aWYoIShlIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pKXtpZighUy5vcHRpb25zLmlnbm9yZUVycm9ycyl0aHJvdyBlO3dhcm4oYGdldFRleHRDb250ZW50IC0gaWdub3JpbmcgRXh0R1N0YXRlOiAiJHtlfSIuYCl9fSkpO3JldHVybjtjYXNlIEN0OmZsdXNoVGV4dENvbnRlbnRJdGVtKCk7aWYoaSl7aC5sZXZlbCsrO2IuaXRlbXMucHVzaCh7dHlwZToiYmVnaW5NYXJrZWRDb250ZW50Iix0YWc6d1swXWluc3RhbmNlb2YgTmFtZT93WzBdLm5hbWU6bnVsbH0pfWJyZWFrO2Nhc2UgdnQ6Zmx1c2hUZXh0Q29udGVudEl0ZW0oKTtpZihpKXtoLmxldmVsKys7bGV0IGU9bnVsbDt3WzFdaW5zdGFuY2VvZiBEaWN0JiYoZT13WzFdLmdldCgiTUNJRCIpKTtiLml0ZW1zLnB1c2goe3R5cGU6ImJlZ2luTWFya2VkQ29udGVudFByb3BzIixpZDpOdW1iZXIuaXNJbnRlZ2VyKGUpP2Ake1MuaWRGYWN0b3J5LmdldFBhZ2VPYmpJZCgpfV9tYyR7ZX1gOm51bGwsdGFnOndbMF1pbnN0YW5jZW9mIE5hbWU/d1swXS5uYW1lOm51bGx9KX1icmVhaztjYXNlIEZ0OmZsdXNoVGV4dENvbnRlbnRJdGVtKCk7aWYoaSl7aWYoMD09PWgubGV2ZWwpYnJlYWs7aC5sZXZlbC0tO2IuaXRlbXMucHVzaCh7dHlwZToiZW5kTWFya2VkQ29udGVudCJ9KX1icmVhaztjYXNlIHdlOiFlfHxlLmZvbnQ9PT1ELmZvbnQmJmUuZm9udFNpemU9PT1ELmZvbnRTaXplJiZlLmZvbnROYW1lPT09RC5mb250TmFtZXx8Zmx1c2hUZXh0Q29udGVudEl0ZW0oKX1pZihiLml0ZW1zLmxlbmd0aD49KHM/LmRlc2lyZWRTaXplPz8xKSl7Zz0hMDticmVha319aWYoZyluZXh0KHhpKTtlbHNle2ZsdXNoVGV4dENvbnRlbnRJdGVtKCk7ZW5xdWV1ZUNodW5rKCk7ZSgpfX0pLmNhdGNoKGU9PntpZighKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikpe2lmKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IGU7d2FybihgZ2V0VGV4dENvbnRlbnQgLSBpZ25vcmluZyBlcnJvcnMgZHVyaW5nICIke3QubmFtZX0iIHRhc2s6ICIke2V9Ii5gKTtmbHVzaFRleHRDb250ZW50SXRlbSgpO2VucXVldWVDaHVuaygpfX0pfWFzeW5jIGV4dHJhY3REYXRhU3RydWN0dXJlcyhlLHQpe2NvbnN0IHI9dGhpcy54cmVmO2xldCBhO2NvbnN0IG49dGhpcy5yZWFkVG9Vbmljb2RlKHQudG9Vbmljb2RlKTtpZih0LmNvbXBvc2l0ZSl7Y29uc3Qgcj1lLmdldCgiQ0lEU3lzdGVtSW5mbyIpO3IgaW5zdGFuY2VvZiBEaWN0JiYodC5jaWRTeXN0ZW1JbmZvPXtyZWdpc3RyeTpzdHJpbmdUb1BERlN0cmluZyhyLmdldCgiUmVnaXN0cnkiKSksb3JkZXJpbmc6c3RyaW5nVG9QREZTdHJpbmcoci5nZXQoIk9yZGVyaW5nIikpLHN1cHBsZW1lbnQ6ci5nZXQoIlN1cHBsZW1lbnQiKX0pO3RyeXtjb25zdCB0PWUuZ2V0KCJDSURUb0dJRE1hcCIpO3QgaW5zdGFuY2VvZiBCYXNlU3RyZWFtJiYoYT10LmdldEJ5dGVzKCkpfWNhdGNoKGUpe2lmKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXRocm93IGU7d2FybihgZXh0cmFjdERhdGFTdHJ1Y3R1cmVzIC0gaWdub3JpbmcgQ0lEVG9HSURNYXAgZGF0YTogIiR7ZX0iLmApfX1jb25zdCBpPVtdO2xldCBzLG89bnVsbDtpZihlLmhhcygiRW5jb2RpbmciKSl7cz1lLmdldCgiRW5jb2RpbmciKTtpZihzIGluc3RhbmNlb2YgRGljdCl7bz1zLmdldCgiQmFzZUVuY29kaW5nIik7bz1vIGluc3RhbmNlb2YgTmFtZT9vLm5hbWU6bnVsbDtpZihzLmhhcygiRGlmZmVyZW5jZXMiKSl7Y29uc3QgZT1zLmdldCgiRGlmZmVyZW5jZXMiKTtsZXQgdD0wO2Zvcihjb25zdCBhIG9mIGUpe2NvbnN0IGU9ci5mZXRjaElmUmVmKGEpO2lmKCJudW1iZXIiPT10eXBlb2YgZSl0PWU7ZWxzZXtpZighKGUgaW5zdGFuY2VvZiBOYW1lKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZW50cnkgaW4gJ0RpZmZlcmVuY2VzJyBhcnJheTogJHtlfWApO2lbdCsrXT1lLm5hbWV9fX19ZWxzZSBpZihzIGluc3RhbmNlb2YgTmFtZSlvPXMubmFtZTtlbHNle2NvbnN0IGU9IkVuY29kaW5nIGlzIG5vdCBhIE5hbWUgbm9yIGEgRGljdCI7aWYoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGUpO3dhcm4oZSl9Ik1hY1JvbWFuRW5jb2RpbmciIT09byYmIk1hY0V4cGVydEVuY29kaW5nIiE9PW8mJiJXaW5BbnNpRW5jb2RpbmciIT09byYmKG89bnVsbCl9Y29uc3QgYz0hdC5maWxlfHx0LmlzSW50ZXJuYWxGb250LGw9cWEoKVt0Lm5hbWVdO28mJmMmJmwmJihvPW51bGwpO2lmKG8pdC5kZWZhdWx0RW5jb2Rpbmc9Z2V0RW5jb2Rpbmcobyk7ZWxzZXtsZXQgZT0hISh0LmZsYWdzJmthKTtjb25zdCByPSEhKHQuZmxhZ3MmQ2EpO2lmKCJUcnVlVHlwZSI9PT10LnR5cGUmJmUmJnImJjAhPT1pLmxlbmd0aCl7dC5mbGFncyY9fmthO2U9ITF9cz1oYTsiVHJ1ZVR5cGUiIT09dC50eXBlfHxyfHwocz11YSk7aWYoZXx8bCl7cz1sYTtjJiYoL1N5bWJvbC9pLnRlc3QodC5uYW1lKT9zPWRhOi9EaW5nYmF0cy9pLnRlc3QodC5uYW1lKT9zPWZhOi9XaW5nZGluZ3MvaS50ZXN0KHQubmFtZSkmJihzPXVhKSl9dC5kZWZhdWx0RW5jb2Rpbmc9c310LmRpZmZlcmVuY2VzPWk7dC5iYXNlRW5jb2RpbmdOYW1lPW87dC5oYXNFbmNvZGluZz0hIW98fGkubGVuZ3RoPjA7dC5kaWN0PWU7dC50b1VuaWNvZGU9YXdhaXQgbjtjb25zdCBoPWF3YWl0IHRoaXMuYnVpbGRUb1VuaWNvZGUodCk7dC50b1VuaWNvZGU9aDthJiYodC5jaWRUb0dpZE1hcD10aGlzLnJlYWRDaWRUb0dpZE1hcChhLGgpKTtyZXR1cm4gdH1fc2ltcGxlRm9udFRvVW5pY29kZShlLHQ9ITEpe2Fzc2VydCghZS5jb21wb3NpdGUsIk11c3QgYmUgYSBzaW1wbGUgZm9udC4iKTtjb25zdCByPVtdLGE9ZS5kZWZhdWx0RW5jb2Rpbmcuc2xpY2UoKSxuPWUuYmFzZUVuY29kaW5nTmFtZSxpPWUuZGlmZmVyZW5jZXM7Zm9yKGNvbnN0IGUgaW4gaSl7Y29uc3QgdD1pW2VdOyIubm90ZGVmIiE9PXQmJihhW2VdPXQpfWNvbnN0IHM9Z2EoKTtmb3IoY29uc3QgaSBpbiBhKXtsZXQgbz1hW2ldO2lmKCIiPT09byljb250aW51ZTtsZXQgYz1zW29dO2lmKHZvaWQgMCE9PWMpe3JbaV09U3RyaW5nLmZyb21DaGFyQ29kZShjKTtjb250aW51ZX1sZXQgbD0wO3N3aXRjaChvWzBdKXtjYXNlIkciOjM9PT1vLmxlbmd0aCYmKGw9cGFyc2VJbnQoby5zdWJzdHJpbmcoMSksMTYpKTticmVhaztjYXNlImciOjU9PT1vLmxlbmd0aCYmKGw9cGFyc2VJbnQoby5zdWJzdHJpbmcoMSksMTYpKTticmVhaztjYXNlIkMiOmNhc2UiYyI6aWYoby5sZW5ndGg+PTMmJm8ubGVuZ3RoPD00KXtjb25zdCByPW8uc3Vic3RyaW5nKDEpO2lmKHQpe2w9cGFyc2VJbnQociwxNik7YnJlYWt9bD0rcjtpZihOdW1iZXIuaXNOYU4obCkmJk51bWJlci5pc0ludGVnZXIocGFyc2VJbnQociwxNikpKXJldHVybiB0aGlzLl9zaW1wbGVGb250VG9Vbmljb2RlKGUsITApfWJyZWFrO2Nhc2UidSI6Yz1nZXRVbmljb2RlRm9yR2x5cGgobyxzKTstMSE9PWMmJihsPWMpO2JyZWFrO2RlZmF1bHQ6c3dpdGNoKG8pe2Nhc2UiZl9oIjpjYXNlImZfdCI6Y2FzZSJUX2giOnJbaV09by5yZXBsYWNlQWxsKCJfIiwiIik7Y29udGludWV9fWlmKGw+MCYmbDw9MTExNDExMSYmTnVtYmVyLmlzSW50ZWdlcihsKSl7aWYobiYmbD09PStpKXtjb25zdCBlPWdldEVuY29kaW5nKG4pO2lmKGUmJihvPWVbaV0pKXtyW2ldPVN0cmluZy5mcm9tQ2hhckNvZGUoc1tvXSk7Y29udGludWV9fXJbaV09U3RyaW5nLmZyb21Db2RlUG9pbnQobCl9fXJldHVybiByfWFzeW5jIGJ1aWxkVG9Vbmljb2RlKGUpe2UuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXA9ZS50b1VuaWNvZGU/Lmxlbmd0aD4wO2lmKGUuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXApeyFlLmNvbXBvc2l0ZSYmZS5oYXNFbmNvZGluZyYmKGUuZmFsbGJhY2tUb1VuaWNvZGU9dGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShlKSk7cmV0dXJuIGUudG9Vbmljb2RlfWlmKCFlLmNvbXBvc2l0ZSlyZXR1cm4gbmV3IFRvVW5pY29kZU1hcCh0aGlzLl9zaW1wbGVGb250VG9Vbmljb2RlKGUpKTtpZihlLmNvbXBvc2l0ZSYmKGUuY01hcC5idWlsdEluQ01hcCYmIShlLmNNYXAgaW5zdGFuY2VvZiBJZGVudGl0eUNNYXApfHwiQWRvYmUiPT09ZS5jaWRTeXN0ZW1JbmZvPy5yZWdpc3RyeSYmKCJHQjEiPT09ZS5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nfHwiQ05TMSI9PT1lLmNpZFN5c3RlbUluZm8ub3JkZXJpbmd8fCJKYXBhbjEiPT09ZS5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nfHwiS29yZWExIj09PWUuY2lkU3lzdGVtSW5mby5vcmRlcmluZykpKXtjb25zdHtyZWdpc3RyeTp0LG9yZGVyaW5nOnJ9PWUuY2lkU3lzdGVtSW5mbyxhPU5hbWUuZ2V0KGAke3R9LSR7cn0tVUNTMmApLG49YXdhaXQgQ01hcEZhY3RvcnkuY3JlYXRlKHtlbmNvZGluZzphLGZldGNoQnVpbHRJbkNNYXA6dGhpcy5fZmV0Y2hCdWlsdEluQ01hcEJvdW5kLHVzZUNNYXA6bnVsbH0pLGk9W10scz1bXTtlLmNNYXAuZm9yRWFjaChmdW5jdGlvbihlLHQpe2lmKHQ+NjU1MzUpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNYXggc2l6ZSBvZiBDSUQgaXMgNjUsNTM1Iik7Y29uc3Qgcj1uLmxvb2t1cCh0KTtpZihyKXtzLmxlbmd0aD0wO2ZvcihsZXQgZT0wLHQ9ci5sZW5ndGg7ZTx0O2UrPTIpcy5wdXNoKChyLmNoYXJDb2RlQXQoZSk8PDgpK3IuY2hhckNvZGVBdChlKzEpKTtpW2VdPVN0cmluZy5mcm9tQ2hhckNvZGUoLi4ucyl9fSk7cmV0dXJuIG5ldyBUb1VuaWNvZGVNYXAoaSl9cmV0dXJuIG5ldyBJZGVudGl0eVRvVW5pY29kZU1hcChlLmZpcnN0Q2hhcixlLmxhc3RDaGFyKX1hc3luYyByZWFkVG9Vbmljb2RlKGUpe2lmKCFlKXJldHVybiBudWxsO2lmKGUgaW5zdGFuY2VvZiBOYW1lKXtjb25zdCB0PWF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7ZW5jb2Rpbmc6ZSxmZXRjaEJ1aWx0SW5DTWFwOnRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCx1c2VDTWFwOm51bGx9KTtyZXR1cm4gdCBpbnN0YW5jZW9mIElkZW50aXR5Q01hcD9uZXcgSWRlbnRpdHlUb1VuaWNvZGVNYXAoMCw2NTUzNSk6bmV3IFRvVW5pY29kZU1hcCh0LmdldE1hcCgpKX1pZihlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSl0cnl7Y29uc3QgdD1hd2FpdCBDTWFwRmFjdG9yeS5jcmVhdGUoe2VuY29kaW5nOmUsZmV0Y2hCdWlsdEluQ01hcDp0aGlzLl9mZXRjaEJ1aWx0SW5DTWFwQm91bmQsdXNlQ01hcDpudWxsfSk7aWYodCBpbnN0YW5jZW9mIElkZW50aXR5Q01hcClyZXR1cm4gbmV3IElkZW50aXR5VG9Vbmljb2RlTWFwKDAsNjU1MzUpO2NvbnN0IHI9bmV3IEFycmF5KHQubGVuZ3RoKTt0LmZvckVhY2goZnVuY3Rpb24oZSx0KXtpZigibnVtYmVyIj09dHlwZW9mIHQpe3JbZV09U3RyaW5nLmZyb21Db2RlUG9pbnQodCk7cmV0dXJufXQubGVuZ3RoJTIhPTAmJih0PSJcMCIrdCk7Y29uc3QgYT1bXTtmb3IobGV0IGU9MDtlPHQubGVuZ3RoO2UrPTIpe2NvbnN0IHI9dC5jaGFyQ29kZUF0KGUpPDw4fHQuY2hhckNvZGVBdChlKzEpO2lmKDU1Mjk2IT0oNjM0ODgmcikpe2EucHVzaChyKTtjb250aW51ZX1lKz0yO2NvbnN0IG49dC5jaGFyQ29kZUF0KGUpPDw4fHQuY2hhckNvZGVBdChlKzEpO2EucHVzaCgoKDEwMjMmcik8PDEwKSsoMTAyMyZuKSs2NTUzNil9cltlXT1TdHJpbmcuZnJvbUNvZGVQb2ludCguLi5hKX0pO3JldHVybiBuZXcgVG9Vbmljb2RlTWFwKHIpfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbilyZXR1cm4gbnVsbDtpZih0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKXt3YXJuKGByZWFkVG9Vbmljb2RlIC0gaWdub3JpbmcgVG9Vbmljb2RlIGRhdGE6ICIke2V9Ii5gKTtyZXR1cm4gbnVsbH10aHJvdyBlfXJldHVybiBudWxsfXJlYWRDaWRUb0dpZE1hcChlLHQpe2NvbnN0IHI9W107Zm9yKGxldCBhPTAsbj1lLmxlbmd0aDthPG47YSsrKXtjb25zdCBuPWVbYSsrXTw8OHxlW2FdLGk9YT4+MTsoMCE9PW58fHQuaGFzKGkpKSYmKHJbaV09bil9cmV0dXJuIHJ9ZXh0cmFjdFdpZHRocyhlLHQscil7Y29uc3QgYT10aGlzLnhyZWY7bGV0IG49W10saT0wO2NvbnN0IHM9W107bGV0IG87aWYoci5jb21wb3NpdGUpe2NvbnN0IHQ9ZS5nZXQoIkRXIik7aT0ibnVtYmVyIj09dHlwZW9mIHQ/TWF0aC5jZWlsKHQpOjFlMztjb25zdCBjPWUuZ2V0KCJXIik7aWYoQXJyYXkuaXNBcnJheShjKSlmb3IobGV0IGU9MCx0PWMubGVuZ3RoO2U8dDtlKyspe2xldCB0PWEuZmV0Y2hJZlJlZihjW2UrK10pO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHQpKWJyZWFrO2NvbnN0IHI9YS5mZXRjaElmUmVmKGNbZV0pO2lmKEFycmF5LmlzQXJyYXkocikpZm9yKGNvbnN0IGUgb2Ygcil7Y29uc3Qgcj1hLmZldGNoSWZSZWYoZSk7Im51bWJlciI9PXR5cGVvZiByJiYoblt0XT1yKTt0Kyt9ZWxzZXtpZighTnVtYmVyLmlzSW50ZWdlcihyKSlicmVhazt7Y29uc3QgaT1hLmZldGNoSWZSZWYoY1srK2VdKTtpZigibnVtYmVyIiE9dHlwZW9mIGkpY29udGludWU7Zm9yKGxldCBlPXQ7ZTw9cjtlKyspbltlXT1pfX19aWYoci52ZXJ0aWNhbCl7Y29uc3QgdD1lLmdldEFycmF5KCJEVzIiKTtsZXQgcj1pc051bWJlckFycmF5KHQsMik/dDpbODgwLC0xZTNdO289W3JbMV0sLjUqaSxyWzBdXTtyPWUuZ2V0KCJXMiIpO2lmKEFycmF5LmlzQXJyYXkocikpZm9yKGxldCBlPTAsdD1yLmxlbmd0aDtlPHQ7ZSsrKXtsZXQgdD1hLmZldGNoSWZSZWYocltlKytdKTtpZighTnVtYmVyLmlzSW50ZWdlcih0KSlicmVhaztjb25zdCBuPWEuZmV0Y2hJZlJlZihyW2VdKTtpZihBcnJheS5pc0FycmF5KG4pKWZvcihsZXQgZT0wLHI9bi5sZW5ndGg7ZTxyO2UrKyl7Y29uc3Qgcj1bYS5mZXRjaElmUmVmKG5bZSsrXSksYS5mZXRjaElmUmVmKG5bZSsrXSksYS5mZXRjaElmUmVmKG5bZV0pXTtpc051bWJlckFycmF5KHIsbnVsbCkmJihzW3RdPXIpO3QrK31lbHNle2lmKCFOdW1iZXIuaXNJbnRlZ2VyKG4pKWJyZWFrO3tjb25zdCBpPVthLmZldGNoSWZSZWYoclsrK2VdKSxhLmZldGNoSWZSZWYoclsrK2VdKSxhLmZldGNoSWZSZWYoclsrK2VdKV07aWYoIWlzTnVtYmVyQXJyYXkoaSxudWxsKSljb250aW51ZTtmb3IobGV0IGU9dDtlPD1uO2UrKylzW2VdPWl9fX19fWVsc2V7Y29uc3Qgcz1lLmdldCgiV2lkdGhzIik7aWYoQXJyYXkuaXNBcnJheShzKSl7bGV0IGU9ci5maXJzdENoYXI7Zm9yKGNvbnN0IHQgb2Ygcyl7Y29uc3Qgcj1hLmZldGNoSWZSZWYodCk7Im51bWJlciI9PXR5cGVvZiByJiYobltlXT1yKTtlKyt9Y29uc3Qgbz10LmdldCgiTWlzc2luZ1dpZHRoIik7aT0ibnVtYmVyIj09dHlwZW9mIG8/bzowfWVsc2V7Y29uc3QgdD1lLmdldCgiQmFzZUZvbnQiKTtpZih0IGluc3RhbmNlb2YgTmFtZSl7Y29uc3QgZT10aGlzLmdldEJhc2VGb250TWV0cmljcyh0Lm5hbWUpO249dGhpcy5idWlsZENoYXJDb2RlVG9XaWR0aChlLndpZHRocyxyKTtpPWUuZGVmYXVsdFdpZHRofX19bGV0IGM9ITAsbD1pO2Zvcihjb25zdCBlIGluIG4pe2NvbnN0IHQ9bltlXTtpZih0KWlmKGwpe2lmKGwhPT10KXtjPSExO2JyZWFrfX1lbHNlIGw9dH1jP3IuZmxhZ3N8PVNhOnIuZmxhZ3MmPX5TYTtyLmRlZmF1bHRXaWR0aD1pO3Iud2lkdGhzPW47ci5kZWZhdWx0Vk1ldHJpY3M9bztyLnZtZXRyaWNzPXN9aXNTZXJpZkZvbnQoZSl7Y29uc3QgdD1lLnNwbGl0KCItIiwxKVswXTtyZXR1cm4gdCBpbiBVYSgpfHwvc2VyaWYvZ2kudGVzdCh0KX1nZXRCYXNlRm9udE1ldHJpY3MoZSl7bGV0IHQ9MCxyPU9iamVjdC5jcmVhdGUobnVsbCksYT0hMTtsZXQgbj1fYSgpW2VdfHxlO2NvbnN0IGk9emEoKTtuIGluIGl8fChuPXRoaXMuaXNTZXJpZkZvbnQoZSk/IlRpbWVzLVJvbWFuIjoiSGVsdmV0aWNhIik7Y29uc3Qgcz1pW25dO2lmKCJudW1iZXIiPT10eXBlb2Ygcyl7dD1zO2E9ITB9ZWxzZSByPXMoKTtyZXR1cm57ZGVmYXVsdFdpZHRoOnQsbW9ub3NwYWNlOmEsd2lkdGhzOnJ9fWJ1aWxkQ2hhckNvZGVUb1dpZHRoKGUsdCl7Y29uc3Qgcj1PYmplY3QuY3JlYXRlKG51bGwpLGE9dC5kaWZmZXJlbmNlcyxuPXQuZGVmYXVsdEVuY29kaW5nO2ZvcihsZXQgdD0wO3Q8MjU2O3QrKyl0IGluIGEmJmVbYVt0XV0/clt0XT1lW2FbdF1dOnQgaW4gbiYmZVtuW3RdXSYmKHJbdF09ZVtuW3RdXSk7cmV0dXJuIHJ9cHJlRXZhbHVhdGVGb250KGUpe2NvbnN0IHQ9ZTtsZXQgcj1lLmdldCgiU3VidHlwZSIpO2lmKCEociBpbnN0YW5jZW9mIE5hbWUpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiaW52YWxpZCBmb250IFN1YnR5cGUiKTtsZXQgYSxuPSExO2lmKCJUeXBlMCI9PT1yLm5hbWUpe2NvbnN0IHQ9ZS5nZXQoIkRlc2NlbmRhbnRGb250cyIpO2lmKCF0KXRocm93IG5ldyBGb3JtYXRFcnJvcigiRGVzY2VuZGFudCBmb250cyBhcmUgbm90IHNwZWNpZmllZCIpO2lmKCEoKGU9QXJyYXkuaXNBcnJheSh0KT90aGlzLnhyZWYuZmV0Y2hJZlJlZih0WzBdKTp0KWluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJEZXNjZW5kYW50IGZvbnQgaXMgbm90IGEgZGljdGlvbmFyeS4iKTtyPWUuZ2V0KCJTdWJ0eXBlIik7aWYoIShyIGluc3RhbmNlb2YgTmFtZSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGZvbnQgU3VidHlwZSIpO249ITB9bGV0IGk9ZS5nZXQoIkZpcnN0Q2hhciIpO051bWJlci5pc0ludGVnZXIoaSl8fChpPTApO2xldCBzPWUuZ2V0KCJMYXN0Q2hhciIpO051bWJlci5pc0ludGVnZXIocyl8fChzPW4/NjU1MzU6MjU1KTtjb25zdCBvPWUuZ2V0KCJGb250RGVzY3JpcHRvciIpLGM9ZS5nZXQoIlRvVW5pY29kZSIpfHx0LmdldCgiVG9Vbmljb2RlIik7aWYobyl7YT1uZXcgTXVybXVySGFzaDNfNjQ7Y29uc3Qgcj10LmdldFJhdygiRW5jb2RpbmciKTtpZihyIGluc3RhbmNlb2YgTmFtZSlhLnVwZGF0ZShyLm5hbWUpO2Vsc2UgaWYociBpbnN0YW5jZW9mIFJlZilhLnVwZGF0ZShyLnRvU3RyaW5nKCkpO2Vsc2UgaWYociBpbnN0YW5jZW9mIERpY3QpZm9yKGNvbnN0IGUgb2Ygci5nZXRSYXdWYWx1ZXMoKSlpZihlIGluc3RhbmNlb2YgTmFtZSlhLnVwZGF0ZShlLm5hbWUpO2Vsc2UgaWYoZSBpbnN0YW5jZW9mIFJlZilhLnVwZGF0ZShlLnRvU3RyaW5nKCkpO2Vsc2UgaWYoQXJyYXkuaXNBcnJheShlKSl7Y29uc3QgdD1lLmxlbmd0aCxyPW5ldyBBcnJheSh0KTtmb3IobGV0IGE9MDthPHQ7YSsrKXtjb25zdCB0PWVbYV07dCBpbnN0YW5jZW9mIE5hbWU/clthXT10Lm5hbWU6KCJudW1iZXIiPT10eXBlb2YgdHx8dCBpbnN0YW5jZW9mIFJlZikmJihyW2FdPXQudG9TdHJpbmcoKSl9YS51cGRhdGUoci5qb2luKCkpfWEudXBkYXRlKGAke2l9LSR7c31gKTtpZihjIGluc3RhbmNlb2YgQmFzZVN0cmVhbSl7Y29uc3QgZT1jLnN0cnx8Yyx0PWUuYnVmZmVyP25ldyBVaW50OEFycmF5KGUuYnVmZmVyLmJ1ZmZlciwwLGUuYnVmZmVyTGVuZ3RoKTpuZXcgVWludDhBcnJheShlLmJ5dGVzLmJ1ZmZlcixlLnN0YXJ0LGUuZW5kLWUuc3RhcnQpO2EudXBkYXRlKHQpfWVsc2UgYyBpbnN0YW5jZW9mIE5hbWUmJmEudXBkYXRlKGMubmFtZSk7Y29uc3Qgbz1lLmdldCgiV2lkdGhzIil8fHQuZ2V0KCJXaWR0aHMiKTtpZihBcnJheS5pc0FycmF5KG8pKXtjb25zdCBlPVtdO2Zvcihjb25zdCB0IG9mIG8pKCJudW1iZXIiPT10eXBlb2YgdHx8dCBpbnN0YW5jZW9mIFJlZikmJmUucHVzaCh0LnRvU3RyaW5nKCkpO2EudXBkYXRlKGUuam9pbigpKX1pZihuKXthLnVwZGF0ZSgiY29tcG9zaXRlRm9udCIpO2NvbnN0IHI9ZS5nZXQoIlciKXx8dC5nZXQoIlciKTtpZihBcnJheS5pc0FycmF5KHIpKXtjb25zdCBlPVtdO2Zvcihjb25zdCB0IG9mIHIpaWYoIm51bWJlciI9PXR5cGVvZiB0fHx0IGluc3RhbmNlb2YgUmVmKWUucHVzaCh0LnRvU3RyaW5nKCkpO2Vsc2UgaWYoQXJyYXkuaXNBcnJheSh0KSl7Y29uc3Qgcj1bXTtmb3IoY29uc3QgZSBvZiB0KSgibnVtYmVyIj09dHlwZW9mIGV8fGUgaW5zdGFuY2VvZiBSZWYpJiZyLnB1c2goZS50b1N0cmluZygpKTtlLnB1c2goYFske3Iuam9pbigpfV1gKX1hLnVwZGF0ZShlLmpvaW4oKSl9Y29uc3Qgbj1lLmdldFJhdygiQ0lEVG9HSURNYXAiKXx8dC5nZXRSYXcoIkNJRFRvR0lETWFwIik7biBpbnN0YW5jZW9mIE5hbWU/YS51cGRhdGUobi5uYW1lKTpuIGluc3RhbmNlb2YgUmVmP2EudXBkYXRlKG4udG9TdHJpbmcoKSk6biBpbnN0YW5jZW9mIEJhc2VTdHJlYW0mJmEudXBkYXRlKG4ucGVla0J5dGVzKCkpfX1yZXR1cm57ZGVzY3JpcHRvcjpvLGRpY3Q6ZSxiYXNlRGljdDp0LGNvbXBvc2l0ZTpuLHR5cGU6ci5uYW1lLGZpcnN0Q2hhcjppLGxhc3RDaGFyOnMsdG9Vbmljb2RlOmMsaGFzaDphP2EuaGV4ZGlnZXN0KCk6IiJ9fWFzeW5jIHRyYW5zbGF0ZUZvbnQoe2Rlc2NyaXB0b3I6ZSxkaWN0OnQsYmFzZURpY3Q6cixjb21wb3NpdGU6bix0eXBlOmksZmlyc3RDaGFyOnMsbGFzdENoYXI6byx0b1VuaWNvZGU6Yyxjc3NGb250SW5mbzpsfSl7Y29uc3QgaD0iVHlwZTMiPT09aTtpZighZSl7aWYoIWgpe2xldCBlPXQuZ2V0KCJCYXNlRm9udCIpO2lmKCEoZSBpbnN0YW5jZW9mIE5hbWUpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFzZSBmb250IGlzIG5vdCBzcGVjaWZpZWQiKTtlPWUubmFtZS5yZXBsYWNlQWxsKC9bLF9dL2csIi0iKTtjb25zdCBhPXRoaXMuZ2V0QmFzZUZvbnRNZXRyaWNzKGUpLG49ZS5zcGxpdCgiLSIsMSlbMF0sbD0odGhpcy5pc1NlcmlmRm9udChuKT9BYTowKXwoYS5tb25vc3BhY2U/U2E6MCl8KHFhKClbbl0/a2E6Q2EpLHU9e3R5cGU6aSxuYW1lOmUsbG9hZGVkTmFtZTpyLmxvYWRlZE5hbWUsc3lzdGVtRm9udEluZm86bnVsbCx3aWR0aHM6YS53aWR0aHMsZGVmYXVsdFdpZHRoOmEuZGVmYXVsdFdpZHRoLGlzU2ltdWxhdGVkRmxhZ3M6ITAsZmxhZ3M6bCxmaXJzdENoYXI6cyxsYXN0Q2hhcjpvLHRvVW5pY29kZTpjLHhIZWlnaHQ6MCxjYXBIZWlnaHQ6MCxpdGFsaWNBbmdsZTowLGlzVHlwZTNGb250Omh9LGQ9dC5nZXQoIldpZHRocyIpLGY9Z2V0U3RhbmRhcmRGb250TmFtZShlKTtsZXQgZz1udWxsO2lmKGYpe2c9YXdhaXQgdGhpcy5mZXRjaFN0YW5kYXJkRm9udERhdGEoZik7dS5pc0ludGVybmFsRm9udD0hIWd9IXUuaXNJbnRlcm5hbEZvbnQmJnRoaXMub3B0aW9ucy51c2VTeXN0ZW1Gb250cyYmKHUuc3lzdGVtRm9udEluZm89Z2V0Rm9udFN1YnN0aXR1dGlvbih0aGlzLnN5c3RlbUZvbnRDYWNoZSx0aGlzLmlkRmFjdG9yeSx0aGlzLm9wdGlvbnMuc3RhbmRhcmRGb250RGF0YVVybCxlLGYsaSkpO2NvbnN0IHA9YXdhaXQgdGhpcy5leHRyYWN0RGF0YVN0cnVjdHVyZXModCx1KTtpZihBcnJheS5pc0FycmF5KGQpKXtjb25zdCBlPVtdO2xldCB0PXM7Zm9yKGNvbnN0IHIgb2YgZCl7Y29uc3QgYT10aGlzLnhyZWYuZmV0Y2hJZlJlZihyKTsibnVtYmVyIj09dHlwZW9mIGEmJihlW3RdPWEpO3QrK31wLndpZHRocz1lfWVsc2UgcC53aWR0aHM9dGhpcy5idWlsZENoYXJDb2RlVG9XaWR0aChhLndpZHRocyxwKTtyZXR1cm4gbmV3IEZvbnQoZSxnLHAsdGhpcy5vcHRpb25zKX1lPURpY3QuZW1wdHl9bGV0IHU9ZS5nZXQoIkZvbnROYW1lIiksZD10LmdldCgiQmFzZUZvbnQiKTsic3RyaW5nIj09dHlwZW9mIHUmJih1PU5hbWUuZ2V0KHUpKTsic3RyaW5nIj09dHlwZW9mIGQmJihkPU5hbWUuZ2V0KGQpKTtjb25zdCBmPXU/Lm5hbWUsZz1kPy5uYW1lO2lmKGgpZnx8KHU9TmFtZS5nZXQoaSkpO2Vsc2UgaWYoZiE9PWcpe2luZm8oYFRoZSBGb250RGVzY3JpcHRvcidzIEZvbnROYW1lIGlzICIke2Z9IiBidXQgc2hvdWxkIGJlIHRoZSBzYW1lIGFzIHRoZSBGb250J3MgQmFzZUZvbnQgIiR7Z30iLmApO2YmJmcmJihnLnN0YXJ0c1dpdGgoZil8fCFpc0tub3duRm9udE5hbWUoZikmJmlzS25vd25Gb250TmFtZShnKSkmJih1PW51bGwpO3V8fD1kfWlmKCEodSBpbnN0YW5jZW9mIE5hbWUpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiaW52YWxpZCBmb250IG5hbWUiKTtsZXQgcCxtLGIseSx3O3RyeXtwPWUuZ2V0KCJGb250RmlsZSIsIkZvbnRGaWxlMiIsIkZvbnRGaWxlMyIpO2lmKHApe2lmKCEocCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pKXRocm93IG5ldyBGb3JtYXRFcnJvcigiRm9udEZpbGUgc2hvdWxkIGJlIGEgc3RyZWFtIik7aWYocC5pc0VtcHR5KXRocm93IG5ldyBGb3JtYXRFcnJvcigiRm9udEZpbGUgaXMgZW1wdHkiKX19Y2F0Y2goZSl7aWYoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpdGhyb3cgZTt3YXJuKGB0cmFuc2xhdGVGb250IC0gZmV0Y2hpbmcgIiR7dS5uYW1lfSIgZm9udCBmaWxlOiAiJHtlfSIuYCk7cD1udWxsfWxldCB4PSExLFM9bnVsbCxrPW51bGw7aWYocCl7aWYocC5kaWN0KXtjb25zdCBlPXAuZGljdC5nZXQoIlN1YnR5cGUiKTtlIGluc3RhbmNlb2YgTmFtZSYmKG09ZS5uYW1lKTtiPXAuZGljdC5nZXQoIkxlbmd0aDEiKTt5PXAuZGljdC5nZXQoIkxlbmd0aDIiKTt3PXAuZGljdC5nZXQoIkxlbmd0aDMiKX19ZWxzZSBpZihsKXtjb25zdCBlPWdldFhmYUZvbnROYW1lKHUubmFtZSk7aWYoZSl7bC5mb250RmFtaWx5PWAke2wuZm9udEZhbWlseX0tUGRmSlMtWEZBYDtsLm1ldHJpY3M9ZS5tZXRyaWNzfHxudWxsO1M9ZS5mYWN0b3JzfHxudWxsO3A9YXdhaXQgdGhpcy5mZXRjaFN0YW5kYXJkRm9udERhdGEoZS5uYW1lKTt4PSEhcDtyPXQ9Z2V0WGZhRm9udERpY3QodS5uYW1lKTtuPSEwfX1lbHNlIGlmKCFoKXtjb25zdCBlPWdldFN0YW5kYXJkRm9udE5hbWUodS5uYW1lKTtpZihlKXtwPWF3YWl0IHRoaXMuZmV0Y2hTdGFuZGFyZEZvbnREYXRhKGUpO3g9ISFwfSF4JiZ0aGlzLm9wdGlvbnMudXNlU3lzdGVtRm9udHMmJihrPWdldEZvbnRTdWJzdGl0dXRpb24odGhpcy5zeXN0ZW1Gb250Q2FjaGUsdGhpcy5pZEZhY3RvcnksdGhpcy5vcHRpb25zLnN0YW5kYXJkRm9udERhdGFVcmwsdS5uYW1lLGUsaSkpfWNvbnN0IEM9bG9va3VwTWF0cml4KHQuZ2V0QXJyYXkoIkZvbnRNYXRyaXgiKSxhKSx2PWxvb2t1cE5vcm1hbFJlY3QoZS5nZXRBcnJheSgiRm9udEJCb3giKXx8dC5nZXRBcnJheSgiRm9udEJCb3giKSxoP1swLDAsMCwwXTp2b2lkIDApO2xldCBUPWUuZ2V0KCJBc2NlbnQiKTsibnVtYmVyIiE9dHlwZW9mIFQmJihUPXZvaWQgMCk7bGV0IE89ZS5nZXQoIkRlc2NlbnQiKTsibnVtYmVyIiE9dHlwZW9mIE8mJihPPXZvaWQgMCk7bGV0IE09ZS5nZXQoIlhIZWlnaHQiKTsibnVtYmVyIiE9dHlwZW9mIE0mJihNPTApO2xldCBEPWUuZ2V0KCJDYXBIZWlnaHQiKTsibnVtYmVyIiE9dHlwZW9mIEQmJihEPTApO2xldCBSPWUuZ2V0KCJGbGFncyIpO051bWJlci5pc0ludGVnZXIoUil8fChSPTApO2xldCBFPWUuZ2V0KCJJdGFsaWNBbmdsZSIpOyJudW1iZXIiIT10eXBlb2YgRSYmKEU9MCk7Y29uc3QgTj17dHlwZTppLG5hbWU6dS5uYW1lLHN1YnR5cGU6bSxmaWxlOnAsbGVuZ3RoMTpiLGxlbmd0aDI6eSxsZW5ndGgzOncsaXNJbnRlcm5hbEZvbnQ6eCxsb2FkZWROYW1lOnIubG9hZGVkTmFtZSxjb21wb3NpdGU6bixmaXhlZFBpdGNoOiExLGZvbnRNYXRyaXg6QyxmaXJzdENoYXI6cyxsYXN0Q2hhcjpvLHRvVW5pY29kZTpjLGJib3g6dixhc2NlbnQ6VCxkZXNjZW50Ok8seEhlaWdodDpNLGNhcEhlaWdodDpELGZsYWdzOlIsaXRhbGljQW5nbGU6RSxpc1R5cGUzRm9udDpoLGNzc0ZvbnRJbmZvOmwsc2NhbGVGYWN0b3JzOlMsc3lzdGVtRm9udEluZm86a307aWYobil7Y29uc3QgZT1yLmdldCgiRW5jb2RpbmciKTtlIGluc3RhbmNlb2YgTmFtZSYmKE4uY2lkRW5jb2Rpbmc9ZS5uYW1lKTtjb25zdCB0PWF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7ZW5jb2Rpbmc6ZSxmZXRjaEJ1aWx0SW5DTWFwOnRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCx1c2VDTWFwOm51bGx9KTtOLmNNYXA9dDtOLnZlcnRpY2FsPU4uY01hcC52ZXJ0aWNhbH1jb25zdCBfPWF3YWl0IHRoaXMuZXh0cmFjdERhdGFTdHJ1Y3R1cmVzKHQsTik7dGhpcy5leHRyYWN0V2lkdGhzKHQsZSxfKTtyZXR1cm4gbmV3IEZvbnQodS5uYW1lLHAsXyx0aGlzLm9wdGlvbnMpfXN0YXRpYyBidWlsZEZvbnRQYXRocyhlLHQscixhKXtmdW5jdGlvbiBidWlsZFBhdGgodCl7Y29uc3Qgbj1gJHtlLmxvYWRlZE5hbWV9X3BhdGhfJHt0fWA7dHJ5e2lmKGUucmVuZGVyZXIuaGFzQnVpbHRQYXRoKHQpKXJldHVybjtyLnNlbmQoImNvbW1vbm9iaiIsW24sIkZvbnRQYXRoIixlLnJlbmRlcmVyLmdldFBhdGhKcyh0KV0pfWNhdGNoKGUpe2lmKGEuaWdub3JlRXJyb3JzKXt3YXJuKGBidWlsZEZvbnRQYXRocyAtIGlnbm9yaW5nICR7bn0gZ2x5cGg6ICIke2V9Ii5gKTtyZXR1cm59dGhyb3cgZX19Zm9yKGNvbnN0IGUgb2YgdCl7YnVpbGRQYXRoKGUuZm9udENoYXIpO2NvbnN0IHQ9ZS5hY2NlbnQ7dD8uZm9udENoYXImJmJ1aWxkUGF0aCh0LmZvbnRDaGFyKX19c3RhdGljIGdldCBmYWxsYmFja0ZvbnREaWN0KCl7Y29uc3QgZT1uZXcgRGljdDtlLnNldCgiQmFzZUZvbnQiLE5hbWUuZ2V0KCJIZWx2ZXRpY2EiKSk7ZS5zZXQoIlR5cGUiLE5hbWUuZ2V0KCJGYWxsYmFja1R5cGUiKSk7ZS5zZXQoIlN1YnR5cGUiLE5hbWUuZ2V0KCJGYWxsYmFja1R5cGUiKSk7ZS5zZXQoIkVuY29kaW5nIixOYW1lLmdldCgiV2luQW5zaUVuY29kaW5nIikpO3JldHVybiBzaGFkb3codGhpcywiZmFsbGJhY2tGb250RGljdCIsZSl9fWNsYXNzIFRyYW5zbGF0ZWRGb250eyNhZT0hMTsjbmU9bnVsbDtjb25zdHJ1Y3Rvcih7bG9hZGVkTmFtZTplLGZvbnQ6dCxkaWN0OnJ9KXt0aGlzLmxvYWRlZE5hbWU9ZTt0aGlzLmZvbnQ9dDt0aGlzLmRpY3Q9cjt0aGlzLnR5cGUzRGVwZW5kZW5jaWVzPXQuaXNUeXBlM0ZvbnQ/bmV3IFNldDpudWxsfXNlbmQoZSl7aWYodGhpcy4jYWUpcmV0dXJuO3RoaXMuI2FlPSEwO2NvbnN0IHQ9dGhpcy5mb250LmV4cG9ydERhdGEoKSxyPVtdO2lmKHQuZGF0YSl7dC5kYXRhLmNoYXJQcm9jT3BlcmF0b3JMaXN0JiYodC5jaGFyUHJvY09wZXJhdG9yTGlzdD10LmRhdGEuY2hhclByb2NPcGVyYXRvckxpc3QpO3QuZGF0YT1Gb250SW5mby53cml0ZSh0LmRhdGEpO3IucHVzaCh0LmRhdGEpfWUuc2VuZCgiY29tbW9ub2JqIixbdGhpcy5sb2FkZWROYW1lLCJGb250Iix0XSxyKX1mYWxsYmFjayhlLHQpe2lmKHRoaXMuZm9udC5kYXRhKXt0aGlzLmZvbnQuZGlzYWJsZUZvbnRGYWNlPSEwO1BhcnRpYWxFdmFsdWF0b3IuYnVpbGRGb250UGF0aHModGhpcy5mb250LHRoaXMuZm9udC5nbHlwaENhY2hlVmFsdWVzLGUsdCl9fWxvYWRUeXBlM0RhdGEoZSx0LHIpe2lmKHRoaXMuI25lKXJldHVybiB0aGlzLiNuZTtjb25zdHtmb250OmEsdHlwZTNEZXBlbmRlbmNpZXM6bn09dGhpczthc3NlcnQoYS5pc1R5cGUzRm9udCwiTXVzdCBiZSBhIFR5cGUzIGZvbnQuIik7Y29uc3QgaT1lLmNsb25lKHtpZ25vcmVFcnJvcnM6ITF9KSxzPW5ldyBSZWZTZXQoZS50eXBlM0ZvbnRSZWZzKTt0aGlzLmRpY3Qub2JqSWQmJiFzLmhhcyh0aGlzLmRpY3Qub2JqSWQpJiZzLnB1dCh0aGlzLmRpY3Qub2JqSWQpO2kudHlwZTNGb250UmVmcz1zO2xldCBvPVByb21pc2UucmVzb2x2ZSgpO2NvbnN0IGM9dGhpcy5kaWN0LmdldCgiQ2hhclByb2NzIiksbD10aGlzLmRpY3QuZ2V0KCJSZXNvdXJjZXMiKXx8dCxoPU9iamVjdC5jcmVhdGUobnVsbCksW3UsZCxmLGddPWEuYmJveCxwPWYtdSxtPWctZCxiPU1hdGguaHlwb3QocCxtKTtmb3IoY29uc3QgZSBvZiBjLmdldEtleXMoKSlvPW8udGhlbigoKT0+e2NvbnN0IHQ9Yy5nZXQoZSksYT1uZXcgT3BlcmF0b3JMaXN0O3JldHVybiBpLmdldE9wZXJhdG9yTGlzdCh7c3RyZWFtOnQsdGFzazpyLHJlc291cmNlczpsLG9wZXJhdG9yTGlzdDphfSkudGhlbigoKT0+e3N3aXRjaChhLmZuQXJyYXlbMF0pe2Nhc2UgbnQ6dGhpcy4jaWUoYSxiKTticmVhaztjYXNlIHJ0OmJ8fHRoaXMuI3NlKGEpfWhbZV09YS5nZXRJUigpO2Zvcihjb25zdCBlIG9mIGEuZGVwZW5kZW5jaWVzKW4uYWRkKGUpfSkuY2F0Y2goZnVuY3Rpb24odCl7d2FybihgVHlwZTMgZm9udCByZXNvdXJjZSAiJHtlfSIgaXMgbm90IGF2YWlsYWJsZS5gKTtjb25zdCByPW5ldyBPcGVyYXRvckxpc3Q7aFtlXT1yLmdldElSKCl9KX0pO3RoaXMuI25lPW8udGhlbigoKT0+e2EuY2hhclByb2NPcGVyYXRvckxpc3Q9aDtpZih0aGlzLl9iYm94KXthLmlzQ2hhckJCb3g9ITA7YS5iYm94PXRoaXMuX2Jib3h9fSk7cmV0dXJuIHRoaXMuI25lfSNpZShlLHQ9TmFOKXtjb25zdCByPVV0aWwubm9ybWFsaXplUmVjdChlLmFyZ3NBcnJheVswXS5zbGljZSgyKSksYT1yWzJdLXJbMF0sbj1yWzNdLXJbMV0saT1NYXRoLmh5cG90KGEsbik7aWYoMD09PWF8fDA9PT1uKXtlLmZuQXJyYXkuc3BsaWNlKDAsMSk7ZS5hcmdzQXJyYXkuc3BsaWNlKDAsMSl9ZWxzZSBpZigwPT09dHx8TWF0aC5yb3VuZChpL3QpPj0xMCl7dGhpcy5fYmJveD8/PVsxLzAsMS8wLC0xLzAsLTEvMF07VXRpbC5yZWN0Qm91bmRpbmdCb3goLi4ucix0aGlzLl9iYm94KX1sZXQgcz0wLG89ZS5sZW5ndGg7Zm9yKDtzPG87KXtzd2l0Y2goZS5mbkFycmF5W3NdKXtjYXNlIG50OmJyZWFrO2Nhc2UgaXQ6Y2FzZSBzdDpjYXNlIG90OmNhc2UgY3Q6Y2FzZSBsdDpjYXNlIGh0OmNhc2UgdXQ6Y2FzZSBkdDpjYXNlIGZ0OmNhc2UgZ3Q6Y2FzZSBwdDpjYXNlIG10OmNhc2UgYnQ6Y2FzZSBwZTplLmZuQXJyYXkuc3BsaWNlKHMsMSk7ZS5hcmdzQXJyYXkuc3BsaWNlKHMsMSk7by0tO2NvbnRpbnVlO2Nhc2UgYmU6Y29uc3RbdF09ZS5hcmdzQXJyYXlbc107bGV0IHI9MCxhPXQubGVuZ3RoO2Zvcig7cjxhOyl7Y29uc3RbZV09dFtyXTtzd2l0Y2goZSl7Y2FzZSJUUiI6Y2FzZSJUUjIiOmNhc2UiSFQiOmNhc2UiQkciOmNhc2UiQkcyIjpjYXNlIlVDUiI6Y2FzZSJVQ1IyIjp0LnNwbGljZShyLDEpO2EtLTtjb250aW51ZX1yKyt9fXMrK319I3NlKGUpe2xldCB0PTE7Y29uc3Qgcj1lLmxlbmd0aDtmb3IoO3Q8cjspe2lmKGUuZm5BcnJheVt0XT09PUh0KXtjb25zdCByPWUuYXJnc0FycmF5W3RdWzJdO3RoaXMuX2Jib3g/Pz1bMS8wLDEvMCwtMS8wLC0xLzBdO1V0aWwucmVjdEJvdW5kaW5nQm94KC4uLnIsdGhpcy5fYmJveCl9dCsrfX19Y2xhc3MgU3RhdGVNYW5hZ2Vye2NvbnN0cnVjdG9yKGU9bmV3IEV2YWxTdGF0ZSl7dGhpcy5zdGF0ZT1lO3RoaXMuc3RhdGVTdGFjaz1bXX1zYXZlKCl7Y29uc3QgZT10aGlzLnN0YXRlO3RoaXMuc3RhdGVTdGFjay5wdXNoKHRoaXMuc3RhdGUpO3RoaXMuc3RhdGU9ZS5jbG9uZSgpfXJlc3RvcmUoKXtjb25zdCBlPXRoaXMuc3RhdGVTdGFjay5wb3AoKTtlJiYodGhpcy5zdGF0ZT1lKX10cmFuc2Zvcm0oZSl7dGhpcy5zdGF0ZS5jdG09VXRpbC50cmFuc2Zvcm0odGhpcy5zdGF0ZS5jdG0sZSl9fWNsYXNzIFRleHRTdGF0ZXtjb25zdHJ1Y3Rvcigpe3RoaXMuY3RtPW5ldyBGbG9hdDMyQXJyYXkoZnIpO3RoaXMuZm9udE5hbWU9bnVsbDt0aGlzLmZvbnRTaXplPTA7dGhpcy5sb2FkZWROYW1lPW51bGw7dGhpcy5mb250PW51bGw7dGhpcy5mb250TWF0cml4PWE7dGhpcy50ZXh0TWF0cml4PWZyLnNsaWNlKCk7dGhpcy50ZXh0TGluZU1hdHJpeD1mci5zbGljZSgpO3RoaXMuY2hhclNwYWNpbmc9MDt0aGlzLndvcmRTcGFjaW5nPTA7dGhpcy5sZWFkaW5nPTA7dGhpcy50ZXh0SFNjYWxlPTE7dGhpcy50ZXh0UmlzZT0wfXNldFRleHRNYXRyaXgoZSx0LHIsYSxuLGkpe2NvbnN0IHM9dGhpcy50ZXh0TWF0cml4O3NbMF09ZTtzWzFdPXQ7c1syXT1yO3NbM109YTtzWzRdPW47c1s1XT1pfXNldFRleHRMaW5lTWF0cml4KGUsdCxyLGEsbixpKXtjb25zdCBzPXRoaXMudGV4dExpbmVNYXRyaXg7c1swXT1lO3NbMV09dDtzWzJdPXI7c1szXT1hO3NbNF09bjtzWzVdPWl9dHJhbnNsYXRlVGV4dE1hdHJpeChlLHQpe2NvbnN0IHI9dGhpcy50ZXh0TWF0cml4O3JbNF09clswXSplK3JbMl0qdCtyWzRdO3JbNV09clsxXSplK3JbM10qdCtyWzVdfXRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KGUsdCl7Y29uc3Qgcj10aGlzLnRleHRMaW5lTWF0cml4O3JbNF09clswXSplK3JbMl0qdCtyWzRdO3JbNV09clsxXSplK3JbM10qdCtyWzVdfWNhcnJpYWdlUmV0dXJuKCl7dGhpcy50cmFuc2xhdGVUZXh0TGluZU1hdHJpeCgwLC10aGlzLmxlYWRpbmcpO3RoaXMudGV4dE1hdHJpeD10aGlzLnRleHRMaW5lTWF0cml4LnNsaWNlKCl9Y2xvbmUoKXtjb25zdCBlPU9iamVjdC5jcmVhdGUodGhpcyk7ZS50ZXh0TWF0cml4PXRoaXMudGV4dE1hdHJpeC5zbGljZSgpO2UudGV4dExpbmVNYXRyaXg9dGhpcy50ZXh0TGluZU1hdHJpeC5zbGljZSgpO2UuZm9udE1hdHJpeD10aGlzLmZvbnRNYXRyaXguc2xpY2UoKTtyZXR1cm4gZX19Y2xhc3MgRXZhbFN0YXRle2NvbnN0cnVjdG9yKCl7dGhpcy5jdG09bmV3IEZsb2F0MzJBcnJheShmcik7dGhpcy5mb250PW51bGw7dGhpcy50ZXh0UmVuZGVyaW5nTW9kZT1rO3RoaXMuX2ZpbGxDb2xvclNwYWNlPXRoaXMuX3N0cm9rZUNvbG9yU3BhY2U9Q29sb3JTcGFjZVV0aWxzLmdyYXk7dGhpcy5wYXR0ZXJuRmlsbENvbG9yU3BhY2U9bnVsbDt0aGlzLnBhdHRlcm5TdHJva2VDb2xvclNwYWNlPW51bGw7dGhpcy5jdXJyZW50UG9pbnRYPXRoaXMuY3VycmVudFBvaW50WT0wO3RoaXMucGF0aE1pbk1heD1uZXcgRmxvYXQzMkFycmF5KFsxLzAsMS8wLC0xLzAsLTEvMF0pO3RoaXMucGF0aEJ1ZmZlcj1bXX1nZXQgZmlsbENvbG9yU3BhY2UoKXtyZXR1cm4gdGhpcy5fZmlsbENvbG9yU3BhY2V9c2V0IGZpbGxDb2xvclNwYWNlKGUpe3RoaXMuX2ZpbGxDb2xvclNwYWNlPXRoaXMucGF0dGVybkZpbGxDb2xvclNwYWNlPWV9Z2V0IHN0cm9rZUNvbG9yU3BhY2UoKXtyZXR1cm4gdGhpcy5fc3Ryb2tlQ29sb3JTcGFjZX1zZXQgc3Ryb2tlQ29sb3JTcGFjZShlKXt0aGlzLl9zdHJva2VDb2xvclNwYWNlPXRoaXMucGF0dGVyblN0cm9rZUNvbG9yU3BhY2U9ZX1jbG9uZSh7bmV3UGF0aDplPSExfT17fSl7Y29uc3QgdD1PYmplY3QuY3JlYXRlKHRoaXMpO2lmKGUpe3QucGF0aEJ1ZmZlcj1bXTt0LnBhdGhNaW5NYXg9bmV3IEZsb2F0MzJBcnJheShbMS8wLDEvMCwtMS8wLC0xLzBdKX1yZXR1cm4gdH19Y2xhc3MgRXZhbHVhdG9yUHJlcHJvY2Vzc29ye3N0YXRpYyBnZXQgb3BNYXAoKXtyZXR1cm4gc2hhZG93KHRoaXMsIm9wTWFwIixPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCkse3c6e2lkOmhlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LEo6e2lkOnVlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LGo6e2lkOmRlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LE06e2lkOmZlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LGQ6e2lkOmdlLG51bUFyZ3M6Mix2YXJpYWJsZUFyZ3M6ITF9LHJpOntpZDpwZSxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxpOntpZDptZSxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxnczp7aWQ6YmUsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0scTp7aWQ6eWUsbnVtQXJnczowLHZhcmlhYmxlQXJnczohMX0sUTp7aWQ6d2UsbnVtQXJnczowLHZhcmlhYmxlQXJnczohMX0sY206e2lkOnhlLG51bUFyZ3M6Nix2YXJpYWJsZUFyZ3M6ITF9LG06e2lkOlNlLG51bUFyZ3M6Mix2YXJpYWJsZUFyZ3M6ITF9LGw6e2lkOkFlLG51bUFyZ3M6Mix2YXJpYWJsZUFyZ3M6ITF9LGM6e2lkOmtlLG51bUFyZ3M6Nix2YXJpYWJsZUFyZ3M6ITF9LHY6e2lkOkNlLG51bUFyZ3M6NCx2YXJpYWJsZUFyZ3M6ITF9LHk6e2lkOnZlLG51bUFyZ3M6NCx2YXJpYWJsZUFyZ3M6ITF9LGg6e2lkOkZlLG51bUFyZ3M6MCx2YXJpYWJsZUFyZ3M6ITF9LHJlOntpZDpJZSxudW1BcmdzOjQsdmFyaWFibGVBcmdzOiExfSxTOntpZDpUZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxzOntpZDpPZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxmOntpZDpNZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxGOntpZDpNZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSwiZioiOntpZDpEZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxCOntpZDpCZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSwiQioiOntpZDpSZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxiOntpZDpFZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSwiYioiOntpZDpOZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxuOntpZDpQZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxXOntpZDpfZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSwiVyoiOntpZDpMZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxCVDp7aWQ6amUsbnVtQXJnczowLHZhcmlhYmxlQXJnczohMX0sRVQ6e2lkOlVlLG51bUFyZ3M6MCx2YXJpYWJsZUFyZ3M6ITF9LFRjOntpZDpxZSxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxUdzp7aWQ6WGUsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0sVHo6e2lkOkhlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LFRMOntpZDpXZSxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxUZjp7aWQ6emUsbnVtQXJnczoyLHZhcmlhYmxlQXJnczohMX0sVHI6e2lkOkdlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LFRzOntpZDokZSxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxUZDp7aWQ6VmUsbnVtQXJnczoyLHZhcmlhYmxlQXJnczohMX0sVEQ6e2lkOktlLG51bUFyZ3M6Mix2YXJpYWJsZUFyZ3M6ITF9LFRtOntpZDpKZSxudW1BcmdzOjYsdmFyaWFibGVBcmdzOiExfSwiVCoiOntpZDpZZSxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxUajp7aWQ6WmUsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0sVEo6e2lkOlFlLG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LCInIjp7aWQ6ZXQsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0sJyInOntpZDp0dCxudW1BcmdzOjMsdmFyaWFibGVBcmdzOiExfSxkMDp7aWQ6cnQsbnVtQXJnczoyLHZhcmlhYmxlQXJnczohMX0sZDE6e2lkOm50LG51bUFyZ3M6Nix2YXJpYWJsZUFyZ3M6ITF9LENTOntpZDppdCxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxjczp7aWQ6c3QsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0sU0M6e2lkOm90LG51bUFyZ3M6NCx2YXJpYWJsZUFyZ3M6ITB9LFNDTjp7aWQ6Y3QsbnVtQXJnczozMyx2YXJpYWJsZUFyZ3M6ITB9LHNjOntpZDpsdCxudW1BcmdzOjQsdmFyaWFibGVBcmdzOiEwfSxzY246e2lkOmh0LG51bUFyZ3M6MzMsdmFyaWFibGVBcmdzOiEwfSxHOntpZDp1dCxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxnOntpZDpkdCxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxSRzp7aWQ6ZnQsbnVtQXJnczozLHZhcmlhYmxlQXJnczohMX0scmc6e2lkOmd0LG51bUFyZ3M6Myx2YXJpYWJsZUFyZ3M6ITF9LEs6e2lkOnB0LG51bUFyZ3M6NCx2YXJpYWJsZUFyZ3M6ITF9LGs6e2lkOm10LG51bUFyZ3M6NCx2YXJpYWJsZUFyZ3M6ITF9LHNoOntpZDpidCxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxCSTp7aWQ6eXQsbnVtQXJnczowLHZhcmlhYmxlQXJnczohMX0sSUQ6e2lkOnd0LG51bUFyZ3M6MCx2YXJpYWJsZUFyZ3M6ITF9LEVJOntpZDp4dCxudW1BcmdzOjEsdmFyaWFibGVBcmdzOiExfSxEbzp7aWQ6U3QsbnVtQXJnczoxLHZhcmlhYmxlQXJnczohMX0sTVA6e2lkOkF0LG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LERQOntpZDprdCxudW1BcmdzOjIsdmFyaWFibGVBcmdzOiExfSxCTUM6e2lkOkN0LG51bUFyZ3M6MSx2YXJpYWJsZUFyZ3M6ITF9LEJEQzp7aWQ6dnQsbnVtQXJnczoyLHZhcmlhYmxlQXJnczohMX0sRU1DOntpZDpGdCxudW1BcmdzOjAsdmFyaWFibGVBcmdzOiExfSxCWDp7aWQ6SXQsbnVtQXJnczowLHZhcmlhYmxlQXJnczohMX0sRVg6e2lkOlR0LG51bUFyZ3M6MCx2YXJpYWJsZUFyZ3M6ITF9LEJNOm51bGwsQkQ6bnVsbCx0cnVlOm51bGwsZmE6bnVsbCxmYWw6bnVsbCxmYWxzOm51bGwsZmFsc2U6bnVsbCxudTpudWxsLG51bDpudWxsLG51bGw6bnVsbH0pKX1zdGF0aWMgTUFYX0lOVkFMSURfUEFUSF9PUFM9MTA7Y29uc3RydWN0b3IoZSx0LHI9bmV3IFN0YXRlTWFuYWdlcil7dGhpcy5wYXJzZXI9bmV3IFBhcnNlcih7bGV4ZXI6bmV3IExleGVyKGUsRXZhbHVhdG9yUHJlcHJvY2Vzc29yLm9wTWFwKSx4cmVmOnR9KTt0aGlzLnN0YXRlTWFuYWdlcj1yO3RoaXMubm9uUHJvY2Vzc2VkQXJncz1bXTt0aGlzLl9pc1BhdGhPcD0hMTt0aGlzLl9udW1JbnZhbGlkUGF0aE9QUz0wfWdldCBzYXZlZFN0YXRlc0RlcHRoKCl7cmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLnN0YXRlU3RhY2subGVuZ3RofXJlYWQoZSl7bGV0IHQ9ZS5hcmdzO2Zvcig7Oyl7Y29uc3Qgcj10aGlzLnBhcnNlci5nZXRPYmooKTtpZihyIGluc3RhbmNlb2YgQ21kKXtjb25zdCBhPXIuY21kLG49RXZhbHVhdG9yUHJlcHJvY2Vzc29yLm9wTWFwW2FdO2lmKCFuKXt3YXJuKGBVbmtub3duIGNvbW1hbmQgIiR7YX0iLmApO2NvbnRpbnVlfWNvbnN0IGk9bi5pZCxzPW4ubnVtQXJncztsZXQgbz1udWxsIT09dD90Lmxlbmd0aDowO3RoaXMuX2lzUGF0aE9wfHwodGhpcy5fbnVtSW52YWxpZFBhdGhPUFM9MCk7dGhpcy5faXNQYXRoT3A9aT49U2UmJmk8PVBlO2lmKG4udmFyaWFibGVBcmdzKW8+cyYmaW5mbyhgQ29tbWFuZCAke2F9OiBleHBlY3RlZCBbMCwgJHtzfV0gYXJncywgYnV0IHJlY2VpdmVkICR7b30gYXJncy5gKTtlbHNle2lmKG8hPT1zKXtjb25zdCBlPXRoaXMubm9uUHJvY2Vzc2VkQXJncztmb3IoO28+czspe2UucHVzaCh0LnNoaWZ0KCkpO28tLX1mb3IoO288cyYmMCE9PWUubGVuZ3RoOyl7bnVsbD09PXQmJih0PVtdKTt0LnVuc2hpZnQoZS5wb3AoKSk7bysrfX1pZihvPHMpe2NvbnN0IGU9YGNvbW1hbmQgJHthfTogZXhwZWN0ZWQgJHtzfSBhcmdzLCBidXQgcmVjZWl2ZWQgJHtvfSBhcmdzLmA7aWYodGhpcy5faXNQYXRoT3AmJisrdGhpcy5fbnVtSW52YWxpZFBhdGhPUFM+RXZhbHVhdG9yUHJlcHJvY2Vzc29yLk1BWF9JTlZBTElEX1BBVEhfT1BTKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCAke2V9YCk7d2FybihgU2tpcHBpbmcgJHtlfWApO251bGwhPT10JiYodC5sZW5ndGg9MCk7Y29udGludWV9fXRoaXMucHJlcHJvY2Vzc0NvbW1hbmQoaSx0KTtlLmZuPWk7ZS5hcmdzPXQ7cmV0dXJuITB9aWYocj09PXNyKXJldHVybiExO2lmKG51bGwhPT1yKXtudWxsPT09dCYmKHQ9W10pO3QucHVzaChyKTtpZih0Lmxlbmd0aD4zMyl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlRvbyBtYW55IGFyZ3VtZW50cyIpfX19cHJlcHJvY2Vzc0NvbW1hbmQoZSx0KXtzd2l0Y2goMHxlKXtjYXNlIHllOnRoaXMuc3RhdGVNYW5hZ2VyLnNhdmUoKTticmVhaztjYXNlIHdlOnRoaXMuc3RhdGVNYW5hZ2VyLnJlc3RvcmUoKTticmVhaztjYXNlIHhlOnRoaXMuc3RhdGVNYW5hZ2VyLnRyYW5zZm9ybSh0KX19fWNsYXNzIERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yIGV4dGVuZHMgRXZhbHVhdG9yUHJlcHJvY2Vzc29ye2NvbnN0cnVjdG9yKGUpe3N1cGVyKG5ldyBTdHJpbmdTdHJlYW0oZSkpfXBhcnNlKCl7Y29uc3QgZT17Zm46MCxhcmdzOltdfSx0PXtmb250U2l6ZTowLGZvbnROYW1lOiIiLGZvbnRDb2xvcjpuZXcgVWludDhDbGFtcGVkQXJyYXkoMyl9O3RyeXtmb3IoOzspe2UuYXJncy5sZW5ndGg9MDtpZighdGhpcy5yZWFkKGUpKWJyZWFrO2lmKDAhPT10aGlzLnNhdmVkU3RhdGVzRGVwdGgpY29udGludWU7Y29uc3R7Zm46cixhcmdzOmF9PWU7c3dpdGNoKDB8cil7Y2FzZSB6ZTpjb25zdFtlLHJdPWE7ZSBpbnN0YW5jZW9mIE5hbWUmJih0LmZvbnROYW1lPWUubmFtZSk7Im51bWJlciI9PXR5cGVvZiByJiZyPjAmJih0LmZvbnRTaXplPXIpO2JyZWFrO2Nhc2UgZ3Q6Q29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JJdGVtKGEsMCx0LmZvbnRDb2xvciwwKTticmVhaztjYXNlIGR0OkNvbG9yU3BhY2VVdGlscy5ncmF5LmdldFJnYkl0ZW0oYSwwLHQuZm9udENvbG9yLDApO2JyZWFrO2Nhc2UgbXQ6Q29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiSXRlbShhLDAsdC5mb250Q29sb3IsMCl9fX1jYXRjaChlKXt3YXJuKGBwYXJzZURlZmF1bHRBcHBlYXJhbmNlIC0gaWdub3JpbmcgZXJyb3JzOiAiJHtlfSIuYCl9cmV0dXJuIHR9fWZ1bmN0aW9uIHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UoZSl7cmV0dXJuIG5ldyBEZWZhdWx0QXBwZWFyYW5jZUV2YWx1YXRvcihlKS5wYXJzZSgpfWNsYXNzIEFwcGVhcmFuY2VTdHJlYW1FdmFsdWF0b3IgZXh0ZW5kcyBFdmFsdWF0b3JQcmVwcm9jZXNzb3J7Y29uc3RydWN0b3IoZSx0LHIsYSl7c3VwZXIoZSk7dGhpcy5zdHJlYW09ZTt0aGlzLmV2YWx1YXRvck9wdGlvbnM9dDt0aGlzLnhyZWY9cjt0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZT1hO3RoaXMucmVzb3VyY2VzPWUuZGljdD8uZ2V0KCJSZXNvdXJjZXMiKX1wYXJzZSgpe2NvbnN0IGU9e2ZuOjAsYXJnczpbXX07bGV0IHQ9e3NjYWxlRmFjdG9yOjEsZm9udFNpemU6MCxmb250TmFtZToiIixmb250Q29sb3I6bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpLGZpbGxDb2xvclNwYWNlOkNvbG9yU3BhY2VVdGlscy5ncmF5fSxyPSExO2NvbnN0IGE9W107dHJ5e2Zvcig7Oyl7ZS5hcmdzLmxlbmd0aD0wO2lmKHJ8fCF0aGlzLnJlYWQoZSkpYnJlYWs7Y29uc3R7Zm46bixhcmdzOml9PWU7c3dpdGNoKDB8bil7Y2FzZSB5ZTphLnB1c2goe3NjYWxlRmFjdG9yOnQuc2NhbGVGYWN0b3IsZm9udFNpemU6dC5mb250U2l6ZSxmb250TmFtZTp0LmZvbnROYW1lLGZvbnRDb2xvcjp0LmZvbnRDb2xvci5zbGljZSgpLGZpbGxDb2xvclNwYWNlOnQuZmlsbENvbG9yU3BhY2V9KTticmVhaztjYXNlIHdlOnQ9YS5wb3AoKXx8dDticmVhaztjYXNlIEplOnQuc2NhbGVGYWN0b3IqPU1hdGguaHlwb3QoaVswXSxpWzFdKTticmVhaztjYXNlIHplOmNvbnN0W2Usbl09aTtlIGluc3RhbmNlb2YgTmFtZSYmKHQuZm9udE5hbWU9ZS5uYW1lKTsibnVtYmVyIj09dHlwZW9mIG4mJm4+MCYmKHQuZm9udFNpemU9bip0LnNjYWxlRmFjdG9yKTticmVhaztjYXNlIHN0OnQuZmlsbENvbG9yU3BhY2U9Q29sb3JTcGFjZVV0aWxzLnBhcnNlKHtjczppWzBdLHhyZWY6dGhpcy54cmVmLHJlc291cmNlczp0aGlzLnJlc291cmNlcyxwZGZGdW5jdGlvbkZhY3Rvcnk6dGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LGdsb2JhbENvbG9yU3BhY2VDYWNoZTp0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSxsb2NhbENvbG9yU3BhY2VDYWNoZTp0aGlzLl9sb2NhbENvbG9yU3BhY2VDYWNoZX0pO2JyZWFrO2Nhc2UgbHQ6dC5maWxsQ29sb3JTcGFjZS5nZXRSZ2JJdGVtKGksMCx0LmZvbnRDb2xvciwwKTticmVhaztjYXNlIGd0OkNvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiSXRlbShpLDAsdC5mb250Q29sb3IsMCk7YnJlYWs7Y2FzZSBkdDpDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JJdGVtKGksMCx0LmZvbnRDb2xvciwwKTticmVhaztjYXNlIG10OkNvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkl0ZW0oaSwwLHQuZm9udENvbG9yLDApO2JyZWFrO2Nhc2UgWmU6Y2FzZSBRZTpjYXNlIGV0OmNhc2UgdHQ6cj0hMH19fWNhdGNoKGUpe3dhcm4oYHBhcnNlQXBwZWFyYW5jZVN0cmVhbSAtIGlnbm9yaW5nIGVycm9yczogIiR7ZX0iLmApfXRoaXMuc3RyZWFtLnJlc2V0KCk7ZGVsZXRlIHQuc2NhbGVGYWN0b3I7ZGVsZXRlIHQuZmlsbENvbG9yU3BhY2U7cmV0dXJuIHR9Z2V0IF9sb2NhbENvbG9yU3BhY2VDYWNoZSgpe3JldHVybiBzaGFkb3codGhpcywiX2xvY2FsQ29sb3JTcGFjZUNhY2hlIixuZXcgTG9jYWxDb2xvclNwYWNlQ2FjaGUpfWdldCBfcGRmRnVuY3Rpb25GYWN0b3J5KCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJfcGRmRnVuY3Rpb25GYWN0b3J5IixuZXcgUERGRnVuY3Rpb25GYWN0b3J5KHt4cmVmOnRoaXMueHJlZixpc0V2YWxTdXBwb3J0ZWQ6dGhpcy5ldmFsdWF0b3JPcHRpb25zLmlzRXZhbFN1cHBvcnRlZH0pKX19ZnVuY3Rpb24gZ2V0UGRmQ29sb3IoZSx0KXtpZihlWzBdPT09ZVsxXSYmZVsxXT09PWVbMl0pe3JldHVybmAke251bWJlclRvU3RyaW5nKGVbMF0vMjU1KX0gJHt0PyJnIjoiRyJ9YH1yZXR1cm4gQXJyYXkuZnJvbShlLGU9Pm51bWJlclRvU3RyaW5nKGUvMjU1KSkuam9pbigiICIpKyIgIisodD8icmciOiJSRyIpfWNsYXNzIEZha2VVbmljb2RlRm9udHtjb25zdHJ1Y3RvcihlLHQpe3RoaXMueHJlZj1lO3RoaXMud2lkdGhzPW51bGw7dGhpcy5maXJzdENoYXI9MS8wO3RoaXMubGFzdENoYXI9LTEvMDt0aGlzLmZvbnRGYW1pbHk9dDtjb25zdCByPW5ldyBPZmZzY3JlZW5DYW52YXMoMSwxKTt0aGlzLmN0eE1lYXN1cmU9ci5nZXRDb250ZXh0KCIyZCIse3dpbGxSZWFkRnJlcXVlbnRseTohMH0pO0Zha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZHx8KEZha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZD0xKTt0aGlzLmZvbnROYW1lPU5hbWUuZ2V0KGBJbnZhbGlkUERGanNGb250XyR7dH1fJHtGYWtlVW5pY29kZUZvbnQuX2ZvbnROYW1lSWQrK31gKX1nZXQgZm9udERlc2NyaXB0b3JSZWYoKXtpZighRmFrZVVuaWNvZGVGb250Ll9mb250RGVzY3JpcHRvclJlZil7Y29uc3QgZT1uZXcgRGljdCh0aGlzLnhyZWYpO2Uuc2V0SWZOYW1lKCJUeXBlIiwiRm9udERlc2NyaXB0b3IiKTtlLnNldCgiRm9udE5hbWUiLHRoaXMuZm9udE5hbWUpO2Uuc2V0KCJGb250RmFtaWx5IiwiTXlyaWFkUHJvIFJlZ3VsYXIiKTtlLnNldCgiRm9udEJCb3giLFswLDAsMCwwXSk7ZS5zZXRJZk5hbWUoIkZvbnRTdHJldGNoIiwiTm9ybWFsIik7ZS5zZXQoIkZvbnRXZWlnaHQiLDQwMCk7ZS5zZXQoIkl0YWxpY0FuZ2xlIiwwKTtGYWtlVW5pY29kZUZvbnQuX2ZvbnREZXNjcmlwdG9yUmVmPXRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGUpfXJldHVybiBGYWtlVW5pY29kZUZvbnQuX2ZvbnREZXNjcmlwdG9yUmVmfWdldCBkZXNjZW5kYW50Rm9udFJlZigpe2NvbnN0IGU9bmV3IERpY3QodGhpcy54cmVmKTtlLnNldCgiQmFzZUZvbnQiLHRoaXMuZm9udE5hbWUpO2Uuc2V0SWZOYW1lKCJUeXBlIiwiRm9udCIpO2Uuc2V0SWZOYW1lKCJTdWJ0eXBlIiwiQ0lERm9udFR5cGUwIik7ZS5zZXRJZk5hbWUoIkNJRFRvR0lETWFwIiwiSWRlbnRpdHkiKTtlLnNldCgiRmlyc3RDaGFyIix0aGlzLmZpcnN0Q2hhcik7ZS5zZXQoIkxhc3RDaGFyIix0aGlzLmxhc3RDaGFyKTtlLnNldCgiRm9udERlc2NyaXB0b3IiLHRoaXMuZm9udERlc2NyaXB0b3JSZWYpO2Uuc2V0KCJEVyIsMWUzKTtjb25zdCB0PVtdLHI9Wy4uLnRoaXMud2lkdGhzLmVudHJpZXMoKV0uc29ydCgpO2xldCBhPW51bGwsbj1udWxsO2Zvcihjb25zdFtlLGldb2YgcilpZihhKWlmKGU9PT1hK24ubGVuZ3RoKW4ucHVzaChpKTtlbHNle3QucHVzaChhLG4pO2E9ZTtuPVtpXX1lbHNle2E9ZTtuPVtpXX1hJiZ0LnB1c2goYSxuKTtlLnNldCgiVyIsdCk7Y29uc3QgaT1uZXcgRGljdCh0aGlzLnhyZWYpO2kuc2V0KCJPcmRlcmluZyIsIklkZW50aXR5Iik7aS5zZXQoIlJlZ2lzdHJ5IiwiQWRvYmUiKTtpLnNldCgiU3VwcGxlbWVudCIsMCk7ZS5zZXQoIkNJRFN5c3RlbUluZm8iLGkpO3JldHVybiB0aGlzLnhyZWYuZ2V0TmV3UGVyc2lzdGVudFJlZihlKX1nZXQgYmFzZUZvbnRSZWYoKXtjb25zdCBlPW5ldyBEaWN0KHRoaXMueHJlZik7ZS5zZXQoIkJhc2VGb250Iix0aGlzLmZvbnROYW1lKTtlLnNldElmTmFtZSgiVHlwZSIsIkZvbnQiKTtlLnNldElmTmFtZSgiU3VidHlwZSIsIlR5cGUwIik7ZS5zZXRJZk5hbWUoIkVuY29kaW5nIiwiSWRlbnRpdHktSCIpO2Uuc2V0KCJEZXNjZW5kYW50Rm9udHMiLFt0aGlzLmRlc2NlbmRhbnRGb250UmVmXSk7ZS5zZXRJZk5hbWUoIlRvVW5pY29kZSIsIklkZW50aXR5LUgiKTtyZXR1cm4gdGhpcy54cmVmLmdldE5ld1BlcnNpc3RlbnRSZWYoZSl9Z2V0IHJlc291cmNlcygpe2NvbnN0IGU9bmV3IERpY3QodGhpcy54cmVmKSx0PW5ldyBEaWN0KHRoaXMueHJlZik7dC5zZXQodGhpcy5mb250TmFtZS5uYW1lLHRoaXMuYmFzZUZvbnRSZWYpO2Uuc2V0KCJGb250Iix0KTtyZXR1cm4gZX1fY3JlYXRlQ29udGV4dCgpe3RoaXMud2lkdGhzPW5ldyBNYXA7dGhpcy5jdHhNZWFzdXJlLmZvbnQ9YDEwMDBweCAke3RoaXMuZm9udEZhbWlseX1gO3JldHVybiB0aGlzLmN0eE1lYXN1cmV9Y3JlYXRlRm9udFJlc291cmNlcyhlKXtjb25zdCB0PXRoaXMuX2NyZWF0ZUNvbnRleHQoKTtmb3IoY29uc3QgciBvZiBlLnNwbGl0KC9cclxuP3xcbi8pKWZvcihjb25zdCBlIG9mIHIuc3BsaXQoIiIpKXtjb25zdCByPWUuY2hhckNvZGVBdCgwKTtpZih0aGlzLndpZHRocy5oYXMocikpY29udGludWU7Y29uc3QgYT10Lm1lYXN1cmVUZXh0KGUpLG49TWF0aC5jZWlsKGEud2lkdGgpO3RoaXMud2lkdGhzLnNldChyLG4pO3RoaXMuZmlyc3RDaGFyPU1hdGgubWluKHIsdGhpcy5maXJzdENoYXIpO3RoaXMubGFzdENoYXI9TWF0aC5tYXgocix0aGlzLmxhc3RDaGFyKX1yZXR1cm4gdGhpcy5yZXNvdXJjZXN9c3RhdGljIGdldEZpcnN0UG9zaXRpb25JbmZvKGUsdCxyKXtjb25zdFthLHMsbyxjXT1lO2xldCBsPW8tYSxoPWMtczt0JTE4MCE9MCYmKFtsLGhdPVtoLGxdKTtjb25zdCB1PW4qcjtyZXR1cm57Y29vcmRzOlswLGgraSpyLXVdLGJib3g6WzAsMCxsLGhdLG1hdHJpeDowIT09dD9nZXRSb3RhdGlvbk1hdHJpeCh0LGgsdSk6dm9pZCAwfX1jcmVhdGVBcHBlYXJhbmNlKGUsdCxyLGEscyxvKXtjb25zdCBjPXRoaXMuX2NyZWF0ZUNvbnRleHQoKSxsPVtdO2xldCBoPS0xLzA7Zm9yKGNvbnN0IHQgb2YgZS5zcGxpdCgvXHJcbj98XG4vKSl7bC5wdXNoKHQpO2NvbnN0IGU9Yy5tZWFzdXJlVGV4dCh0KS53aWR0aDtoPU1hdGgubWF4KGgsZSk7Zm9yKGNvbnN0IGUgb2YgY29kZVBvaW50SXRlcih0KSl7Y29uc3QgdD1TdHJpbmcuZnJvbUNvZGVQb2ludChlKTtsZXQgcj10aGlzLndpZHRocy5nZXQoZSk7aWYodm9pZCAwPT09cil7Y29uc3QgYT1jLm1lYXN1cmVUZXh0KHQpO3I9TWF0aC5jZWlsKGEud2lkdGgpO3RoaXMud2lkdGhzLnNldChlLHIpO3RoaXMuZmlyc3RDaGFyPU1hdGgubWluKGUsdGhpcy5maXJzdENoYXIpO3RoaXMubGFzdENoYXI9TWF0aC5tYXgoZSx0aGlzLmxhc3RDaGFyKX19fWgqPWEvMWUzO2NvbnN0W3UsZCxmLGddPXQ7bGV0IHA9Zi11LG09Zy1kO3IlMTgwIT0wJiYoW3AsbV09W20scF0pO2xldCBiPTE7aD5wJiYoYj1wL2gpO2xldCB5PTE7Y29uc3Qgdz1uKmEseD1pKmEsUz13KmwubGVuZ3RoO1M+bSYmKHk9bS9TKTtjb25zdCBrPWEqTWF0aC5taW4oYix5KSxDPVsicSIsYDAgMCAke251bWJlclRvU3RyaW5nKHApfSAke251bWJlclRvU3RyaW5nKG0pfSByZSBXIG5gLCJCVCIsYDEgMCAwIDEgMCAke251bWJlclRvU3RyaW5nKG0reCl9IFRtIDAgVGMgJHtnZXRQZGZDb2xvcihzLCEwKX1gLGAvJHt0aGlzLmZvbnROYW1lLm5hbWV9ICR7bnVtYmVyVG9TdHJpbmcoayl9IFRmYF0se3Jlc291cmNlczp2fT10aGlzO2lmKDEhPT0obz0ibnVtYmVyIj09dHlwZW9mIG8mJm8+PTAmJm88PTE/bzoxKSl7Qy5wdXNoKCIvUjAgZ3MiKTtjb25zdCBlPW5ldyBEaWN0KHRoaXMueHJlZiksdD1uZXcgRGljdCh0aGlzLnhyZWYpO3Quc2V0KCJjYSIsbyk7dC5zZXQoIkNBIixvKTt0LnNldElmTmFtZSgiVHlwZSIsIkV4dEdTdGF0ZSIpO2Uuc2V0KCJSMCIsdCk7di5zZXQoIkV4dEdTdGF0ZSIsZSl9Y29uc3QgVD1udW1iZXJUb1N0cmluZyh3KTtmb3IoY29uc3QgZSBvZiBsKUMucHVzaChgMCAtJHtUfSBUZCA8JHtzdHJpbmdUb1VURjE2SGV4U3RyaW5nKGUpfT4gVGpgKTtDLnB1c2goIkVUIiwiUSIpO2NvbnN0IE89Qy5qb2luKCJcbiIpLE09bmV3IERpY3QodGhpcy54cmVmKTtNLnNldElmTmFtZSgiU3VidHlwZSIsIkZvcm0iKTtNLnNldElmTmFtZSgiVHlwZSIsIlhPYmplY3QiKTtNLnNldCgiQkJveCIsWzAsMCxwLG1dKTtNLnNldCgiTGVuZ3RoIixPLmxlbmd0aCk7TS5zZXQoIlJlc291cmNlcyIsdik7aWYocil7Y29uc3QgZT1nZXRSb3RhdGlvbk1hdHJpeChyLHAsbSk7TS5zZXQoIk1hdHJpeCIsZSl9Y29uc3QgRD1uZXcgU3RyaW5nU3RyZWFtKE8pO0QuZGljdD1NO3JldHVybiBEfX1jb25zdCBTaT1bIm0vZCIsIm0vZC95eSIsIm1tL2RkL3l5IiwibW0veXkiLCJkLW1tbSIsImQtbW1tLXl5IiwiZGQtbW1tLXl5IiwieXktbW0tZGQiLCJtbW0teXkiLCJtbW1tLXl5IiwibW1tIGQsIHl5eXkiLCJtbW1tIGQsIHl5eXkiLCJtL2QveXkgaDpNTSB0dCIsIm0vZC95eSBISDpNTSJdLEFpPVsiSEg6TU0iLCJoOk1NIHR0IiwiSEg6TU06c3MiLCJoOk1NOnNzIHR0Il07Y2xhc3MgTmFtZU9yTnVtYmVyVHJlZXtjb25zdHJ1Y3RvcihlLHQscil7dGhpcy5yb290PWU7dGhpcy54cmVmPXQ7dGhpcy5fdHlwZT1yfWdldEFsbCgpe2NvbnN0IGU9bmV3IE1hcDtpZighdGhpcy5yb290KXJldHVybiBlO2NvbnN0IHQ9dGhpcy54cmVmLHI9bmV3IFJlZlNldDtyLnB1dCh0aGlzLnJvb3QpO2NvbnN0IGE9W3RoaXMucm9vdF07Zm9yKDthLmxlbmd0aD4wOyl7Y29uc3Qgbj10LmZldGNoSWZSZWYoYS5zaGlmdCgpKTtpZighKG4gaW5zdGFuY2VvZiBEaWN0KSljb250aW51ZTtpZihuLmhhcygiS2lkcyIpKXtjb25zdCBlPW4uZ2V0KCJLaWRzIik7aWYoIUFycmF5LmlzQXJyYXkoZSkpY29udGludWU7Zm9yKGNvbnN0IHQgb2YgZSl7aWYoci5oYXModCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBEdXBsaWNhdGUgZW50cnkgaW4gIiR7dGhpcy5fdHlwZX0iIHRyZWUuYCk7YS5wdXNoKHQpO3IucHV0KHQpfWNvbnRpbnVlfWNvbnN0IGk9bi5nZXQodGhpcy5fdHlwZSk7aWYoQXJyYXkuaXNBcnJheShpKSlmb3IobGV0IHI9MCxhPWkubGVuZ3RoO3I8YTtyKz0yKWUuc2V0KHQuZmV0Y2hJZlJlZihpW3JdKSx0LmZldGNoSWZSZWYoaVtyKzFdKSl9cmV0dXJuIGV9Z2V0UmF3KGUpe2lmKCF0aGlzLnJvb3QpcmV0dXJuIG51bGw7Y29uc3QgdD10aGlzLnhyZWY7bGV0IHI9dC5mZXRjaElmUmVmKHRoaXMucm9vdCksYT0wO2Zvcig7ci5oYXMoIktpZHMiKTspe2lmKCsrYT4xMCl7d2FybihgU2VhcmNoIGRlcHRoIGxpbWl0IHJlYWNoZWQgZm9yICIke3RoaXMuX3R5cGV9IiB0cmVlLmApO3JldHVybiBudWxsfWNvbnN0IG49ci5nZXQoIktpZHMiKTtpZighQXJyYXkuaXNBcnJheShuKSlyZXR1cm4gbnVsbDtsZXQgaT0wLHM9bi5sZW5ndGgtMTtmb3IoO2k8PXM7KXtjb25zdCBhPWkrcz4+MSxvPXQuZmV0Y2hJZlJlZihuW2FdKSxjPW8uZ2V0KCJMaW1pdHMiKTtpZihlPHQuZmV0Y2hJZlJlZihjWzBdKSlzPWEtMTtlbHNle2lmKCEoZT50LmZldGNoSWZSZWYoY1sxXSkpKXtyPW87YnJlYWt9aT1hKzF9fWlmKGk+cylyZXR1cm4gbnVsbH1jb25zdCBuPXIuZ2V0KHRoaXMuX3R5cGUpO2lmKEFycmF5LmlzQXJyYXkobikpe2xldCByPTAsYT1uLmxlbmd0aC0yO2Zvcig7cjw9YTspe2NvbnN0IGk9cithPj4xLHM9aSsoMSZpKSxvPXQuZmV0Y2hJZlJlZihuW3NdKTtpZihlPG8pYT1zLTI7ZWxzZXtpZighKGU+bykpcmV0dXJuIG5bcysxXTtyPXMrMn19fXJldHVybiBudWxsfWdldChlKXtyZXR1cm4gdGhpcy54cmVmLmZldGNoSWZSZWYodGhpcy5nZXRSYXcoZSkpfX1jbGFzcyBOYW1lVHJlZSBleHRlbmRzIE5hbWVPck51bWJlclRyZWV7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihlLHQsIk5hbWVzIil9fWNsYXNzIE51bWJlclRyZWUgZXh0ZW5kcyBOYW1lT3JOdW1iZXJUcmVle2NvbnN0cnVjdG9yKGUsdCl7c3VwZXIoZSx0LCJOdW1zIil9fWZ1bmN0aW9uIGNsZWFyR2xvYmFsQ2FjaGVzKCl7IWZ1bmN0aW9uIGNsZWFyUGF0dGVybkNhY2hlcygpe3BuPU9iamVjdC5jcmVhdGUobnVsbCl9KCk7IWZ1bmN0aW9uIGNsZWFyUHJpbWl0aXZlQ2FjaGVzKCl7b3I9T2JqZWN0LmNyZWF0ZShudWxsKTtjcj1PYmplY3QuY3JlYXRlKG51bGwpO2xyPU9iamVjdC5jcmVhdGUobnVsbCl9KCk7IWZ1bmN0aW9uIGNsZWFyVW5pY29kZUNhY2hlcygpe3dhLmNsZWFyKCl9KCk7SnB4SW1hZ2UuY2xlYW51cCgpfWZ1bmN0aW9uIHBpY2tQbGF0Zm9ybUl0ZW0oZSl7cmV0dXJuIGUgaW5zdGFuY2VvZiBEaWN0P2UuaGFzKCJVRiIpP2UuZ2V0KCJVRiIpOmUuaGFzKCJGIik/ZS5nZXQoIkYiKTplLmhhcygiVW5peCIpP2UuZ2V0KCJVbml4Iik6ZS5oYXMoIk1hYyIpP2UuZ2V0KCJNYWMiKTplLmhhcygiRE9TIik/ZS5nZXQoIkRPUyIpOm51bGw6bnVsbH1jbGFzcyBGaWxlU3BlY3sjb2U9ITE7Y29uc3RydWN0b3IoZSx0LHI9ITEpe2lmKGUgaW5zdGFuY2VvZiBEaWN0KXt0aGlzLnhyZWY9dDt0aGlzLnJvb3Q9ZTtlLmhhcygiRlMiKSYmKHRoaXMuZnM9ZS5nZXQoIkZTIikpO2UuaGFzKCJSRiIpJiZ3YXJuKCJSZWxhdGVkIGZpbGUgc3BlY2lmaWNhdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQiKTtyfHwoZS5oYXMoIkVGIik/dGhpcy4jb2U9ITA6d2FybigiTm9uLWVtYmVkZGVkIGZpbGUgc3BlY2lmaWNhdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQiKSl9fWdldCBmaWxlbmFtZSgpe2xldCBlPSIiO2NvbnN0IHQ9cGlja1BsYXRmb3JtSXRlbSh0aGlzLnJvb3QpO3QmJiJzdHJpbmciPT10eXBlb2YgdCYmKGU9c3RyaW5nVG9QREZTdHJpbmcodCwhMCkucmVwbGFjZUFsbCgiXFxcXCIsIlxcIikucmVwbGFjZUFsbCgiXFwvIiwiLyIpLnJlcGxhY2VBbGwoIlxcIiwiLyIpKTtyZXR1cm4gc2hhZG93KHRoaXMsImZpbGVuYW1lIixlfHwidW5uYW1lZCIpfWdldCBjb250ZW50KCl7aWYoIXRoaXMuI29lKXJldHVybiBudWxsO3RoaXMuX2NvbnRlbnRSZWZ8fD1waWNrUGxhdGZvcm1JdGVtKHRoaXMucm9vdD8uZ2V0KCJFRiIpKTtsZXQgZT1udWxsO2lmKHRoaXMuX2NvbnRlbnRSZWYpe2NvbnN0IHQ9dGhpcy54cmVmLmZldGNoSWZSZWYodGhpcy5fY29udGVudFJlZik7dCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0/ZT10LmdldEJ5dGVzKCk6d2FybigiRW1iZWRkZWQgZmlsZSBzcGVjaWZpY2F0aW9uIHBvaW50cyB0byBub24tZXhpc3RpbmcvaW52YWxpZCBjb250ZW50Iil9ZWxzZSB3YXJuKCJFbWJlZGRlZCBmaWxlIHNwZWNpZmljYXRpb24gZG9lcyBub3QgaGF2ZSBhbnkgY29udGVudCIpO3JldHVybiBlfWdldCBkZXNjcmlwdGlvbigpe2xldCBlPSIiO2NvbnN0IHQ9dGhpcy5yb290Py5nZXQoIkRlc2MiKTt0JiYic3RyaW5nIj09dHlwZW9mIHQmJihlPXN0cmluZ1RvUERGU3RyaW5nKHQpKTtyZXR1cm4gc2hhZG93KHRoaXMsImRlc2NyaXB0aW9uIixlKX1nZXQgc2VyaWFsaXphYmxlKCl7cmV0dXJue3Jhd0ZpbGVuYW1lOnRoaXMuZmlsZW5hbWUsZmlsZW5hbWU6KGU9dGhpcy5maWxlbmFtZSxlLnN1YnN0cmluZyhlLmxhc3RJbmRleE9mKCIvIikrMSkpLGNvbnRlbnQ6dGhpcy5jb250ZW50LGRlc2NyaXB0aW9uOnRoaXMuZGVzY3JpcHRpb259O3ZhciBlfX1jb25zdCBraT0wLENpPS0yLHZpPS0zLEZpPS00LElpPS01LFRpPS02LE9pPS05O2Z1bmN0aW9uIGlzV2hpdGVzcGFjZShlLHQpe2NvbnN0IHI9ZVt0XTtyZXR1cm4iICI9PT1yfHwiXG4iPT09cnx8IlxyIj09PXJ8fCJcdCI9PT1yfWNsYXNzIFhNTFBhcnNlckJhc2V7X3Jlc29sdmVFbnRpdGllcyhlKXtyZXR1cm4gZS5yZXBsYWNlQWxsKC8mKFteO10rKTsvZywoZSx0KT0+e2lmKCIjeCI9PT10LnN1YnN0cmluZygwLDIpKXJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChwYXJzZUludCh0LnN1YnN0cmluZygyKSwxNikpO2lmKCIjIj09PXQuc3Vic3RyaW5nKDAsMSkpcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KHBhcnNlSW50KHQuc3Vic3RyaW5nKDEpLDEwKSk7c3dpdGNoKHQpe2Nhc2UibHQiOnJldHVybiI8IjtjYXNlImd0IjpyZXR1cm4iPiI7Y2FzZSJhbXAiOnJldHVybiImIjtjYXNlInF1b3QiOnJldHVybiciJztjYXNlImFwb3MiOnJldHVybiInIn1yZXR1cm4gdGhpcy5vblJlc29sdmVFbnRpdHkodCl9KX1fcGFyc2VDb250ZW50KGUsdCl7Y29uc3Qgcj1bXTtsZXQgYT10O2Z1bmN0aW9uIHNraXBXcygpe2Zvcig7YTxlLmxlbmd0aCYmaXNXaGl0ZXNwYWNlKGUsYSk7KSsrYX1mb3IoO2E8ZS5sZW5ndGgmJiFpc1doaXRlc3BhY2UoZSxhKSYmIj4iIT09ZVthXSYmIi8iIT09ZVthXTspKythO2NvbnN0IG49ZS5zdWJzdHJpbmcodCxhKTtza2lwV3MoKTtmb3IoO2E8ZS5sZW5ndGgmJiI+IiE9PWVbYV0mJiIvIiE9PWVbYV0mJiI/IiE9PWVbYV07KXtza2lwV3MoKTtsZXQgdD0iIixuPSIiO2Zvcig7YTxlLmxlbmd0aCYmIWlzV2hpdGVzcGFjZShlLGEpJiYiPSIhPT1lW2FdOyl7dCs9ZVthXTsrK2F9c2tpcFdzKCk7aWYoIj0iIT09ZVthXSlyZXR1cm4gbnVsbDsrK2E7c2tpcFdzKCk7Y29uc3QgaT1lW2FdO2lmKCciJyE9PWkmJiInIiE9PWkpcmV0dXJuIG51bGw7Y29uc3Qgcz1lLmluZGV4T2YoaSwrK2EpO2lmKHM8MClyZXR1cm4gbnVsbDtuPWUuc3Vic3RyaW5nKGEscyk7ci5wdXNoKHtuYW1lOnQsdmFsdWU6dGhpcy5fcmVzb2x2ZUVudGl0aWVzKG4pfSk7YT1zKzE7c2tpcFdzKCl9cmV0dXJue25hbWU6bixhdHRyaWJ1dGVzOnIscGFyc2VkOmEtdH19X3BhcnNlUHJvY2Vzc2luZ0luc3RydWN0aW9uKGUsdCl7bGV0IHI9dDtmb3IoO3I8ZS5sZW5ndGgmJiFpc1doaXRlc3BhY2UoZSxyKSYmIj4iIT09ZVtyXSYmIj8iIT09ZVtyXSYmIi8iIT09ZVtyXTspKytyO2NvbnN0IGE9ZS5zdWJzdHJpbmcodCxyKTshZnVuY3Rpb24gc2tpcFdzKCl7Zm9yKDtyPGUubGVuZ3RoJiZpc1doaXRlc3BhY2UoZSxyKTspKytyfSgpO2NvbnN0IG49cjtmb3IoO3I8ZS5sZW5ndGgmJigiPyIhPT1lW3JdfHwiPiIhPT1lW3IrMV0pOykrK3I7cmV0dXJue25hbWU6YSx2YWx1ZTplLnN1YnN0cmluZyhuLHIpLHBhcnNlZDpyLXR9fXBhcnNlWG1sKGUpe2xldCB0PTA7Zm9yKDt0PGUubGVuZ3RoOyl7bGV0IHI9dDtpZigiPCI9PT1lW3RdKXsrK3I7bGV0IHQ7c3dpdGNoKGVbcl0pe2Nhc2UiLyI6KytyO3Q9ZS5pbmRleE9mKCI+IixyKTtpZih0PDApe3RoaXMub25FcnJvcihPaSk7cmV0dXJufXRoaXMub25FbmRFbGVtZW50KGUuc3Vic3RyaW5nKHIsdCkpO3I9dCsxO2JyZWFrO2Nhc2UiPyI6KytyO2NvbnN0IGE9dGhpcy5fcGFyc2VQcm9jZXNzaW5nSW5zdHJ1Y3Rpb24oZSxyKTtpZigiPz4iIT09ZS5zdWJzdHJpbmcocithLnBhcnNlZCxyK2EucGFyc2VkKzIpKXt0aGlzLm9uRXJyb3IodmkpO3JldHVybn10aGlzLm9uUGkoYS5uYW1lLGEudmFsdWUpO3IrPWEucGFyc2VkKzI7YnJlYWs7Y2FzZSIhIjppZigiLS0iPT09ZS5zdWJzdHJpbmcocisxLHIrMykpe3Q9ZS5pbmRleE9mKCItLVx4M2UiLHIrMyk7aWYodDwwKXt0aGlzLm9uRXJyb3IoSWkpO3JldHVybn10aGlzLm9uQ29tbWVudChlLnN1YnN0cmluZyhyKzMsdCkpO3I9dCszfWVsc2UgaWYoIltDREFUQVsiPT09ZS5zdWJzdHJpbmcocisxLHIrOCkpe3Q9ZS5pbmRleE9mKCJdXT4iLHIrOCk7aWYodDwwKXt0aGlzLm9uRXJyb3IoQ2kpO3JldHVybn10aGlzLm9uQ2RhdGEoZS5zdWJzdHJpbmcocis4LHQpKTtyPXQrM31lbHNle2lmKCJET0NUWVBFIiE9PWUuc3Vic3RyaW5nKHIrMSxyKzgpKXt0aGlzLm9uRXJyb3IoVGkpO3JldHVybn17Y29uc3QgYT1lLmluZGV4T2YoIlsiLHIrOCk7bGV0IG49ITE7dD1lLmluZGV4T2YoIj4iLHIrOCk7aWYodDwwKXt0aGlzLm9uRXJyb3IoRmkpO3JldHVybn1pZihhPjAmJnQ+YSl7dD1lLmluZGV4T2YoIl0+IixyKzgpO2lmKHQ8MCl7dGhpcy5vbkVycm9yKEZpKTtyZXR1cm59bj0hMH1jb25zdCBpPWUuc3Vic3RyaW5nKHIrOCx0KyhuPzE6MCkpO3RoaXMub25Eb2N0eXBlKGkpO3I9dCsobj8yOjEpfX1icmVhaztkZWZhdWx0OmNvbnN0IG49dGhpcy5fcGFyc2VDb250ZW50KGUscik7aWYobnVsbD09PW4pe3RoaXMub25FcnJvcihUaSk7cmV0dXJufWxldCBpPSExO2lmKCIvPiI9PT1lLnN1YnN0cmluZyhyK24ucGFyc2VkLHIrbi5wYXJzZWQrMikpaT0hMDtlbHNlIGlmKCI+IiE9PWUuc3Vic3RyaW5nKHIrbi5wYXJzZWQscituLnBhcnNlZCsxKSl7dGhpcy5vbkVycm9yKE9pKTtyZXR1cm59dGhpcy5vbkJlZ2luRWxlbWVudChuLm5hbWUsbi5hdHRyaWJ1dGVzLGkpO3IrPW4ucGFyc2VkKyhpPzI6MSl9fWVsc2V7Zm9yKDtyPGUubGVuZ3RoJiYiPCIhPT1lW3JdOylyKys7Y29uc3QgYT1lLnN1YnN0cmluZyh0LHIpO3RoaXMub25UZXh0KHRoaXMuX3Jlc29sdmVFbnRpdGllcyhhKSl9dD1yfX1vblJlc29sdmVFbnRpdHkoZSl7cmV0dXJuYCYke2V9O2B9b25QaShlLHQpe31vbkNvbW1lbnQoZSl7fW9uQ2RhdGEoZSl7fW9uRG9jdHlwZShlKXt9b25UZXh0KGUpe31vbkJlZ2luRWxlbWVudChlLHQscil7fW9uRW5kRWxlbWVudChlKXt9b25FcnJvcihlKXt9fWNsYXNzIFNpbXBsZURPTU5vZGV7Y29uc3RydWN0b3IoZSx0KXt0aGlzLm5vZGVOYW1lPWU7dGhpcy5ub2RlVmFsdWU9dDtPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywicGFyZW50Tm9kZSIse3ZhbHVlOm51bGwsd3JpdGFibGU6ITB9KX1nZXQgZmlyc3RDaGlsZCgpe3JldHVybiB0aGlzLmNoaWxkTm9kZXM/LlswXX1nZXQgbmV4dFNpYmxpbmcoKXtjb25zdCBlPXRoaXMucGFyZW50Tm9kZS5jaGlsZE5vZGVzO2lmKCFlKXJldHVybjtjb25zdCB0PWUuaW5kZXhPZih0aGlzKTtyZXR1cm4tMSE9PXQ/ZVt0KzFdOnZvaWQgMH1nZXQgdGV4dENvbnRlbnQoKXtyZXR1cm4gdGhpcy5jaGlsZE5vZGVzP3RoaXMuY2hpbGROb2Rlcy5tYXAoZT0+ZS50ZXh0Q29udGVudCkuam9pbigiIik6dGhpcy5ub2RlVmFsdWV8fCIifWdldCBjaGlsZHJlbigpe3JldHVybiB0aGlzLmNoaWxkTm9kZXN8fFtdfWhhc0NoaWxkTm9kZXMoKXtyZXR1cm4gdGhpcy5jaGlsZE5vZGVzPy5sZW5ndGg+MH1zZWFyY2hOb2RlKGUsdCl7aWYodD49ZS5sZW5ndGgpcmV0dXJuIHRoaXM7Y29uc3Qgcj1lW3RdO2lmKHIubmFtZS5zdGFydHNXaXRoKCIjIikmJnQ8ZS5sZW5ndGgtMSlyZXR1cm4gdGhpcy5zZWFyY2hOb2RlKGUsdCsxKTtjb25zdCBhPVtdO2xldCBuPXRoaXM7Zm9yKDs7KXtpZihyLm5hbWU9PT1uLm5vZGVOYW1lKXtpZigwIT09ci5wb3Mpe2lmKDA9PT1hLmxlbmd0aClyZXR1cm4gbnVsbDt7Y29uc3RbaV09YS5wb3AoKTtsZXQgcz0wO2Zvcihjb25zdCBhIG9mIGkuY2hpbGROb2RlcylpZihyLm5hbWU9PT1hLm5vZGVOYW1lKXtpZihzPT09ci5wb3MpcmV0dXJuIGEuc2VhcmNoTm9kZShlLHQrMSk7cysrfXJldHVybiBuLnNlYXJjaE5vZGUoZSx0KzEpfX17Y29uc3Qgcj1uLnNlYXJjaE5vZGUoZSx0KzEpO2lmKG51bGwhPT1yKXJldHVybiByfX1pZihuLmNoaWxkTm9kZXM/Lmxlbmd0aD4wKXthLnB1c2goW24sMF0pO249bi5jaGlsZE5vZGVzWzBdfWVsc2V7aWYoMD09PWEubGVuZ3RoKXJldHVybiBudWxsO2Zvcig7MCE9PWEubGVuZ3RoOyl7Y29uc3RbZSx0XT1hLnBvcCgpLHI9dCsxO2lmKHI8ZS5jaGlsZE5vZGVzLmxlbmd0aCl7YS5wdXNoKFtlLHJdKTtuPWUuY2hpbGROb2Rlc1tyXTticmVha319aWYoMD09PWEubGVuZ3RoKXJldHVybiBudWxsfX19ZHVtcChlKXtpZigiI3RleHQiIT09dGhpcy5ub2RlTmFtZSl7ZS5wdXNoKGA8JHt0aGlzLm5vZGVOYW1lfWApO2lmKHRoaXMuYXR0cmlidXRlcylmb3IoY29uc3QgdCBvZiB0aGlzLmF0dHJpYnV0ZXMpZS5wdXNoKGAgJHt0Lm5hbWV9PSIke2VuY29kZVRvWG1sU3RyaW5nKHQudmFsdWUpfSJgKTtpZih0aGlzLmhhc0NoaWxkTm9kZXMoKSl7ZS5wdXNoKCI+Iik7Zm9yKGNvbnN0IHQgb2YgdGhpcy5jaGlsZE5vZGVzKXQuZHVtcChlKTtlLnB1c2goYDwvJHt0aGlzLm5vZGVOYW1lfT5gKX1lbHNlIHRoaXMubm9kZVZhbHVlP2UucHVzaChgPiR7ZW5jb2RlVG9YbWxTdHJpbmcodGhpcy5ub2RlVmFsdWUpfTwvJHt0aGlzLm5vZGVOYW1lfT5gKTplLnB1c2goIi8+Iil9ZWxzZSBlLnB1c2goZW5jb2RlVG9YbWxTdHJpbmcodGhpcy5ub2RlVmFsdWUpKX19Y2xhc3MgU2ltcGxlWE1MUGFyc2VyIGV4dGVuZHMgWE1MUGFyc2VyQmFzZXtjb25zdHJ1Y3Rvcih7aGFzQXR0cmlidXRlczplPSExLGxvd2VyQ2FzZU5hbWU6dD0hMX0pe3N1cGVyKCk7dGhpcy5fY3VycmVudEZyYWdtZW50PW51bGw7dGhpcy5fc3RhY2s9bnVsbDt0aGlzLl9lcnJvckNvZGU9a2k7dGhpcy5faGFzQXR0cmlidXRlcz1lO3RoaXMuX2xvd2VyQ2FzZU5hbWU9dH1wYXJzZUZyb21TdHJpbmcoZSl7dGhpcy5fY3VycmVudEZyYWdtZW50PVtdO3RoaXMuX3N0YWNrPVtdO3RoaXMuX2Vycm9yQ29kZT1raTt0aGlzLnBhcnNlWG1sKGUpO2lmKHRoaXMuX2Vycm9yQ29kZSE9PWtpKXJldHVybjtjb25zdFt0XT10aGlzLl9jdXJyZW50RnJhZ21lbnQ7cmV0dXJuIHQ/e2RvY3VtZW50RWxlbWVudDp0fTp2b2lkIDB9b25UZXh0KGUpe2lmKGZ1bmN0aW9uIGlzV2hpdGVzcGFjZVN0cmluZyhlKXtmb3IobGV0IHQ9MCxyPWUubGVuZ3RoO3Q8cjt0KyspaWYoIWlzV2hpdGVzcGFjZShlLHQpKXJldHVybiExO3JldHVybiEwfShlKSlyZXR1cm47Y29uc3QgdD1uZXcgU2ltcGxlRE9NTm9kZSgiI3RleHQiLGUpO3RoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKHQpfW9uQ2RhdGEoZSl7Y29uc3QgdD1uZXcgU2ltcGxlRE9NTm9kZSgiI3RleHQiLGUpO3RoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKHQpfW9uQmVnaW5FbGVtZW50KGUsdCxyKXt0aGlzLl9sb3dlckNhc2VOYW1lJiYoZT1lLnRvTG93ZXJDYXNlKCkpO2NvbnN0IGE9bmV3IFNpbXBsZURPTU5vZGUoZSk7YS5jaGlsZE5vZGVzPVtdO3RoaXMuX2hhc0F0dHJpYnV0ZXMmJihhLmF0dHJpYnV0ZXM9dCk7dGhpcy5fY3VycmVudEZyYWdtZW50LnB1c2goYSk7aWYoIXIpe3RoaXMuX3N0YWNrLnB1c2godGhpcy5fY3VycmVudEZyYWdtZW50KTt0aGlzLl9jdXJyZW50RnJhZ21lbnQ9YS5jaGlsZE5vZGVzfX1vbkVuZEVsZW1lbnQoZSl7dGhpcy5fY3VycmVudEZyYWdtZW50PXRoaXMuX3N0YWNrLnBvcCgpfHxbXTtjb25zdCB0PXRoaXMuX2N1cnJlbnRGcmFnbWVudC5hdCgtMSk7aWYoIXQpcmV0dXJuIG51bGw7Zm9yKGNvbnN0IGUgb2YgdC5jaGlsZE5vZGVzKWUucGFyZW50Tm9kZT10O3JldHVybiB0fW9uRXJyb3IoZSl7dGhpcy5fZXJyb3JDb2RlPWV9fWNsYXNzIE1ldGFkYXRhUGFyc2Vye2NvbnN0cnVjdG9yKGUpe2U9dGhpcy5fcmVwYWlyKGUpO2NvbnN0IHQ9bmV3IFNpbXBsZVhNTFBhcnNlcih7bG93ZXJDYXNlTmFtZTohMH0pLnBhcnNlRnJvbVN0cmluZyhlKTt0aGlzLl9tZXRhZGF0YU1hcD1uZXcgTWFwO3RoaXMuX2RhdGE9ZTt0JiZ0aGlzLl9wYXJzZSh0KX1fcmVwYWlyKGUpe3JldHVybiBlLnJlcGxhY2UoL15bXjxdKy8sIiIpLnJlcGxhY2VBbGwoLz5cXDM3NlxcMzc3KFtePF0rKS9nLGZ1bmN0aW9uKGUsdCl7Y29uc3Qgcj10LnJlcGxhY2VBbGwoL1xcKFswLTNdKShbMC03XSkoWzAtN10pL2csZnVuY3Rpb24oZSx0LHIsYSl7cmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoNjQqdCs4KnIrMSphKX0pLnJlcGxhY2VBbGwoLyYoYW1wfGFwb3N8Z3R8bHR8cXVvdCk7L2csZnVuY3Rpb24oZSx0KXtzd2l0Y2godCl7Y2FzZSJhbXAiOnJldHVybiImIjtjYXNlImFwb3MiOnJldHVybiInIjtjYXNlImd0IjpyZXR1cm4iPiI7Y2FzZSJsdCI6cmV0dXJuIjwiO2Nhc2UicXVvdCI6cmV0dXJuJyInfXRocm93IG5ldyBFcnJvcihgX3JlcGFpcjogJHt0fSBpc24ndCBkZWZpbmVkLmApfSksYT1bIj4iXTtmb3IobGV0IGU9MCx0PXIubGVuZ3RoO2U8dDtlKz0yKXtjb25zdCB0PTI1NipyLmNoYXJDb2RlQXQoZSkrci5jaGFyQ29kZUF0KGUrMSk7dD49MzImJnQ8MTI3JiY2MCE9PXQmJjYyIT09dCYmMzghPT10P2EucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKHQpKTphLnB1c2goIiYjeCIrKDY1NTM2K3QpLnRvU3RyaW5nKDE2KS5zdWJzdHJpbmcoMSkrIjsiKX1yZXR1cm4gYS5qb2luKCIiKX0pfV9nZXRTZXF1ZW5jZShlKXtjb25zdCB0PWUubm9kZU5hbWU7cmV0dXJuInJkZjpiYWciIT09dCYmInJkZjpzZXEiIT09dCYmInJkZjphbHQiIT09dD9udWxsOmUuY2hpbGROb2Rlcy5maWx0ZXIoZT0+InJkZjpsaSI9PT1lLm5vZGVOYW1lKX1fcGFyc2VBcnJheShlKXtpZighZS5oYXNDaGlsZE5vZGVzKCkpcmV0dXJuO2NvbnN0W3RdPWUuY2hpbGROb2RlcyxyPXRoaXMuX2dldFNlcXVlbmNlKHQpfHxbXTt0aGlzLl9tZXRhZGF0YU1hcC5zZXQoZS5ub2RlTmFtZSxyLm1hcChlPT5lLnRleHRDb250ZW50LnRyaW0oKSkpfV9wYXJzZShlKXtsZXQgdD1lLmRvY3VtZW50RWxlbWVudDtpZigicmRmOnJkZiIhPT10Lm5vZGVOYW1lKXt0PXQuZmlyc3RDaGlsZDtmb3IoO3QmJiJyZGY6cmRmIiE9PXQubm9kZU5hbWU7KXQ9dC5uZXh0U2libGluZ31pZih0JiYicmRmOnJkZiI9PT10Lm5vZGVOYW1lJiZ0Lmhhc0NoaWxkTm9kZXMoKSlmb3IoY29uc3QgZSBvZiB0LmNoaWxkTm9kZXMpaWYoInJkZjpkZXNjcmlwdGlvbiI9PT1lLm5vZGVOYW1lKWZvcihjb25zdCB0IG9mIGUuY2hpbGROb2Rlcyl7Y29uc3QgZT10Lm5vZGVOYW1lO3N3aXRjaChlKXtjYXNlIiN0ZXh0Ijpjb250aW51ZTtjYXNlImRjOmNyZWF0b3IiOmNhc2UiZGM6c3ViamVjdCI6dGhpcy5fcGFyc2VBcnJheSh0KTtjb250aW51ZX10aGlzLl9tZXRhZGF0YU1hcC5zZXQoZSx0LnRleHRDb250ZW50LnRyaW0oKSl9fWdldCBzZXJpYWxpemFibGUoKXtyZXR1cm57cGFyc2VkRGF0YTp0aGlzLl9tZXRhZGF0YU1hcCxyYXdEYXRhOnRoaXMuX2RhdGF9fX1jb25zdCBNaT0xLERpPTIsQmk9MyxSaT00LEVpPTU7Y2xhc3MgU3RydWN0VHJlZVJvb3R7Y29uc3RydWN0b3IoZSx0LHIpe3RoaXMueHJlZj1lO3RoaXMuZGljdD10O3RoaXMucmVmPXIgaW5zdGFuY2VvZiBSZWY/cjpudWxsO3RoaXMucm9sZU1hcD1uZXcgTWFwO3RoaXMuc3RydWN0UGFyZW50SWRzPW51bGx9aW5pdCgpe3RoaXMucmVhZFJvbGVNYXAoKX0jY2UoZSx0LHIpe2lmKCEoZSBpbnN0YW5jZW9mIFJlZil8fHQ8MClyZXR1cm47dGhpcy5zdHJ1Y3RQYXJlbnRJZHN8fD1uZXcgUmVmU2V0Q2FjaGU7bGV0IGE9dGhpcy5zdHJ1Y3RQYXJlbnRJZHMuZ2V0KGUpO2lmKCFhKXthPVtdO3RoaXMuc3RydWN0UGFyZW50SWRzLnB1dChlLGEpfWEucHVzaChbdCxyXSl9YWRkQW5ub3RhdGlvbklkVG9QYWdlKGUsdCl7dGhpcy4jY2UoZSx0LFJpKX1yZWFkUm9sZU1hcCgpe2NvbnN0IGU9dGhpcy5kaWN0LmdldCgiUm9sZU1hcCIpO2lmKGUgaW5zdGFuY2VvZiBEaWN0KWZvcihjb25zdFt0LHJdb2YgZSlyIGluc3RhbmNlb2YgTmFtZSYmdGhpcy5yb2xlTWFwLnNldCh0LHIubmFtZSl9c3RhdGljIGFzeW5jIGNhbkNyZWF0ZVN0cnVjdHVyZVRyZWUoe2NhdGFsb2dSZWY6ZSxwZGZNYW5hZ2VyOnQsbmV3QW5ub3RhdGlvbnNCeVBhZ2U6cn0pe2lmKCEoZSBpbnN0YW5jZW9mIFJlZikpe3dhcm4oIkNhbm5vdCBzYXZlIHRoZSBzdHJ1Y3QgdHJlZTogbm8gY2F0YWxvZyByZWZlcmVuY2UuIik7cmV0dXJuITF9bGV0IGE9MCxuPSEwO2Zvcihjb25zdFtlLGldb2Ygcil7Y29uc3R7cmVmOnJ9PWF3YWl0IHQuZ2V0UGFnZShlKTtpZighKHIgaW5zdGFuY2VvZiBSZWYpKXt3YXJuKGBDYW5ub3Qgc2F2ZSB0aGUgc3RydWN0IHRyZWU6IHBhZ2UgJHtlfSBoYXMgbm8gcmVmLmApO249ITA7YnJlYWt9Zm9yKGNvbnN0IGUgb2YgaSlpZihlLmFjY2Vzc2liaWxpdHlEYXRhPy50eXBlKXtlLnBhcmVudFRyZWVJZD1hKys7bj0hMX19aWYobil7Zm9yKGNvbnN0IGUgb2Ygci52YWx1ZXMoKSlmb3IoY29uc3QgdCBvZiBlKWRlbGV0ZSB0LnBhcmVudFRyZWVJZDtyZXR1cm4hMX1yZXR1cm4hMH1zdGF0aWMgYXN5bmMgY3JlYXRlU3RydWN0dXJlVHJlZSh7bmV3QW5ub3RhdGlvbnNCeVBhZ2U6ZSx4cmVmOnQsY2F0YWxvZ1JlZjpyLHBkZk1hbmFnZXI6YSxjaGFuZ2VzOm59KXtjb25zdCBpPWF3YWl0IGEuZW5zdXJlQ2F0YWxvZygiY2xvbmVEaWN0Iikscz1uZXcgUmVmU2V0Q2FjaGU7cy5wdXQocixpKTtjb25zdCBvPXQuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7aS5zZXQoIlN0cnVjdFRyZWVSb290IixvKTtjb25zdCBjPW5ldyBEaWN0KHQpO2Muc2V0KCJUeXBlIixOYW1lLmdldCgiU3RydWN0VHJlZVJvb3QiKSk7Y29uc3QgbD10LmdldE5ld1RlbXBvcmFyeVJlZigpO2Muc2V0KCJQYXJlbnRUcmVlIixsKTtjb25zdCBoPVtdO2Muc2V0KCJLIixoKTtzLnB1dChvLGMpO2NvbnN0IHU9bmV3IERpY3QodCksZD1bXTt1LnNldCgiTnVtcyIsZCk7Y29uc3QgZj1hd2FpdCB0aGlzLiNsZSh7bmV3QW5ub3RhdGlvbnNCeVBhZ2U6ZSxzdHJ1Y3RUcmVlUm9vdFJlZjpvLHN0cnVjdFRyZWVSb290Om51bGwsa2lkczpoLG51bXM6ZCx4cmVmOnQscGRmTWFuYWdlcjphLGNoYW5nZXM6bixjYWNoZTpzfSk7Yy5zZXQoIlBhcmVudFRyZWVOZXh0S2V5IixmKTtzLnB1dChsLHUpO2Zvcihjb25zdFtlLHRdb2Ygcy5pdGVtcygpKW4ucHV0KGUse2RhdGE6dH0pfWFzeW5jIGNhblVwZGF0ZVN0cnVjdFRyZWUoe3BkZk1hbmFnZXI6ZSxuZXdBbm5vdGF0aW9uc0J5UGFnZTp0fSl7aWYoIXRoaXMucmVmKXt3YXJuKCJDYW5ub3QgdXBkYXRlIHRoZSBzdHJ1Y3QgdHJlZTogbm8gcm9vdCByZWZlcmVuY2UuIik7cmV0dXJuITF9bGV0IHI9dGhpcy5kaWN0LmdldCgiUGFyZW50VHJlZU5leHRLZXkiKTtpZighTnVtYmVyLmlzSW50ZWdlcihyKXx8cjwwKXt3YXJuKCJDYW5ub3QgdXBkYXRlIHRoZSBzdHJ1Y3QgdHJlZTogaW52YWxpZCBuZXh0IGtleS4iKTtyZXR1cm4hMX1jb25zdCBhPXRoaXMuZGljdC5nZXQoIlBhcmVudFRyZWUiKTtpZighKGEgaW5zdGFuY2VvZiBEaWN0KSl7d2FybigiQ2Fubm90IHVwZGF0ZSB0aGUgc3RydWN0IHRyZWU6IFBhcmVudFRyZWUgaXNuJ3QgYSBkaWN0LiIpO3JldHVybiExfWNvbnN0IG49YS5nZXQoIk51bXMiKTtpZighQXJyYXkuaXNBcnJheShuKSl7d2FybigiQ2Fubm90IHVwZGF0ZSB0aGUgc3RydWN0IHRyZWU6IG51bXMgaXNuJ3QgYW4gYXJyYXkuIik7cmV0dXJuITF9Y29uc3QgaT1uZXcgTnVtYmVyVHJlZShhLHRoaXMueHJlZik7Zm9yKGNvbnN0IHIgb2YgdC5rZXlzKCkpe2NvbnN0e3BhZ2VEaWN0OnR9PWF3YWl0IGUuZ2V0UGFnZShyKTtpZighdC5oYXMoIlN0cnVjdFBhcmVudHMiKSljb250aW51ZTtjb25zdCBhPXQuZ2V0KCJTdHJ1Y3RQYXJlbnRzIik7aWYoIU51bWJlci5pc0ludGVnZXIoYSl8fCFBcnJheS5pc0FycmF5KGkuZ2V0KGEpKSl7d2FybihgQ2Fubm90IHNhdmUgdGhlIHN0cnVjdCB0cmVlOiBwYWdlICR7cn0gaGFzIGEgd3JvbmcgaWQuYCk7cmV0dXJuITF9fWxldCBzPSEwO2Zvcihjb25zdFthLG5db2YgdCl7Y29uc3R7cGFnZURpY3Q6dH09YXdhaXQgZS5nZXRQYWdlKGEpO1N0cnVjdFRyZWVSb290LiNoZSh7ZWxlbWVudHM6bix4cmVmOnRoaXMueHJlZixwYWdlRGljdDp0LG51bWJlclRyZWU6aX0pO2Zvcihjb25zdCBlIG9mIG4paWYoZS5hY2Nlc3NpYmlsaXR5RGF0YT8udHlwZSl7ZS5hY2Nlc3NpYmlsaXR5RGF0YS5zdHJ1Y3RQYXJlbnQ+PTB8fChlLnBhcmVudFRyZWVJZD1yKyspO3M9ITF9fWlmKHMpe2Zvcihjb25zdCBlIG9mIHQudmFsdWVzKCkpZm9yKGNvbnN0IHQgb2YgZSl7ZGVsZXRlIHQucGFyZW50VHJlZUlkO2RlbGV0ZSB0LnN0cnVjdFRyZWVQYXJlbnR9cmV0dXJuITF9cmV0dXJuITB9YXN5bmMgdXBkYXRlU3RydWN0dXJlVHJlZSh7bmV3QW5ub3RhdGlvbnNCeVBhZ2U6ZSxwZGZNYW5hZ2VyOnQsY2hhbmdlczpyfSl7Y29uc3R7cmVmOmEseHJlZjpufT10aGlzLGk9dGhpcy5kaWN0LmNsb25lKCkscz1uZXcgUmVmU2V0Q2FjaGU7cy5wdXQoYSxpKTtsZXQgbyxjPWkuZ2V0UmF3KCJQYXJlbnRUcmVlIik7aWYoYyBpbnN0YW5jZW9mIFJlZilvPW4uZmV0Y2goYyk7ZWxzZXtvPWM7Yz1uLmdldE5ld1RlbXBvcmFyeVJlZigpO2kuc2V0KCJQYXJlbnRUcmVlIixjKX1vPW8uY2xvbmUoKTtzLnB1dChjLG8pO2xldCBsPW8uZ2V0UmF3KCJOdW1zIiksaD1udWxsO2lmKGwgaW5zdGFuY2VvZiBSZWYpe2g9bDtsPW4uZmV0Y2goaCl9bD1sLnNsaWNlKCk7aHx8by5zZXQoIk51bXMiLGwpO2NvbnN0IHU9YXdhaXQgU3RydWN0VHJlZVJvb3QuI2xlKHtuZXdBbm5vdGF0aW9uc0J5UGFnZTplLHN0cnVjdFRyZWVSb290UmVmOmEsc3RydWN0VHJlZVJvb3Q6dGhpcyxraWRzOm51bGwsbnVtczpsLHhyZWY6bixwZGZNYW5hZ2VyOnQsY2hhbmdlczpyLGNhY2hlOnN9KTtpZigtMSE9PXUpe2kuc2V0KCJQYXJlbnRUcmVlTmV4dEtleSIsdSk7aCYmcy5wdXQoaCxsKTtmb3IoY29uc3RbZSx0XW9mIHMuaXRlbXMoKSlyLnB1dChlLHtkYXRhOnR9KX19c3RhdGljIGFzeW5jI2xlKHtuZXdBbm5vdGF0aW9uc0J5UGFnZTplLHN0cnVjdFRyZWVSb290UmVmOnQsc3RydWN0VHJlZVJvb3Q6cixraWRzOmEsbnVtczpuLHhyZWY6aSxwZGZNYW5hZ2VyOnMsY2hhbmdlczpvLGNhY2hlOmN9KXtjb25zdCBsPU5hbWUuZ2V0KCJPQkpSIik7bGV0IGgsdT0tMTtmb3IoY29uc3RbZCxmXW9mIGUpe2NvbnN0IGU9YXdhaXQgcy5nZXRQYWdlKGQpLHtyZWY6Z309ZSxwPWcgaW5zdGFuY2VvZiBSZWY7Zm9yKGNvbnN0e2FjY2Vzc2liaWxpdHlEYXRhOnMscmVmOm0scGFyZW50VHJlZUlkOmIsc3RydWN0VHJlZVBhcmVudDp5fW9mIGYpe2lmKCFzPy50eXBlKWNvbnRpbnVlO2NvbnN0e3N0cnVjdFBhcmVudDpmfT1zO2lmKHImJk51bWJlci5pc0ludGVnZXIoZikmJmY+PTApe2xldCB0PShofHw9bmV3IE1hcCkuZ2V0KGQpO2lmKHZvaWQgMD09PXQpe3Q9bmV3IFN0cnVjdFRyZWVQYWdlKHIsZS5wYWdlRGljdCkuY29sbGVjdE9iamVjdHMoZyk7aC5zZXQoZCx0KX1jb25zdCBhPXQ/LmdldChmKTtpZihhKXtjb25zdCBlPWkuZmV0Y2goYSkuY2xvbmUoKTtTdHJ1Y3RUcmVlUm9vdC4jdWUoZSxzKTtvLnB1dChhLHtkYXRhOmV9KTtjb250aW51ZX19dT1NYXRoLm1heCh1LGIpO2NvbnN0IHc9aS5nZXROZXdUZW1wb3JhcnlSZWYoKSx4PW5ldyBEaWN0KGkpO1N0cnVjdFRyZWVSb290LiN1ZSh4LHMpO2F3YWl0IHRoaXMuI2RlKHtzdHJ1Y3RUcmVlUGFyZW50OnksdGFnRGljdDp4LG5ld1RhZ1JlZjp3LHN0cnVjdFRyZWVSb290UmVmOnQsZmFsbGJhY2tLaWRzOmEseHJlZjppLGNhY2hlOmN9KTtjb25zdCBTPW5ldyBEaWN0KGkpO3guc2V0KCJLIixTKTtTLnNldCgiVHlwZSIsbCk7cCYmUy5zZXQoIlBnIixnKTtTLnNldCgiT2JqIixtKTtjLnB1dCh3LHgpO24ucHVzaChiLHcpfX1yZXR1cm4gdSsxfXN0YXRpYyN1ZShlLHt0eXBlOnQsdGl0bGU6cixsYW5nOmEsYWx0Om4sZXhwYW5kZWQ6aSxhY3R1YWxUZXh0OnN9KXtlLnNldCgiUyIsTmFtZS5nZXQodCkpO3ImJmUuc2V0KCJUIixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKHIpKTthJiZlLnNldCgiTGFuZyIsc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShhKSk7biYmZS5zZXQoIkFsdCIsc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShuKSk7aSYmZS5zZXQoIkUiLHN0cmluZ1RvQXNjaWlPclVURjE2QkUoaSkpO3MmJmUuc2V0KCJBY3R1YWxUZXh0IixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKHMpKX1zdGF0aWMjaGUoe2VsZW1lbnRzOmUseHJlZjp0LHBhZ2VEaWN0OnIsbnVtYmVyVHJlZTphfSl7Y29uc3Qgbj1uZXcgTWFwO2Zvcihjb25zdCB0IG9mIGUpaWYodC5zdHJ1Y3RUcmVlUGFyZW50SWQpe2NvbnN0IGU9cGFyc2VJbnQodC5zdHJ1Y3RUcmVlUGFyZW50SWQuc3BsaXQoIl9tYyIpWzFdLDEwKTtsZXQgcj1uLmdldChlKTtpZighcil7cj1bXTtuLnNldChlLHIpfXIucHVzaCh0KX1jb25zdCBpPXIuZ2V0KCJTdHJ1Y3RQYXJlbnRzIik7aWYoIU51bWJlci5pc0ludGVnZXIoaSkpcmV0dXJuO2NvbnN0IHM9YS5nZXQoaSksdXBkYXRlRWxlbWVudD0oZSxyLGEpPT57Y29uc3QgaT1uLmdldChlKTtpZihpKXtjb25zdCBlPXIuZ2V0UmF3KCJQIiksbj10LmZldGNoSWZSZWYoZSk7aWYoZSBpbnN0YW5jZW9mIFJlZiYmbiBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IGU9e3JlZjphLGRpY3Q6cn07Zm9yKGNvbnN0IHQgb2YgaSl0LnN0cnVjdFRyZWVQYXJlbnQ9ZX1yZXR1cm4hMH1yZXR1cm4hMX07Zm9yKGNvbnN0IGUgb2Ygcyl7aWYoIShlIGluc3RhbmNlb2YgUmVmKSljb250aW51ZTtjb25zdCByPXQuZmV0Y2goZSksYT1yLmdldCgiSyIpO2lmKE51bWJlci5pc0ludGVnZXIoYSkpdXBkYXRlRWxlbWVudChhLHIsZSk7ZWxzZSBpZihBcnJheS5pc0FycmF5KGEpKWZvcihsZXQgbiBvZiBhKXtuPXQuZmV0Y2hJZlJlZihuKTtpZihOdW1iZXIuaXNJbnRlZ2VyKG4pJiZ1cGRhdGVFbGVtZW50KG4scixlKSlicmVhaztpZighKG4gaW5zdGFuY2VvZiBEaWN0KSljb250aW51ZTtpZighaXNOYW1lKG4uZ2V0KCJUeXBlIiksIk1DUiIpKWJyZWFrO2NvbnN0IGE9bi5nZXQoIk1DSUQiKTtpZihOdW1iZXIuaXNJbnRlZ2VyKGEpJiZ1cGRhdGVFbGVtZW50KGEscixlKSlicmVha319fXN0YXRpYyBhc3luYyNkZSh7c3RydWN0VHJlZVBhcmVudDplLHRhZ0RpY3Q6dCxuZXdUYWdSZWY6cixzdHJ1Y3RUcmVlUm9vdFJlZjphLGZhbGxiYWNrS2lkczpuLHhyZWY6aSxjYWNoZTpzfSl7bGV0IG8sYz1udWxsO2lmKGUpeyh7cmVmOmN9PWUpO289ZS5kaWN0LmdldFJhdygiUCIpfHxhfWVsc2Ugbz1hO3Quc2V0KCJQIixvKTtjb25zdCBsPWkuZmV0Y2hJZlJlZihvKTtpZighbCl7bi5wdXNoKHIpO3JldHVybn1sZXQgaD1zLmdldChvKTtpZighaCl7aD1sLmNsb25lKCk7cy5wdXQobyxoKX1jb25zdCB1PWguZ2V0UmF3KCJLIik7bGV0IGQ9dSBpbnN0YW5jZW9mIFJlZj9zLmdldCh1KTpudWxsO2lmKCFkKXtkPWkuZmV0Y2hJZlJlZih1KTtkPUFycmF5LmlzQXJyYXkoZCk/ZC5zbGljZSgpOlt1XTtjb25zdCBlPWkuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7aC5zZXQoIksiLGUpO3MucHV0KGUsZCl9Y29uc3QgZj1kLmluZGV4T2YoYyk7ZC5zcGxpY2UoZj49MD9mKzE6ZC5sZW5ndGgsMCxyKX19Y2xhc3MgU3RydWN0RWxlbWVudE5vZGV7Y29uc3RydWN0b3IoZSx0KXt0aGlzLnRyZWU9ZTt0aGlzLnhyZWY9ZS54cmVmO3RoaXMuZGljdD10O3RoaXMua2lkcz1bXTt0aGlzLnBhcnNlS2lkcygpfWdldCByb2xlKCl7Y29uc3QgZT10aGlzLmRpY3QuZ2V0KCJTIiksdD1lIGluc3RhbmNlb2YgTmFtZT9lLm5hbWU6IiIse3Jvb3Q6cn09dGhpcy50cmVlO3JldHVybiByLnJvbGVNYXAuZ2V0KHQpPz90fXBhcnNlS2lkcygpe2xldCBlPW51bGw7Y29uc3QgdD10aGlzLmRpY3QuZ2V0UmF3KCJQZyIpO3QgaW5zdGFuY2VvZiBSZWYmJihlPXQudG9TdHJpbmcoKSk7Y29uc3Qgcj10aGlzLmRpY3QuZ2V0KCJLIik7aWYoQXJyYXkuaXNBcnJheShyKSlmb3IoY29uc3QgdCBvZiByKXtjb25zdCByPXRoaXMucGFyc2VLaWQoZSx0aGlzLnhyZWYuZmV0Y2hJZlJlZih0KSk7ciYmdGhpcy5raWRzLnB1c2gocil9ZWxzZXtjb25zdCB0PXRoaXMucGFyc2VLaWQoZSxyKTt0JiZ0aGlzLmtpZHMucHVzaCh0KX19cGFyc2VLaWQoZSx0KXtpZihOdW1iZXIuaXNJbnRlZ2VyKHQpKXJldHVybiB0aGlzLnRyZWUucGFnZURpY3Qub2JqSWQhPT1lP251bGw6bmV3IFN0cnVjdEVsZW1lbnQoe3R5cGU6TWksbWNpZDp0LHBhZ2VPYmpJZDplfSk7aWYoISh0IGluc3RhbmNlb2YgRGljdCkpcmV0dXJuIG51bGw7Y29uc3Qgcj10LmdldFJhdygiUGciKTtyIGluc3RhbmNlb2YgUmVmJiYoZT1yLnRvU3RyaW5nKCkpO2NvbnN0IGE9dC5nZXQoIlR5cGUiKWluc3RhbmNlb2YgTmFtZT90LmdldCgiVHlwZSIpLm5hbWU6bnVsbDtpZigiTUNSIj09PWEpe2lmKHRoaXMudHJlZS5wYWdlRGljdC5vYmpJZCE9PWUpcmV0dXJuIG51bGw7Y29uc3Qgcj10LmdldFJhdygiU3RtIik7cmV0dXJuIG5ldyBTdHJ1Y3RFbGVtZW50KHt0eXBlOkRpLHJlZk9iaklkOnIgaW5zdGFuY2VvZiBSZWY/ci50b1N0cmluZygpOm51bGwscGFnZU9iaklkOmUsbWNpZDp0LmdldCgiTUNJRCIpfSl9aWYoIk9CSlIiPT09YSl7aWYodGhpcy50cmVlLnBhZ2VEaWN0Lm9iaklkIT09ZSlyZXR1cm4gbnVsbDtjb25zdCByPXQuZ2V0UmF3KCJPYmoiKTtyZXR1cm4gbmV3IFN0cnVjdEVsZW1lbnQoe3R5cGU6QmkscmVmT2JqSWQ6ciBpbnN0YW5jZW9mIFJlZj9yLnRvU3RyaW5nKCk6bnVsbCxwYWdlT2JqSWQ6ZX0pfXJldHVybiBuZXcgU3RydWN0RWxlbWVudCh7dHlwZTpFaSxkaWN0OnR9KX19Y2xhc3MgU3RydWN0RWxlbWVudHtjb25zdHJ1Y3Rvcih7dHlwZTplLGRpY3Q6dD1udWxsLG1jaWQ6cj1udWxsLHBhZ2VPYmpJZDphPW51bGwscmVmT2JqSWQ6bj1udWxsfSl7dGhpcy50eXBlPWU7dGhpcy5kaWN0PXQ7dGhpcy5tY2lkPXI7dGhpcy5wYWdlT2JqSWQ9YTt0aGlzLnJlZk9iaklkPW47dGhpcy5wYXJlbnROb2RlPW51bGx9fWNsYXNzIFN0cnVjdFRyZWVQYWdle2NvbnN0cnVjdG9yKGUsdCl7dGhpcy5yb290PWU7dGhpcy54cmVmPWU/LnhyZWY/P251bGw7dGhpcy5yb290RGljdD1lPy5kaWN0Pz9udWxsO3RoaXMucGFnZURpY3Q9dDt0aGlzLm5vZGVzPVtdfWNvbGxlY3RPYmplY3RzKGUpe2lmKCEodGhpcy5yb290JiZ0aGlzLnJvb3REaWN0JiZlIGluc3RhbmNlb2YgUmVmKSlyZXR1cm4gbnVsbDtjb25zdCB0PXRoaXMucm9vdERpY3QuZ2V0KCJQYXJlbnRUcmVlIik7aWYoIXQpcmV0dXJuIG51bGw7Y29uc3Qgcj10aGlzLnJvb3Quc3RydWN0UGFyZW50SWRzPy5nZXQoZSk7aWYoIXIpcmV0dXJuIG51bGw7Y29uc3QgYT1uZXcgTWFwLG49bmV3IE51bWJlclRyZWUodCx0aGlzLnhyZWYpO2Zvcihjb25zdFtlXW9mIHIpe2NvbnN0IHQ9bi5nZXRSYXcoZSk7dCBpbnN0YW5jZW9mIFJlZiYmYS5zZXQoZSx0KX1yZXR1cm4gYX1wYXJzZShlKXtpZighKHRoaXMucm9vdCYmdGhpcy5yb290RGljdCYmZSBpbnN0YW5jZW9mIFJlZikpcmV0dXJuO2NvbnN0IHQ9dGhpcy5yb290RGljdC5nZXQoIlBhcmVudFRyZWUiKTtpZighdClyZXR1cm47Y29uc3Qgcj10aGlzLnBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpLGE9dGhpcy5yb290LnN0cnVjdFBhcmVudElkcz8uZ2V0KGUpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHIpJiYhYSlyZXR1cm47Y29uc3Qgbj1uZXcgTWFwLGk9bmV3IE51bWJlclRyZWUodCx0aGlzLnhyZWYpO2lmKE51bWJlci5pc0ludGVnZXIocikpe2NvbnN0IGU9aS5nZXQocik7aWYoQXJyYXkuaXNBcnJheShlKSlmb3IoY29uc3QgdCBvZiBlKXQgaW5zdGFuY2VvZiBSZWYmJnRoaXMuYWRkTm9kZSh0aGlzLnhyZWYuZmV0Y2godCksbil9aWYoYSlmb3IoY29uc3RbZSx0XW9mIGEpe2NvbnN0IHI9aS5nZXQoZSk7aWYocil7Y29uc3QgZT10aGlzLmFkZE5vZGUodGhpcy54cmVmLmZldGNoSWZSZWYociksbik7MT09PWU/LmtpZHM/Lmxlbmd0aCYmZS5raWRzWzBdLnR5cGU9PT1CaSYmKGUua2lkc1swXS50eXBlPXQpfX19YWRkTm9kZShlLHQscj0wKXtpZihyPjQwKXt3YXJuKCJTdHJ1Y3RUcmVlIE1BWF9ERVBUSCByZWFjaGVkLiIpO3JldHVybiBudWxsfWlmKCEoZSBpbnN0YW5jZW9mIERpY3QpKXJldHVybiBudWxsO2lmKHQuaGFzKGUpKXJldHVybiB0LmdldChlKTtjb25zdCBhPW5ldyBTdHJ1Y3RFbGVtZW50Tm9kZSh0aGlzLGUpO3Quc2V0KGUsYSk7Y29uc3Qgbj1lLmdldCgiUCIpO2lmKCEobiBpbnN0YW5jZW9mIERpY3QpfHxpc05hbWUobi5nZXQoIlR5cGUiKSwiU3RydWN0VHJlZVJvb3QiKSl7dGhpcy5hZGRUb3BMZXZlbE5vZGUoZSxhKXx8dC5kZWxldGUoZSk7cmV0dXJuIGF9Y29uc3QgaT10aGlzLmFkZE5vZGUobix0LHIrMSk7aWYoIWkpcmV0dXJuIGE7bGV0IHM9ITE7Zm9yKGNvbnN0IHQgb2YgaS5raWRzKWlmKHQudHlwZT09PUVpJiZ0LmRpY3Q9PT1lKXt0LnBhcmVudE5vZGU9YTtzPSEwfXN8fHQuZGVsZXRlKGUpO3JldHVybiBhfWFkZFRvcExldmVsTm9kZShlLHQpe2NvbnN0IHI9dGhpcy5yb290RGljdC5nZXQoIksiKTtpZighcilyZXR1cm4hMTtpZihyIGluc3RhbmNlb2YgRGljdCl7aWYoci5vYmpJZCE9PWUub2JqSWQpcmV0dXJuITE7dGhpcy5ub2Rlc1swXT10O3JldHVybiEwfWlmKCFBcnJheS5pc0FycmF5KHIpKXJldHVybiEwO2xldCBhPSExO2ZvcihsZXQgbj0wO248ci5sZW5ndGg7bisrKXtjb25zdCBpPXJbbl07aWYoaT8udG9TdHJpbmcoKT09PWUub2JqSWQpe3RoaXMubm9kZXNbbl09dDthPSEwfX1yZXR1cm4gYX1nZXQgc2VyaWFsaXphYmxlKCl7ZnVuY3Rpb24gbm9kZVRvU2VyaWFsaXphYmxlKGUsdCxyPTApe2lmKHI+NDApe3dhcm4oIlN0cnVjdFRyZWUgdG9vIGRlZXAgdG8gYmUgZnVsbHkgc2VyaWFsaXplZC4iKTtyZXR1cm59Y29uc3QgYT1PYmplY3QuY3JlYXRlKG51bGwpO2Eucm9sZT1lLnJvbGU7YS5jaGlsZHJlbj1bXTt0LmNoaWxkcmVuLnB1c2goYSk7bGV0IG49ZS5kaWN0LmdldCgiQWx0Iik7InN0cmluZyIhPXR5cGVvZiBuJiYobj1lLmRpY3QuZ2V0KCJBY3R1YWxUZXh0IikpOyJzdHJpbmciPT10eXBlb2YgbiYmKGEuYWx0PXN0cmluZ1RvUERGU3RyaW5nKG4pKTtjb25zdCBpPWUuZGljdC5nZXQoIkEiKTtpZihpIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgZT1sb29rdXBOb3JtYWxSZWN0KGkuZ2V0QXJyYXkoIkJCb3giKSxudWxsKTtpZihlKWEuYmJveD1lO2Vsc2V7Y29uc3QgZT1pLmdldCgiV2lkdGgiKSx0PWkuZ2V0KCJIZWlnaHQiKTsibnVtYmVyIj09dHlwZW9mIGUmJmU+MCYmIm51bWJlciI9PXR5cGVvZiB0JiZ0PjAmJihhLmJib3g9WzAsMCxlLHRdKX19Y29uc3Qgcz1lLmRpY3QuZ2V0KCJMYW5nIik7InN0cmluZyI9PXR5cGVvZiBzJiYoYS5sYW5nPXN0cmluZ1RvUERGU3RyaW5nKHMpKTtmb3IoY29uc3QgdCBvZiBlLmtpZHMpe2NvbnN0IGU9dC50eXBlPT09RWk/dC5wYXJlbnROb2RlOm51bGw7ZT9ub2RlVG9TZXJpYWxpemFibGUoZSxhLHIrMSk6dC50eXBlPT09TWl8fHQudHlwZT09PURpP2EuY2hpbGRyZW4ucHVzaCh7dHlwZToiY29udGVudCIsaWQ6YHAke3QucGFnZU9iaklkfV9tYyR7dC5tY2lkfWB9KTp0LnR5cGU9PT1CaT9hLmNoaWxkcmVuLnB1c2goe3R5cGU6Im9iamVjdCIsaWQ6dC5yZWZPYmpJZH0pOnQudHlwZT09PVJpJiZhLmNoaWxkcmVuLnB1c2goe3R5cGU6ImFubm90YXRpb24iLGlkOmBwZGZqc19pbnRlcm5hbF9pZF8ke3QucmVmT2JqSWR9YH0pfX1jb25zdCBlPU9iamVjdC5jcmVhdGUobnVsbCk7ZS5jaGlsZHJlbj1bXTtlLnJvbGU9IlJvb3QiO2Zvcihjb25zdCB0IG9mIHRoaXMubm9kZXMpdCYmbm9kZVRvU2VyaWFsaXphYmxlKHQsZSk7cmV0dXJuIGV9fWNvbnN0IE5pPWZ1bmN0aW9uIF9pc1ZhbGlkRXhwbGljaXREZXN0KGUsdCxyKXtpZighQXJyYXkuaXNBcnJheShyKXx8ci5sZW5ndGg8MilyZXR1cm4hMTtjb25zdFthLG4sLi4uaV09cjtpZighZShhKSYmIU51bWJlci5pc0ludGVnZXIoYSkpcmV0dXJuITE7aWYoIXQobikpcmV0dXJuITE7Y29uc3Qgcz1pLmxlbmd0aDtsZXQgbz0hMDtzd2l0Y2gobi5uYW1lKXtjYXNlIlhZWiI6aWYoczwyfHxzPjMpcmV0dXJuITE7YnJlYWs7Y2FzZSJGaXQiOmNhc2UiRml0QiI6cmV0dXJuIDA9PT1zO2Nhc2UiRml0SCI6Y2FzZSJGaXRCSCI6Y2FzZSJGaXRWIjpjYXNlIkZpdEJWIjppZihzPjEpcmV0dXJuITE7YnJlYWs7Y2FzZSJGaXRSIjppZig0IT09cylyZXR1cm4hMTtvPSExO2JyZWFrO2RlZmF1bHQ6cmV0dXJuITF9Zm9yKGNvbnN0IGUgb2YgaSlpZighKCJudW1iZXIiPT10eXBlb2YgZXx8byYmbnVsbD09PWUpKXJldHVybiExO3JldHVybiEwfS5iaW5kKG51bGwsZT0+ZSBpbnN0YW5jZW9mIFJlZixpc05hbWUpO2Z1bmN0aW9uIGZldGNoRGVzdChlKXtlIGluc3RhbmNlb2YgRGljdCYmKGU9ZS5nZXQoIkQiKSk7cmV0dXJuIE5pKGUpP2U6bnVsbH1mdW5jdGlvbiBmZXRjaFJlbW90ZURlc3QoZSl7bGV0IHQ9ZS5nZXQoIkQiKTtpZih0KXt0IGluc3RhbmNlb2YgTmFtZSYmKHQ9dC5uYW1lKTtpZigic3RyaW5nIj09dHlwZW9mIHQpcmV0dXJuIHN0cmluZ1RvUERGU3RyaW5nKHQsITApO2lmKE5pKHQpKXJldHVybiBKU09OLnN0cmluZ2lmeSh0KX1yZXR1cm4gbnVsbH1jbGFzcyBDYXRhbG9neyNmZT1udWxsOyNnZT1udWxsO2J1aWx0SW5DTWFwQ2FjaGU9bmV3IE1hcDtmb250Q2FjaGU9bmV3IFJlZlNldENhY2hlO2dsb2JhbENvbG9yU3BhY2VDYWNoZT1uZXcgR2xvYmFsQ29sb3JTcGFjZUNhY2hlO2dsb2JhbEltYWdlQ2FjaGU9bmV3IEdsb2JhbEltYWdlQ2FjaGU7bm9uQmxlbmRNb2Rlc1NldD1uZXcgUmVmU2V0O3BhZ2VEaWN0Q2FjaGU9bmV3IFJlZlNldENhY2hlO3BhZ2VJbmRleENhY2hlPW5ldyBSZWZTZXRDYWNoZTtwYWdlS2lkc0NvdW50Q2FjaGU9bmV3IFJlZlNldENhY2hlO3N0YW5kYXJkRm9udERhdGFDYWNoZT1uZXcgTWFwO3N5c3RlbUZvbnRDYWNoZT1uZXcgTWFwO2NvbnN0cnVjdG9yKGUsdCl7dGhpcy5wZGZNYW5hZ2VyPWU7dGhpcy54cmVmPXQ7dGhpcy4jZ2U9dC5nZXRDYXRhbG9nT2JqKCk7aWYoISh0aGlzLiNnZSBpbnN0YW5jZW9mIERpY3QpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiQ2F0YWxvZyBvYmplY3QgaXMgbm90IGEgZGljdGlvbmFyeS4iKTt0aGlzLnRvcGxldmVsUGFnZXNEaWN0fWNsb25lRGljdCgpe3JldHVybiB0aGlzLiNnZS5jbG9uZSgpfWdldCB2ZXJzaW9uKCl7Y29uc3QgZT10aGlzLiNnZS5nZXQoIlZlcnNpb24iKTtpZihlIGluc3RhbmNlb2YgTmFtZSl7aWYodXIudGVzdChlLm5hbWUpKXJldHVybiBzaGFkb3codGhpcywidmVyc2lvbiIsZS5uYW1lKTt3YXJuKGBJbnZhbGlkIFBERiBjYXRhbG9nIHZlcnNpb246ICR7ZS5uYW1lfWApfXJldHVybiBzaGFkb3codGhpcywidmVyc2lvbiIsbnVsbCl9Z2V0IGxhbmcoKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiTGFuZyIpO3JldHVybiBzaGFkb3codGhpcywibGFuZyIsZSYmInN0cmluZyI9PXR5cGVvZiBlP3N0cmluZ1RvUERGU3RyaW5nKGUpOm51bGwpfWdldCBuZWVkc1JlbmRlcmluZygpe2NvbnN0IGU9dGhpcy4jZ2UuZ2V0KCJOZWVkc1JlbmRlcmluZyIpO3JldHVybiBzaGFkb3codGhpcywibmVlZHNSZW5kZXJpbmciLCJib29sZWFuIj09dHlwZW9mIGUmJmUpfWdldCBjb2xsZWN0aW9uKCl7bGV0IGU9bnVsbDt0cnl7Y29uc3QgdD10aGlzLiNnZS5nZXQoIkNvbGxlY3Rpb24iKTt0IGluc3RhbmNlb2YgRGljdCYmdC5zaXplPjAmJihlPXQpfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO2luZm8oIkNhbm5vdCBmZXRjaCBDb2xsZWN0aW9uIGVudHJ5OyBhc3N1bWluZyBubyBjb2xsZWN0aW9uIGlzIHByZXNlbnQuIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJjb2xsZWN0aW9uIixlKX1nZXQgYWNyb0Zvcm0oKXtsZXQgZT1udWxsO3RyeXtjb25zdCB0PXRoaXMuI2dlLmdldCgiQWNyb0Zvcm0iKTt0IGluc3RhbmNlb2YgRGljdCYmdC5zaXplPjAmJihlPXQpfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO2luZm8oIkNhbm5vdCBmZXRjaCBBY3JvRm9ybSBlbnRyeTsgYXNzdW1pbmcgbm8gZm9ybXMgYXJlIHByZXNlbnQuIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJhY3JvRm9ybSIsZSl9Z2V0IGFjcm9Gb3JtUmVmKCl7Y29uc3QgZT10aGlzLiNnZS5nZXRSYXcoIkFjcm9Gb3JtIik7cmV0dXJuIHNoYWRvdyh0aGlzLCJhY3JvRm9ybVJlZiIsZSBpbnN0YW5jZW9mIFJlZj9lOm51bGwpfWdldCBtZXRhZGF0YSgpe2NvbnN0IGU9dGhpcy4jZ2UuZ2V0UmF3KCJNZXRhZGF0YSIpO2lmKCEoZSBpbnN0YW5jZW9mIFJlZikpcmV0dXJuIHNoYWRvdyh0aGlzLCJtZXRhZGF0YSIsbnVsbCk7bGV0IHQ9bnVsbDt0cnl7Y29uc3Qgcj10aGlzLnhyZWYuZmV0Y2goZSwhdGhpcy54cmVmLmVuY3J5cHQ/LmVuY3J5cHRNZXRhZGF0YSk7aWYociBpbnN0YW5jZW9mIEJhc2VTdHJlYW0mJnIuZGljdCBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IGU9ci5kaWN0LmdldCgiVHlwZSIpLGE9ci5kaWN0LmdldCgiU3VidHlwZSIpO2lmKGlzTmFtZShlLCJNZXRhZGF0YSIpJiZpc05hbWUoYSwiWE1MIikpe2NvbnN0IGU9c3RyaW5nVG9VVEY4U3RyaW5nKHIuZ2V0U3RyaW5nKCkpO2UmJih0PW5ldyBNZXRhZGF0YVBhcnNlcihlKS5zZXJpYWxpemFibGUpfX19Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKXRocm93IGU7aW5mbyhgU2tpcHBpbmcgaW52YWxpZCBNZXRhZGF0YTogIiR7ZX0iLmApfXJldHVybiBzaGFkb3codGhpcywibWV0YWRhdGEiLHQpfWdldCBtYXJrSW5mbygpe2xldCBlPW51bGw7dHJ5e2U9dGhpcy4jcGUoKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKCJVbmFibGUgdG8gcmVhZCBtYXJrIGluZm8uIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJtYXJrSW5mbyIsZSl9I3BlKCl7Y29uc3QgZT10aGlzLiNnZS5nZXQoIk1hcmtJbmZvIik7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuIG51bGw7Y29uc3QgdD17TWFya2VkOiExLFVzZXJQcm9wZXJ0aWVzOiExLFN1c3BlY3RzOiExfTtmb3IoY29uc3QgciBpbiB0KXtjb25zdCBhPWUuZ2V0KHIpOyJib29sZWFuIj09dHlwZW9mIGEmJih0W3JdPWEpfXJldHVybiB0fWdldCBzdHJ1Y3RUcmVlUm9vdCgpe2xldCBlPW51bGw7dHJ5e2U9dGhpcy4jbWUoKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKCJVbmFibGUgcmVhZCB0byBzdHJ1Y3RUcmVlUm9vdCBpbmZvLiIpfXJldHVybiBzaGFkb3codGhpcywic3RydWN0VHJlZVJvb3QiLGUpfSNtZSgpe2NvbnN0IGU9dGhpcy4jZ2UuZ2V0UmF3KCJTdHJ1Y3RUcmVlUm9vdCIpLHQ9dGhpcy54cmVmLmZldGNoSWZSZWYoZSk7aWYoISh0IGluc3RhbmNlb2YgRGljdCkpcmV0dXJuIG51bGw7Y29uc3Qgcj1uZXcgU3RydWN0VHJlZVJvb3QodGhpcy54cmVmLHQsZSk7ci5pbml0KCk7cmV0dXJuIHJ9Z2V0IHRvcGxldmVsUGFnZXNEaWN0KCl7Y29uc3QgZT10aGlzLiNnZS5nZXQoIlBhZ2VzIik7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIHRvcC1sZXZlbCBwYWdlcyBkaWN0aW9uYXJ5LiIpO3JldHVybiBzaGFkb3codGhpcywidG9wbGV2ZWxQYWdlc0RpY3QiLGUpfWdldCBkb2N1bWVudE91dGxpbmUoKXtsZXQgZT1udWxsO3RyeXtlPXRoaXMuI2JlKCl9Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKXRocm93IGU7d2FybigiVW5hYmxlIHRvIHJlYWQgZG9jdW1lbnQgb3V0bGluZS4iKX1yZXR1cm4gc2hhZG93KHRoaXMsImRvY3VtZW50T3V0bGluZSIsZSl9I2JlKCl7bGV0IGU9dGhpcy4jZ2UuZ2V0KCJPdXRsaW5lcyIpO2lmKCEoZSBpbnN0YW5jZW9mIERpY3QpKXJldHVybiBudWxsO2U9ZS5nZXRSYXcoIkZpcnN0Iik7aWYoIShlIGluc3RhbmNlb2YgUmVmKSlyZXR1cm4gbnVsbDtjb25zdCB0PXtpdGVtczpbXX0scj1be29iajplLHBhcmVudDp0fV0sYT1uZXcgUmVmU2V0O2EucHV0KGUpO2NvbnN0IG49dGhpcy54cmVmLGk9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpO2Zvcig7ci5sZW5ndGg+MDspe2NvbnN0IHQ9ci5zaGlmdCgpLHM9bi5mZXRjaElmUmVmKHQub2JqKTtpZihudWxsPT09cyljb250aW51ZTtzLmhhcygiVGl0bGUiKXx8d2FybigiSW52YWxpZCBvdXRsaW5lIGl0ZW0gZW5jb3VudGVyZWQuIik7Y29uc3Qgbz17dXJsOm51bGwsZGVzdDpudWxsLGFjdGlvbjpudWxsfTtDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoe2Rlc3REaWN0OnMscmVzdWx0T2JqOm8sZG9jQmFzZVVybDp0aGlzLmJhc2VVcmwsZG9jQXR0YWNobWVudHM6dGhpcy5hdHRhY2htZW50c30pO2NvbnN0IGM9cy5nZXQoIlRpdGxlIiksbD1zLmdldCgiRiIpfHwwLGg9cy5nZXRBcnJheSgiQyIpLHU9cy5nZXQoIkNvdW50Iik7bGV0IGQ9aTshaXNOdW1iZXJBcnJheShoLDMpfHwwPT09aFswXSYmMD09PWhbMV0mJjA9PT1oWzJdfHwoZD1Db2xvclNwYWNlVXRpbHMucmdiLmdldFJnYihoLDApKTtjb25zdCBmPXthY3Rpb246by5hY3Rpb24sYXR0YWNobWVudDpvLmF0dGFjaG1lbnQsZGVzdDpvLmRlc3QsdXJsOm8udXJsLHVuc2FmZVVybDpvLnVuc2FmZVVybCxuZXdXaW5kb3c6by5uZXdXaW5kb3csc2V0T0NHU3RhdGU6by5zZXRPQ0dTdGF0ZSx0aXRsZToic3RyaW5nIj09dHlwZW9mIGM/c3RyaW5nVG9QREZTdHJpbmcoYyk6IiIsY29sb3I6ZCxjb3VudDpOdW1iZXIuaXNJbnRlZ2VyKHUpP3U6dm9pZCAwLGJvbGQ6ISEoMiZsKSxpdGFsaWM6ISEoMSZsKSxpdGVtczpbXX07dC5wYXJlbnQuaXRlbXMucHVzaChmKTtlPXMuZ2V0UmF3KCJGaXJzdCIpO2lmKGUgaW5zdGFuY2VvZiBSZWYmJiFhLmhhcyhlKSl7ci5wdXNoKHtvYmo6ZSxwYXJlbnQ6Zn0pO2EucHV0KGUpfWU9cy5nZXRSYXcoIk5leHQiKTtpZihlIGluc3RhbmNlb2YgUmVmJiYhYS5oYXMoZSkpe3IucHVzaCh7b2JqOmUscGFyZW50OnQucGFyZW50fSk7YS5wdXQoZSl9fXJldHVybiB0Lml0ZW1zLmxlbmd0aD4wP3QuaXRlbXM6bnVsbH1nZXQgcGVybWlzc2lvbnMoKXtsZXQgZT1udWxsO3RyeXtlPXRoaXMuI3llKCl9Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKXRocm93IGU7d2FybigiVW5hYmxlIHRvIHJlYWQgcGVybWlzc2lvbnMuIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJwZXJtaXNzaW9ucyIsZSl9I3llKCl7Y29uc3QgZT10aGlzLnhyZWYudHJhaWxlci5nZXQoIkVuY3J5cHQiKTtpZighKGUgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm4gbnVsbDtsZXQgdD1lLmdldCgiUCIpO2lmKCJudW1iZXIiIT10eXBlb2YgdClyZXR1cm4gbnVsbDt0Kz0yKiozMjtjb25zdCByPVtdO2Zvcihjb25zdCBlIGluIFMpe2NvbnN0IGE9U1tlXTt0JmEmJnIucHVzaChhKX1yZXR1cm4gcn1nZXQgb3B0aW9uYWxDb250ZW50Q29uZmlnKCl7bGV0IGU9bnVsbDt0cnl7Y29uc3QgdD10aGlzLiNnZS5nZXQoIk9DUHJvcGVydGllcyIpO2lmKCF0KXJldHVybiBzaGFkb3codGhpcywib3B0aW9uYWxDb250ZW50Q29uZmlnIixudWxsKTtjb25zdCByPXQuZ2V0KCJEIik7aWYoIXIpcmV0dXJuIHNoYWRvdyh0aGlzLCJvcHRpb25hbENvbnRlbnRDb25maWciLG51bGwpO2NvbnN0IGE9dC5nZXQoIk9DR3MiKTtpZighQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gc2hhZG93KHRoaXMsIm9wdGlvbmFsQ29udGVudENvbmZpZyIsbnVsbCk7Y29uc3Qgbj1uZXcgUmVmU2V0Q2FjaGU7Zm9yKGNvbnN0IGUgb2YgYSllIGluc3RhbmNlb2YgUmVmJiYhbi5oYXMoZSkmJm4ucHV0KGUsdGhpcy4jd2UoZSkpO2U9dGhpcy4jeGUocixuKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKGBVbmFibGUgdG8gcmVhZCBvcHRpb25hbCBjb250ZW50IGNvbmZpZzogJHtlfWApfXJldHVybiBzaGFkb3codGhpcywib3B0aW9uYWxDb250ZW50Q29uZmlnIixlKX0jd2UoZSl7Y29uc3QgdD10aGlzLnhyZWYuZmV0Y2goZSkscj17aWQ6ZS50b1N0cmluZygpLG5hbWU6bnVsbCxpbnRlbnQ6bnVsbCx1c2FnZTp7cHJpbnQ6bnVsbCx2aWV3Om51bGx9LHJiR3JvdXBzOltdfSxhPXQuZ2V0KCJOYW1lIik7InN0cmluZyI9PXR5cGVvZiBhJiYoci5uYW1lPXN0cmluZ1RvUERGU3RyaW5nKGEpKTtsZXQgbj10LmdldEFycmF5KCJJbnRlbnQiKTtBcnJheS5pc0FycmF5KG4pfHwobj1bbl0pO24uZXZlcnkoZT0+ZSBpbnN0YW5jZW9mIE5hbWUpJiYoci5pbnRlbnQ9bi5tYXAoZT0+ZS5uYW1lKSk7Y29uc3QgaT10LmdldCgiVXNhZ2UiKTtpZighKGkgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm4gcjtjb25zdCBzPXIudXNhZ2Usbz1pLmdldCgiUHJpbnQiKTtpZihvIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgZT1vLmdldCgiUHJpbnRTdGF0ZSIpO2lmKGUgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChlLm5hbWUpe2Nhc2UiT04iOmNhc2UiT0ZGIjpzLnByaW50PXtwcmludFN0YXRlOmUubmFtZX19fWNvbnN0IGM9aS5nZXQoIlZpZXciKTtpZihjIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgZT1jLmdldCgiVmlld1N0YXRlIik7aWYoZSBpbnN0YW5jZW9mIE5hbWUpc3dpdGNoKGUubmFtZSl7Y2FzZSJPTiI6Y2FzZSJPRkYiOnMudmlldz17dmlld1N0YXRlOmUubmFtZX19fXJldHVybiByfSN4ZShlLHQpe2Z1bmN0aW9uIHBhcnNlT25PZmYoZSl7Y29uc3Qgcj1bXTtpZihBcnJheS5pc0FycmF5KGUpKWZvcihjb25zdCBhIG9mIGUpYSBpbnN0YW5jZW9mIFJlZiYmdC5oYXMoYSkmJnIucHVzaChhLnRvU3RyaW5nKCkpO3JldHVybiByfWZ1bmN0aW9uIHBhcnNlT3JkZXIoZSxyPTApe2lmKCFBcnJheS5pc0FycmF5KGUpKXJldHVybiBudWxsO2NvbnN0IG49W107Zm9yKGNvbnN0IGkgb2YgZSl7aWYoaSBpbnN0YW5jZW9mIFJlZiYmdC5oYXMoaSkpe2EucHV0KGkpO24ucHVzaChpLnRvU3RyaW5nKCkpO2NvbnRpbnVlfWNvbnN0IGU9cGFyc2VOZXN0ZWRPcmRlcihpLHIpO2UmJm4ucHVzaChlKX1pZihyPjApcmV0dXJuIG47Y29uc3QgaT1bXTtmb3IoY29uc3RbZV1vZiB0Lml0ZW1zKCkpYS5oYXMoZSl8fGkucHVzaChlLnRvU3RyaW5nKCkpO2kubGVuZ3RoJiZuLnB1c2goe25hbWU6bnVsbCxvcmRlcjppfSk7cmV0dXJuIG59ZnVuY3Rpb24gcGFyc2VOZXN0ZWRPcmRlcihlLHQpe2lmKCsrdD5uKXt3YXJuKCJwYXJzZU5lc3RlZE9yZGVyIC0gcmVhY2hlZCBNQVhfTkVTVEVEX0xFVkVMUy4iKTtyZXR1cm4gbnVsbH1jb25zdCBhPXIuZmV0Y2hJZlJlZihlKTtpZighQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gbnVsbDtjb25zdCBpPXIuZmV0Y2hJZlJlZihhWzBdKTtpZigic3RyaW5nIiE9dHlwZW9mIGkpcmV0dXJuIG51bGw7Y29uc3Qgcz1wYXJzZU9yZGVyKGEuc2xpY2UoMSksdCk7cmV0dXJuIHM/Lmxlbmd0aD97bmFtZTpzdHJpbmdUb1BERlN0cmluZyhpKSxvcmRlcjpzfTpudWxsfWNvbnN0IHI9dGhpcy54cmVmLGE9bmV3IFJlZlNldCxuPTEwOyFmdW5jdGlvbiBwYXJzZVJCR3JvdXBzKGUpe2lmKEFycmF5LmlzQXJyYXkoZSkpZm9yKGNvbnN0IGEgb2YgZSl7Y29uc3QgZT1yLmZldGNoSWZSZWYoYSk7aWYoIUFycmF5LmlzQXJyYXkoZSl8fCFlLmxlbmd0aCljb250aW51ZTtjb25zdCBuPW5ldyBTZXQ7Zm9yKGNvbnN0IHIgb2YgZSlpZihyIGluc3RhbmNlb2YgUmVmJiZ0LmhhcyhyKSYmIW4uaGFzKHIudG9TdHJpbmcoKSkpe24uYWRkKHIudG9TdHJpbmcoKSk7dC5nZXQocikucmJHcm91cHMucHVzaChuKX19fShlLmdldCgiUkJHcm91cHMiKSk7cmV0dXJue25hbWU6InN0cmluZyI9PXR5cGVvZiBlLmdldCgiTmFtZSIpP3N0cmluZ1RvUERGU3RyaW5nKGUuZ2V0KCJOYW1lIikpOm51bGwsY3JlYXRvcjoic3RyaW5nIj09dHlwZW9mIGUuZ2V0KCJDcmVhdG9yIik/c3RyaW5nVG9QREZTdHJpbmcoZS5nZXQoIkNyZWF0b3IiKSk6bnVsbCxiYXNlU3RhdGU6ZS5nZXQoIkJhc2VTdGF0ZSIpaW5zdGFuY2VvZiBOYW1lP2UuZ2V0KCJCYXNlU3RhdGUiKS5uYW1lOm51bGwsb246cGFyc2VPbk9mZihlLmdldCgiT04iKSksb2ZmOnBhcnNlT25PZmYoZS5nZXQoIk9GRiIpKSxvcmRlcjpwYXJzZU9yZGVyKGUuZ2V0KCJPcmRlciIpKSxncm91cHM6Wy4uLnRdfX1zZXRBY3R1YWxOdW1QYWdlcyhlPW51bGwpe3RoaXMuI2ZlPWV9Z2V0IGhhc0FjdHVhbE51bVBhZ2VzKCl7cmV0dXJuIG51bGwhPT10aGlzLiNmZX1nZXQgX3BhZ2VzQ291bnQoKXtjb25zdCBlPXRoaXMudG9wbGV2ZWxQYWdlc0RpY3QuZ2V0KCJDb3VudCIpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGUpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpbiB0b3AtbGV2ZWwgcGFnZXMgZGljdGlvbmFyeSBpcyBub3QgYW4gaW50ZWdlci4iKTtyZXR1cm4gc2hhZG93KHRoaXMsIl9wYWdlc0NvdW50IixlKX1nZXQgbnVtUGFnZXMoKXtyZXR1cm4gdGhpcy4jZmU/P3RoaXMuX3BhZ2VzQ291bnR9Z2V0IGRlc3RpbmF0aW9ucygpe2NvbnN0IGU9dGhpcy4jU2UoKSx0PU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGNvbnN0IHIgb2YgZSlpZihyIGluc3RhbmNlb2YgTmFtZVRyZWUpZm9yKGNvbnN0W2UsYV1vZiByLmdldEFsbCgpKXtjb25zdCByPWZldGNoRGVzdChhKTtyJiYodFtzdHJpbmdUb1BERlN0cmluZyhlLCEwKV09cil9ZWxzZSBpZihyIGluc3RhbmNlb2YgRGljdClmb3IoY29uc3RbZSxhXW9mIHIpe2NvbnN0IHI9ZmV0Y2hEZXN0KGEpO3ImJih0W3N0cmluZ1RvUERGU3RyaW5nKGUsITApXXx8PXIpfXJldHVybiBzaGFkb3codGhpcywiZGVzdGluYXRpb25zIix0KX1nZXREZXN0aW5hdGlvbihlKXtpZih0aGlzLmhhc093blByb3BlcnR5KCJkZXN0aW5hdGlvbnMiKSlyZXR1cm4gdGhpcy5kZXN0aW5hdGlvbnNbZV0/P251bGw7Y29uc3QgdD10aGlzLiNTZSgpO2Zvcihjb25zdCByIG9mIHQpaWYociBpbnN0YW5jZW9mIE5hbWVUcmVlfHxyIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgdD1mZXRjaERlc3Qoci5nZXQoZSkpO2lmKHQpcmV0dXJuIHR9aWYodC5sZW5ndGgpe2NvbnN0IHQ9dGhpcy5kZXN0aW5hdGlvbnNbZV07aWYodClyZXR1cm4gdH1yZXR1cm4gbnVsbH0jU2UoKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiTmFtZXMiKSx0PVtdO2U/LmhhcygiRGVzdHMiKSYmdC5wdXNoKG5ldyBOYW1lVHJlZShlLmdldFJhdygiRGVzdHMiKSx0aGlzLnhyZWYpKTt0aGlzLiNnZS5oYXMoIkRlc3RzIikmJnQucHVzaCh0aGlzLiNnZS5nZXQoIkRlc3RzIikpO3JldHVybiB0fWdldCBwYWdlTGFiZWxzKCl7bGV0IGU9bnVsbDt0cnl7ZT10aGlzLiNBZSgpfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO3dhcm4oIlVuYWJsZSB0byByZWFkIHBhZ2UgbGFiZWxzLiIpfXJldHVybiBzaGFkb3codGhpcywicGFnZUxhYmVscyIsZSl9I0FlKCl7Y29uc3QgZT10aGlzLiNnZS5nZXRSYXcoIlBhZ2VMYWJlbHMiKTtpZighZSlyZXR1cm4gbnVsbDtjb25zdCB0PW5ldyBBcnJheSh0aGlzLm51bVBhZ2VzKTtsZXQgcj1udWxsLGE9IiI7Y29uc3Qgbj1uZXcgTnVtYmVyVHJlZShlLHRoaXMueHJlZikuZ2V0QWxsKCk7bGV0IGk9IiIscz0xO2ZvcihsZXQgZT0wLG89dGhpcy5udW1QYWdlcztlPG87ZSsrKXtjb25zdCBvPW4uZ2V0KGUpO2lmKHZvaWQgMCE9PW8pe2lmKCEobyBpbnN0YW5jZW9mIERpY3QpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZUxhYmVsIGlzIG5vdCBhIGRpY3Rpb25hcnkuIik7aWYoby5oYXMoIlR5cGUiKSYmIWlzTmFtZShvLmdldCgiVHlwZSIpLCJQYWdlTGFiZWwiKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgdHlwZSBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTtpZihvLmhhcygiUyIpKXtjb25zdCBlPW8uZ2V0KCJTIik7aWYoIShlIGluc3RhbmNlb2YgTmFtZSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIHN0eWxlIGluIFBhZ2VMYWJlbCBkaWN0aW9uYXJ5LiIpO3I9ZS5uYW1lfWVsc2Ugcj1udWxsO2lmKG8uaGFzKCJQIikpe2NvbnN0IGU9by5nZXQoIlAiKTtpZigic3RyaW5nIiE9dHlwZW9mIGUpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIHByZWZpeCBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTthPXN0cmluZ1RvUERGU3RyaW5nKGUpfWVsc2UgYT0iIjtpZihvLmhhcygiU3QiKSl7Y29uc3QgZT1vLmdldCgiU3QiKTtpZighKE51bWJlci5pc0ludGVnZXIoZSkmJmU+PTEpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBzdGFydCBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTtzPWV9ZWxzZSBzPTF9c3dpdGNoKHIpe2Nhc2UiRCI6aT1zO2JyZWFrO2Nhc2UiUiI6Y2FzZSJyIjppPXRvUm9tYW5OdW1lcmFscyhzLCJyIj09PXIpO2JyZWFrO2Nhc2UiQSI6Y2FzZSJhIjpjb25zdCBlPTI2LHQ9ImEiPT09cj85Nzo2NSxhPXMtMTtpPVN0cmluZy5mcm9tQ2hhckNvZGUodCthJWUpLnJlcGVhdChNYXRoLmZsb29yKGEvZSkrMSk7YnJlYWs7ZGVmYXVsdDppZihyKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBzdHlsZSAiJHtyfSIgaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuYCk7aT0iIn10W2VdPWEraTtzKyt9cmV0dXJuIHR9Z2V0IHBhZ2VMYXlvdXQoKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiUGFnZUxheW91dCIpO2xldCB0PSIiO2lmKGUgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChlLm5hbWUpe2Nhc2UiU2luZ2xlUGFnZSI6Y2FzZSJPbmVDb2x1bW4iOmNhc2UiVHdvQ29sdW1uTGVmdCI6Y2FzZSJUd29Db2x1bW5SaWdodCI6Y2FzZSJUd29QYWdlTGVmdCI6Y2FzZSJUd29QYWdlUmlnaHQiOnQ9ZS5uYW1lfXJldHVybiBzaGFkb3codGhpcywicGFnZUxheW91dCIsdCl9Z2V0IHBhZ2VNb2RlKCl7Y29uc3QgZT10aGlzLiNnZS5nZXQoIlBhZ2VNb2RlIik7bGV0IHQ9IlVzZU5vbmUiO2lmKGUgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChlLm5hbWUpe2Nhc2UiVXNlTm9uZSI6Y2FzZSJVc2VPdXRsaW5lcyI6Y2FzZSJVc2VUaHVtYnMiOmNhc2UiRnVsbFNjcmVlbiI6Y2FzZSJVc2VPQyI6Y2FzZSJVc2VBdHRhY2htZW50cyI6dD1lLm5hbWV9cmV0dXJuIHNoYWRvdyh0aGlzLCJwYWdlTW9kZSIsdCl9Z2V0IHZpZXdlclByZWZlcmVuY2VzKCl7Y29uc3QgZT10aGlzLiNnZS5nZXQoIlZpZXdlclByZWZlcmVuY2VzIik7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuIHNoYWRvdyh0aGlzLCJ2aWV3ZXJQcmVmZXJlbmNlcyIsbnVsbCk7bGV0IHQ9bnVsbDtmb3IoY29uc3RbcixhXW9mIGUpe2xldCBlO3N3aXRjaChyKXtjYXNlIkhpZGVUb29sYmFyIjpjYXNlIkhpZGVNZW51YmFyIjpjYXNlIkhpZGVXaW5kb3dVSSI6Y2FzZSJGaXRXaW5kb3ciOmNhc2UiQ2VudGVyV2luZG93IjpjYXNlIkRpc3BsYXlEb2NUaXRsZSI6Y2FzZSJQaWNrVHJheUJ5UERGU2l6ZSI6ImJvb2xlYW4iPT10eXBlb2YgYSYmKGU9YSk7YnJlYWs7Y2FzZSJOb25GdWxsU2NyZWVuUGFnZU1vZGUiOmlmKGEgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChhLm5hbWUpe2Nhc2UiVXNlTm9uZSI6Y2FzZSJVc2VPdXRsaW5lcyI6Y2FzZSJVc2VUaHVtYnMiOmNhc2UiVXNlT0MiOmU9YS5uYW1lO2JyZWFrO2RlZmF1bHQ6ZT0iVXNlTm9uZSJ9YnJlYWs7Y2FzZSJEaXJlY3Rpb24iOmlmKGEgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChhLm5hbWUpe2Nhc2UiTDJSIjpjYXNlIlIyTCI6ZT1hLm5hbWU7YnJlYWs7ZGVmYXVsdDplPSJMMlIifWJyZWFrO2Nhc2UiVmlld0FyZWEiOmNhc2UiVmlld0NsaXAiOmNhc2UiUHJpbnRBcmVhIjpjYXNlIlByaW50Q2xpcCI6aWYoYSBpbnN0YW5jZW9mIE5hbWUpc3dpdGNoKGEubmFtZSl7Y2FzZSJNZWRpYUJveCI6Y2FzZSJDcm9wQm94IjpjYXNlIkJsZWVkQm94IjpjYXNlIlRyaW1Cb3giOmNhc2UiQXJ0Qm94IjplPWEubmFtZTticmVhaztkZWZhdWx0OmU9IkNyb3BCb3gifWJyZWFrO2Nhc2UiUHJpbnRTY2FsaW5nIjppZihhIGluc3RhbmNlb2YgTmFtZSlzd2l0Y2goYS5uYW1lKXtjYXNlIk5vbmUiOmNhc2UiQXBwRGVmYXVsdCI6ZT1hLm5hbWU7YnJlYWs7ZGVmYXVsdDplPSJBcHBEZWZhdWx0In1icmVhaztjYXNlIkR1cGxleCI6aWYoYSBpbnN0YW5jZW9mIE5hbWUpc3dpdGNoKGEubmFtZSl7Y2FzZSJTaW1wbGV4IjpjYXNlIkR1cGxleEZsaXBTaG9ydEVkZ2UiOmNhc2UiRHVwbGV4RmxpcExvbmdFZGdlIjplPWEubmFtZTticmVhaztkZWZhdWx0OmU9Ik5vbmUifWJyZWFrO2Nhc2UiUHJpbnRQYWdlUmFuZ2UiOmlmKEFycmF5LmlzQXJyYXkoYSkmJmEubGVuZ3RoJTI9PTApe2EuZXZlcnkoKGUsdCxyKT0+TnVtYmVyLmlzSW50ZWdlcihlKSYmZT4wJiYoMD09PXR8fGU+PXJbdC0xXSkmJmU8PXRoaXMubnVtUGFnZXMpJiYoZT1hKX1icmVhaztjYXNlIk51bUNvcGllcyI6TnVtYmVyLmlzSW50ZWdlcihhKSYmYT4wJiYoZT1hKTticmVhaztkZWZhdWx0Ondhcm4oYElnbm9yaW5nIG5vbi1zdGFuZGFyZCBrZXkgaW4gVmlld2VyUHJlZmVyZW5jZXM6ICR7cn0uYCk7Y29udGludWV9aWYodm9pZCAwIT09ZSl7dD8/PU9iamVjdC5jcmVhdGUobnVsbCk7dFtyXT1lfWVsc2Ugd2FybihgQmFkIHZhbHVlLCBmb3Iga2V5ICIke3J9IiwgaW4gVmlld2VyUHJlZmVyZW5jZXM6ICR7YX0uYCl9cmV0dXJuIHNoYWRvdyh0aGlzLCJ2aWV3ZXJQcmVmZXJlbmNlcyIsdCl9Z2V0IG9wZW5BY3Rpb24oKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiT3BlbkFjdGlvbiIpLHQ9T2JqZWN0LmNyZWF0ZShudWxsKTtpZihlIGluc3RhbmNlb2YgRGljdCl7Y29uc3Qgcj1uZXcgRGljdCh0aGlzLnhyZWYpO3Iuc2V0KCJBIixlKTtjb25zdCBhPXt1cmw6bnVsbCxkZXN0Om51bGwsYWN0aW9uOm51bGx9O0NhdGFsb2cucGFyc2VEZXN0RGljdGlvbmFyeSh7ZGVzdERpY3Q6cixyZXN1bHRPYmo6YX0pO0FycmF5LmlzQXJyYXkoYS5kZXN0KT90LmRlc3Q9YS5kZXN0OmEuYWN0aW9uJiYodC5hY3Rpb249YS5hY3Rpb24pfWVsc2UgTmkoZSkmJih0LmRlc3Q9ZSk7cmV0dXJuIHNoYWRvdyh0aGlzLCJvcGVuQWN0aW9uIixvYmplY3RTaXplKHQpPjA/dDpudWxsKX1nZXQgYXR0YWNobWVudHMoKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiTmFtZXMiKTtsZXQgdD1udWxsO2lmKGUgaW5zdGFuY2VvZiBEaWN0JiZlLmhhcygiRW1iZWRkZWRGaWxlcyIpKXtjb25zdCByPW5ldyBOYW1lVHJlZShlLmdldFJhdygiRW1iZWRkZWRGaWxlcyIpLHRoaXMueHJlZik7Zm9yKGNvbnN0W2UsYV1vZiByLmdldEFsbCgpKXtjb25zdCByPW5ldyBGaWxlU3BlYyhhLHRoaXMueHJlZik7dD8/PU9iamVjdC5jcmVhdGUobnVsbCk7dFtzdHJpbmdUb1BERlN0cmluZyhlLCEwKV09ci5zZXJpYWxpemFibGV9fXJldHVybiBzaGFkb3codGhpcywiYXR0YWNobWVudHMiLHQpfWdldCB4ZmFJbWFnZXMoKXtjb25zdCBlPXRoaXMuI2dlLmdldCgiTmFtZXMiKTtsZXQgdD1udWxsO2lmKGUgaW5zdGFuY2VvZiBEaWN0JiZlLmhhcygiWEZBSW1hZ2VzIikpe2NvbnN0IHI9bmV3IE5hbWVUcmVlKGUuZ2V0UmF3KCJYRkFJbWFnZXMiKSx0aGlzLnhyZWYpO2Zvcihjb25zdFtlLGFdb2Ygci5nZXRBbGwoKSlpZihhIGluc3RhbmNlb2YgQmFzZVN0cmVhbSl7dD8/PW5ldyBNYXA7dC5zZXQoc3RyaW5nVG9QREZTdHJpbmcoZSwhMCksYS5nZXRCeXRlcygpKX19cmV0dXJuIHNoYWRvdyh0aGlzLCJ4ZmFJbWFnZXMiLHQpfSNrZSgpe2NvbnN0IGU9dGhpcy4jZ2UuZ2V0KCJOYW1lcyIpO2xldCB0PW51bGw7ZnVuY3Rpb24gYXBwZW5kSWZKYXZhU2NyaXB0RGljdChlLHIpe2lmKCEociBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtpZighaXNOYW1lKHIuZ2V0KCJTIiksIkphdmFTY3JpcHQiKSlyZXR1cm47bGV0IGE9ci5nZXQoIkpTIik7aWYoYSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pYT1hLmdldFN0cmluZygpO2Vsc2UgaWYoInN0cmluZyIhPXR5cGVvZiBhKXJldHVybjthPXN0cmluZ1RvUERGU3RyaW5nKGEsITApLnJlcGxhY2VBbGwoIlwwIiwiIik7YSYmKHR8fD1uZXcgTWFwKS5zZXQoZSxhKX1pZihlIGluc3RhbmNlb2YgRGljdCYmZS5oYXMoIkphdmFTY3JpcHQiKSl7Y29uc3QgdD1uZXcgTmFtZVRyZWUoZS5nZXRSYXcoIkphdmFTY3JpcHQiKSx0aGlzLnhyZWYpO2Zvcihjb25zdFtlLHJdb2YgdC5nZXRBbGwoKSlhcHBlbmRJZkphdmFTY3JpcHREaWN0KHN0cmluZ1RvUERGU3RyaW5nKGUsITApLHIpfWNvbnN0IHI9dGhpcy4jZ2UuZ2V0KCJPcGVuQWN0aW9uIik7ciYmYXBwZW5kSWZKYXZhU2NyaXB0RGljdCgiT3BlbkFjdGlvbiIscik7cmV0dXJuIHR9Z2V0IGpzQWN0aW9ucygpe2NvbnN0IGU9dGhpcy4ja2UoKTtsZXQgdD1jb2xsZWN0QWN0aW9ucyh0aGlzLnhyZWYsdGhpcy4jZ2UsaWUpO2lmKGUpe3R8fD1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcihjb25zdFtyLGFdb2YgZSlyIGluIHQ/dFtyXS5wdXNoKGEpOnRbcl09W2FdfXJldHVybiBzaGFkb3codGhpcywianNBY3Rpb25zIix0KX1hc3luYyBjbGVhbnVwKGU9ITEpe2NsZWFyR2xvYmFsQ2FjaGVzKCk7dGhpcy5nbG9iYWxDb2xvclNwYWNlQ2FjaGUuY2xlYXIoKTt0aGlzLmdsb2JhbEltYWdlQ2FjaGUuY2xlYXIoZSk7dGhpcy5wYWdlS2lkc0NvdW50Q2FjaGUuY2xlYXIoKTt0aGlzLnBhZ2VJbmRleENhY2hlLmNsZWFyKCk7dGhpcy5wYWdlRGljdENhY2hlLmNsZWFyKCk7dGhpcy5ub25CbGVuZE1vZGVzU2V0LmNsZWFyKCk7Zm9yKGNvbnN0e2RpY3Q6ZX1vZiBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLmZvbnRDYWNoZSkpZGVsZXRlIGUuY2FjaGVLZXk7dGhpcy5mb250Q2FjaGUuY2xlYXIoKTt0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUuY2xlYXIoKTt0aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZS5jbGVhcigpO3RoaXMuc3lzdGVtRm9udENhY2hlLmNsZWFyKCl9YXN5bmMgZ2V0UGFnZURpY3QoZSl7Y29uc3QgdD1bdGhpcy50b3BsZXZlbFBhZ2VzRGljdF0scj1uZXcgUmVmU2V0LGE9dGhpcy4jZ2UuZ2V0UmF3KCJQYWdlcyIpO2EgaW5zdGFuY2VvZiBSZWYmJnIucHV0KGEpO2NvbnN0IG49dGhpcy54cmVmLGk9dGhpcy5wYWdlS2lkc0NvdW50Q2FjaGUscz10aGlzLnBhZ2VJbmRleENhY2hlLG89dGhpcy5wYWdlRGljdENhY2hlO2xldCBjPTA7Zm9yKDt0Lmxlbmd0aDspe2NvbnN0IGE9dC5wb3AoKTtpZihhIGluc3RhbmNlb2YgUmVmKXtjb25zdCBsPWkuZ2V0KGEpO2lmKGw+PTAmJmMrbDw9ZSl7Yys9bDtjb250aW51ZX1pZihyLmhhcyhhKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhZ2VzIHRyZWUgY29udGFpbnMgY2lyY3VsYXIgcmVmZXJlbmNlLiIpO3IucHV0KGEpO2NvbnN0IGg9YXdhaXQoby5nZXQoYSl8fG4uZmV0Y2hBc3luYyhhKSk7aWYoaCBpbnN0YW5jZW9mIERpY3Qpe2xldCB0PWguZ2V0UmF3KCJUeXBlIik7dCBpbnN0YW5jZW9mIFJlZiYmKHQ9YXdhaXQgbi5mZXRjaEFzeW5jKHQpKTtpZihpc05hbWUodCwiUGFnZSIpfHwhaC5oYXMoIktpZHMiKSl7aS5oYXMoYSl8fGkucHV0KGEsMSk7cy5oYXMoYSl8fHMucHV0KGEsYyk7aWYoYz09PWUpcmV0dXJuW2gsYV07YysrO2NvbnRpbnVlfX10LnB1c2goaCk7Y29udGludWV9aWYoIShhIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkIHJlZmVyZW5jZSBwb2ludHMgdG8gd3JvbmcgdHlwZSBvZiBvYmplY3QuIik7Y29uc3R7b2JqSWQ6bH09YTtsZXQgaD1hLmdldFJhdygiQ291bnQiKTtoIGluc3RhbmNlb2YgUmVmJiYoaD1hd2FpdCBuLmZldGNoQXN5bmMoaCkpO2lmKE51bWJlci5pc0ludGVnZXIoaCkmJmg+PTApe2wmJiFpLmhhcyhsKSYmaS5wdXQobCxoKTtpZihjK2g8PWUpe2MrPWg7Y29udGludWV9fWxldCB1PWEuZ2V0UmF3KCJLaWRzIik7dSBpbnN0YW5jZW9mIFJlZiYmKHU9YXdhaXQgbi5mZXRjaEFzeW5jKHUpKTtpZighQXJyYXkuaXNBcnJheSh1KSl7bGV0IHQ9YS5nZXRSYXcoIlR5cGUiKTt0IGluc3RhbmNlb2YgUmVmJiYodD1hd2FpdCBuLmZldGNoQXN5bmModCkpO2lmKGlzTmFtZSh0LCJQYWdlIil8fCFhLmhhcygiS2lkcyIpKXtpZihjPT09ZSlyZXR1cm5bYSxudWxsXTtjKys7Y29udGludWV9dGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkcyBvYmplY3QgaXMgbm90IGFuIGFycmF5LiIpfWZvcihsZXQgZT11Lmxlbmd0aC0xO2U+PTA7ZS0tKXtjb25zdCByPXVbZV07dC5wdXNoKHIpO2E9PT10aGlzLnRvcGxldmVsUGFnZXNEaWN0JiZyIGluc3RhbmNlb2YgUmVmJiYhby5oYXMocikmJm8ucHV0KHIsbi5mZXRjaEFzeW5jKHIpKX19dGhyb3cgbmV3IEVycm9yKGBQYWdlIGluZGV4ICR7ZX0gbm90IGZvdW5kLmApfWFzeW5jIGdldEFsbFBhZ2VEaWN0cyhlPSExKXtjb25zdHtpZ25vcmVFcnJvcnM6dH09dGhpcy5wZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnMscj1be2N1cnJlbnROb2RlOnRoaXMudG9wbGV2ZWxQYWdlc0RpY3QscG9zSW5LaWRzOjB9XSxhPW5ldyBSZWZTZXQsbj10aGlzLiNnZS5nZXRSYXcoIlBhZ2VzIik7biBpbnN0YW5jZW9mIFJlZiYmYS5wdXQobik7Y29uc3QgaT1uZXcgTWFwLHM9dGhpcy54cmVmLG89dGhpcy5wYWdlSW5kZXhDYWNoZTtsZXQgYz0wO2Z1bmN0aW9uIGFkZFBhZ2VEaWN0KGUsdCl7dCYmIW8uaGFzKHQpJiZvLnB1dCh0LGMpO2kuc2V0KGMrKyxbZSx0XSl9ZnVuY3Rpb24gYWRkUGFnZUVycm9yKHIpe2lmKHIgaW5zdGFuY2VvZiBYUmVmRW50cnlFeGNlcHRpb24mJiFlKXRocm93IHI7aWYoZSYmdCYmMD09PWMpe3dhcm4oYGdldEFsbFBhZ2VEaWN0cyAtIFNraXBwaW5nIGludmFsaWQgZmlyc3QgcGFnZTogIiR7cn0iLmApO3I9RGljdC5lbXB0eX1pLnNldChjKyssW3IsbnVsbF0pfWZvcig7ci5sZW5ndGg+MDspe2NvbnN0IGU9ci5hdCgtMSkse2N1cnJlbnROb2RlOnQscG9zSW5LaWRzOm59PWU7bGV0IGk9dC5nZXRSYXcoIktpZHMiKTtpZihpIGluc3RhbmNlb2YgUmVmKXRyeXtpPWF3YWl0IHMuZmV0Y2hBc3luYyhpKX1jYXRjaChlKXthZGRQYWdlRXJyb3IoZSk7YnJlYWt9aWYoIUFycmF5LmlzQXJyYXkoaSkpe2FkZFBhZ2VFcnJvcihuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWRzIG9iamVjdCBpcyBub3QgYW4gYXJyYXkuIikpO2JyZWFrfWlmKG4+PWkubGVuZ3RoKXtyLnBvcCgpO2NvbnRpbnVlfWNvbnN0IG89aVtuXTtsZXQgYztpZihvIGluc3RhbmNlb2YgUmVmKXtpZihhLmhhcyhvKSl7YWRkUGFnZUVycm9yKG5ldyBGb3JtYXRFcnJvcigiUGFnZXMgdHJlZSBjb250YWlucyBjaXJjdWxhciByZWZlcmVuY2UuIikpO2JyZWFrfWEucHV0KG8pO3RyeXtjPWF3YWl0IHMuZmV0Y2hBc3luYyhvKX1jYXRjaChlKXthZGRQYWdlRXJyb3IoZSk7YnJlYWt9fWVsc2UgYz1vO2lmKCEoYyBpbnN0YW5jZW9mIERpY3QpKXthZGRQYWdlRXJyb3IobmV3IEZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkIHJlZmVyZW5jZSBwb2ludHMgdG8gd3JvbmcgdHlwZSBvZiBvYmplY3QuIikpO2JyZWFrfWxldCBsPWMuZ2V0UmF3KCJUeXBlIik7aWYobCBpbnN0YW5jZW9mIFJlZil0cnl7bD1hd2FpdCBzLmZldGNoQXN5bmMobCl9Y2F0Y2goZSl7YWRkUGFnZUVycm9yKGUpO2JyZWFrfWlzTmFtZShsLCJQYWdlIil8fCFjLmhhcygiS2lkcyIpP2FkZFBhZ2VEaWN0KGMsbyBpbnN0YW5jZW9mIFJlZj9vOm51bGwpOnIucHVzaCh7Y3VycmVudE5vZGU6Yyxwb3NJbktpZHM6MH0pO2UucG9zSW5LaWRzKyt9cmV0dXJuIGl9Z2V0UGFnZUluZGV4KGUpe2NvbnN0IHQ9dGhpcy5wYWdlSW5kZXhDYWNoZS5nZXQoZSk7aWYodm9pZCAwIT09dClyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHQpO2NvbnN0IHI9dGhpcy54cmVmO2xldCBhPTA7Y29uc3QgbmV4dD10PT5mdW5jdGlvbiBwYWdlc0JlZm9yZVJlZih0KXtsZXQgYSxuPTA7cmV0dXJuIHIuZmV0Y2hBc3luYyh0KS50aGVuKGZ1bmN0aW9uKHIpe2lmKGlzUmVmc0VxdWFsKHQsZSkmJiFpc0RpY3QociwiUGFnZSIpJiYhKHIgaW5zdGFuY2VvZiBEaWN0JiYhci5oYXMoIlR5cGUiKSYmci5oYXMoIkNvbnRlbnRzIikpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiVGhlIHJlZmVyZW5jZSBkb2VzIG5vdCBwb2ludCB0byBhIC9QYWdlIGRpY3Rpb25hcnkuIik7aWYoIXIpcmV0dXJuIG51bGw7aWYoIShyIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJOb2RlIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpO2E9ci5nZXRSYXcoIlBhcmVudCIpO3JldHVybiByLmdldEFzeW5jKCJQYXJlbnQiKX0pLnRoZW4oZnVuY3Rpb24oZSl7aWYoIWUpcmV0dXJuIG51bGw7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJQYXJlbnQgbXVzdCBiZSBhIGRpY3Rpb25hcnkuIik7cmV0dXJuIGUuZ2V0QXN5bmMoIktpZHMiKX0pLnRoZW4oZnVuY3Rpb24oZSl7aWYoIWUpcmV0dXJuIG51bGw7Y29uc3QgaT1bXTtsZXQgcz0hMTtmb3IoY29uc3QgYSBvZiBlKXtpZighKGEgaW5zdGFuY2VvZiBSZWYpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiS2lkIG11c3QgYmUgYSByZWZlcmVuY2UuIik7aWYoaXNSZWZzRXF1YWwoYSx0KSl7cz0hMDticmVha31pLnB1c2goci5mZXRjaEFzeW5jKGEpLnRoZW4oZnVuY3Rpb24oZSl7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJLaWQgbm9kZSBtdXN0IGJlIGEgZGljdGlvbmFyeS4iKTtlLmhhcygiQ291bnQiKT9uKz1lLmdldCgiQ291bnQiKTpuKyt9KSl9aWYoIXMpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJLaWQgcmVmZXJlbmNlIG5vdCBmb3VuZCBpbiBwYXJlbnQncyBraWRzLiIpO3JldHVybiBQcm9taXNlLmFsbChpKS50aGVuKCgpPT5bbixhXSl9KX0odCkudGhlbih0PT57aWYoIXQpe3RoaXMucGFnZUluZGV4Q2FjaGUucHV0KGUsYSk7cmV0dXJuIGF9Y29uc3RbcixuXT10O2ErPXI7cmV0dXJuIG5leHQobil9KTtyZXR1cm4gbmV4dChlKX1nZXQgYmFzZVVybCgpe2NvbnN0IGU9dGhpcy4jZ2UuZ2V0KCJVUkkiKTtpZihlIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgdD1lLmdldCgiQmFzZSIpO2lmKCJzdHJpbmciPT10eXBlb2YgdCl7Y29uc3QgZT1jcmVhdGVWYWxpZEFic29sdXRlVXJsKHQsbnVsbCx7dHJ5Q29udmVydEVuY29kaW5nOiEwfSk7aWYoZSlyZXR1cm4gc2hhZG93KHRoaXMsImJhc2VVcmwiLGUuaHJlZil9fXJldHVybiBzaGFkb3codGhpcywiYmFzZVVybCIsdGhpcy5wZGZNYW5hZ2VyLmRvY0Jhc2VVcmwpfXN0YXRpYyBwYXJzZURlc3REaWN0aW9uYXJ5KHtkZXN0RGljdDplLHJlc3VsdE9iajp0LGRvY0Jhc2VVcmw6cj1udWxsLGRvY0F0dGFjaG1lbnRzOmE9bnVsbH0pe2lmKCEoZSBpbnN0YW5jZW9mIERpY3QpKXt3YXJuKCJwYXJzZURlc3REaWN0aW9uYXJ5OiBgZGVzdERpY3RgIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpO3JldHVybn1sZXQgbixpLHM9ZS5nZXQoIkEiKTtpZighKHMgaW5zdGFuY2VvZiBEaWN0KSlpZihlLmhhcygiRGVzdCIpKXM9ZS5nZXQoIkRlc3QiKTtlbHNle3M9ZS5nZXQoIkFBIik7cyBpbnN0YW5jZW9mIERpY3QmJihzLmhhcygiRCIpP3M9cy5nZXQoIkQiKTpzLmhhcygiVSIpJiYocz1zLmdldCgiVSIpKSl9aWYocyBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IGU9cy5nZXQoIlMiKTtpZighKGUgaW5zdGFuY2VvZiBOYW1lKSl7d2FybigicGFyc2VEZXN0RGljdGlvbmFyeTogSW52YWxpZCB0eXBlIGluIEFjdGlvbiBkaWN0aW9uYXJ5LiIpO3JldHVybn1jb25zdCByPWUubmFtZTtzd2l0Y2gocil7Y2FzZSJSZXNldEZvcm0iOmNvbnN0IGU9cy5nZXQoIkZsYWdzIiksbz0hKDEmKCJudW1iZXIiPT10eXBlb2YgZT9lOjApKSxjPVtdLGw9W107Zm9yKGNvbnN0IGUgb2Ygcy5nZXQoIkZpZWxkcyIpfHxbXSllIGluc3RhbmNlb2YgUmVmP2wucHVzaChlLnRvU3RyaW5nKCkpOiJzdHJpbmciPT10eXBlb2YgZSYmYy5wdXNoKHN0cmluZ1RvUERGU3RyaW5nKGUpKTt0LnJlc2V0Rm9ybT17ZmllbGRzOmMscmVmczpsLGluY2x1ZGU6b307YnJlYWs7Y2FzZSJVUkkiOm49cy5nZXQoIlVSSSIpO24gaW5zdGFuY2VvZiBOYW1lJiYobj0iLyIrbi5uYW1lKTticmVhaztjYXNlIkdvVG8iOmk9cy5nZXQoIkQiKTticmVhaztjYXNlIkxhdW5jaCI6Y2FzZSJHb1RvUiI6Y29uc3QgaD1zLmdldCgiRiIpO2lmKGggaW5zdGFuY2VvZiBEaWN0KXtjb25zdCBlPW5ldyBGaWxlU3BlYyhoLG51bGwsITApLHtyYXdGaWxlbmFtZTp0fT1lLnNlcmlhbGl6YWJsZTtuPXR9ZWxzZSJzdHJpbmciPT10eXBlb2YgaCYmKG49aCk7Y29uc3QgdT1mZXRjaFJlbW90ZURlc3Qocyk7dSYmInN0cmluZyI9PXR5cGVvZiBuJiYobj1uLnNwbGl0KCIjIiwxKVswXSsiIyIrdSk7Y29uc3QgZD1zLmdldCgiTmV3V2luZG93Iik7ImJvb2xlYW4iPT10eXBlb2YgZCYmKHQubmV3V2luZG93PWQpO2JyZWFrO2Nhc2UiR29Ub0UiOmNvbnN0IGY9cy5nZXQoIlQiKTtsZXQgZztpZihhJiZmIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgZT1mLmdldCgiUiIpLHQ9Zi5nZXQoIk4iKTtpc05hbWUoZSwiQyIpJiYic3RyaW5nIj09dHlwZW9mIHQmJihnPWFbc3RyaW5nVG9QREZTdHJpbmcodCwhMCldKX1pZihnKXt0LmF0dGFjaG1lbnQ9Zztjb25zdCBlPWZldGNoUmVtb3RlRGVzdChzKTtlJiYodC5hdHRhY2htZW50RGVzdD1lKX1lbHNlIHdhcm4oJ3BhcnNlRGVzdERpY3Rpb25hcnkgLSB1bmltcGxlbWVudGVkICJHb1RvRSIgYWN0aW9uLicpO2JyZWFrO2Nhc2UiTmFtZWQiOmNvbnN0IHA9cy5nZXQoIk4iKTtwIGluc3RhbmNlb2YgTmFtZSYmKHQuYWN0aW9uPXAubmFtZSk7YnJlYWs7Y2FzZSJTZXRPQ0dTdGF0ZSI6Y29uc3QgbT1zLmdldCgiU3RhdGUiKSxiPXMuZ2V0KCJQcmVzZXJ2ZVJCIik7aWYoIUFycmF5LmlzQXJyYXkobSl8fDA9PT1tLmxlbmd0aClicmVhaztjb25zdCB5PVtdO2Zvcihjb25zdCBlIG9mIG0paWYoZSBpbnN0YW5jZW9mIE5hbWUpc3dpdGNoKGUubmFtZSl7Y2FzZSJPTiI6Y2FzZSJPRkYiOmNhc2UiVG9nZ2xlIjp5LnB1c2goZS5uYW1lKX1lbHNlIGUgaW5zdGFuY2VvZiBSZWYmJnkucHVzaChlLnRvU3RyaW5nKCkpO2lmKHkubGVuZ3RoIT09bS5sZW5ndGgpYnJlYWs7dC5zZXRPQ0dTdGF0ZT17c3RhdGU6eSxwcmVzZXJ2ZVJCOiJib29sZWFuIiE9dHlwZW9mIGJ8fGJ9O2JyZWFrO2Nhc2UiSmF2YVNjcmlwdCI6Y29uc3Qgdz1zLmdldCgiSlMiKTtsZXQgeDt3IGluc3RhbmNlb2YgQmFzZVN0cmVhbT94PXcuZ2V0U3RyaW5nKCk6InN0cmluZyI9PXR5cGVvZiB3JiYoeD13KTtjb25zdCBTPXgmJnJlY292ZXJKc1VSTChzdHJpbmdUb1BERlN0cmluZyh4LCEwKSk7aWYoUyl7bj1TLnVybDt0Lm5ld1dpbmRvdz1TLm5ld1dpbmRvdzticmVha31kZWZhdWx0OmlmKCJKYXZhU2NyaXB0Ij09PXJ8fCJTdWJtaXRGb3JtIj09PXIpYnJlYWs7d2FybihgcGFyc2VEZXN0RGljdGlvbmFyeSAtIHVuc3VwcG9ydGVkIGFjdGlvbjogIiR7cn0iLmApfX1lbHNlIGUuaGFzKCJEZXN0IikmJihpPWUuZ2V0KCJEZXN0IikpO2lmKCJzdHJpbmciPT10eXBlb2Ygbil7Y29uc3QgZT1jcmVhdGVWYWxpZEFic29sdXRlVXJsKG4scix7YWRkRGVmYXVsdFByb3RvY29sOiEwLHRyeUNvbnZlcnRFbmNvZGluZzohMH0pO2UmJih0LnVybD1lLmhyZWYpO3QudW5zYWZlVXJsPW59aWYoaSl7aSBpbnN0YW5jZW9mIE5hbWUmJihpPWkubmFtZSk7InN0cmluZyI9PXR5cGVvZiBpP3QuZGVzdD1zdHJpbmdUb1BERlN0cmluZyhpLCEwKTpOaShpKSYmKHQuZGVzdD1pKX19fWZ1bmN0aW9uIG1heUhhdmVDaGlsZHJlbihlKXtyZXR1cm4gZSBpbnN0YW5jZW9mIFJlZnx8ZSBpbnN0YW5jZW9mIERpY3R8fGUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtfHxBcnJheS5pc0FycmF5KGUpfWZ1bmN0aW9uIGFkZENoaWxkcmVuKGUsdCl7aWYoZSBpbnN0YW5jZW9mIERpY3QpZT1lLmdldFJhd1ZhbHVlcygpO2Vsc2UgaWYoZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pZT1lLmRpY3QuZ2V0UmF3VmFsdWVzKCk7ZWxzZSBpZighQXJyYXkuaXNBcnJheShlKSlyZXR1cm47Zm9yKGNvbnN0IHIgb2YgZSltYXlIYXZlQ2hpbGRyZW4ocikmJnQucHVzaChyKX1jbGFzcyBPYmplY3RMb2FkZXJ7cmVmU2V0PW5ldyBSZWZTZXQ7Y29uc3RydWN0b3IoZSx0LHIpe3RoaXMuZGljdD1lO3RoaXMua2V5cz10O3RoaXMueHJlZj1yfWFzeW5jIGxvYWQoKXtjb25zdHtrZXlzOmUsZGljdDp0fT10aGlzLHI9W107Zm9yKGNvbnN0IGEgb2YgZSl7Y29uc3QgZT10LmdldFJhdyhhKTt2b2lkIDAhPT1lJiZyLnB1c2goZSl9YXdhaXQgdGhpcy4jQ2Uocik7dGhpcy5yZWZTZXQ9bnVsbH1hc3luYyNDZShlKXtjb25zdCB0PVtdLHI9W107Zm9yKDtlLmxlbmd0aDspe2xldCBhPWUucG9wKCk7aWYoYSBpbnN0YW5jZW9mIFJlZil7aWYodGhpcy5yZWZTZXQuaGFzKGEpKWNvbnRpbnVlO3RyeXt0aGlzLnJlZlNldC5wdXQoYSk7YT10aGlzLnhyZWYuZmV0Y2goYSl9Y2F0Y2goZSl7aWYoIShlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKXt3YXJuKGBPYmplY3RMb2FkZXIuI3dhbGsgLSByZXF1ZXN0aW5nIGFsbCBkYXRhOiAiJHtlfSIuYCk7YXdhaXQgdGhpcy54cmVmLnN0cmVhbS5tYW5hZ2VyLnJlcXVlc3RBbGxDaHVua3MoKTtyZXR1cm59dC5wdXNoKGEpO3IucHVzaCh7YmVnaW46ZS5iZWdpbixlbmQ6ZS5lbmR9KX19aWYoYSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pe2NvbnN0IGU9YS5nZXRCYXNlU3RyZWFtcygpO2lmKGUpe2xldCBuPSExO2Zvcihjb25zdCB0IG9mIGUpaWYoIXQuaXNEYXRhTG9hZGVkKXtuPSEwO3IucHVzaCh7YmVnaW46dC5zdGFydCxlbmQ6dC5lbmR9KX1uJiZ0LnB1c2goYSl9fWFkZENoaWxkcmVuKGEsZSl9aWYoci5sZW5ndGgpe2F3YWl0IHRoaXMueHJlZi5zdHJlYW0ubWFuYWdlci5yZXF1ZXN0UmFuZ2VzKHIpO2Zvcihjb25zdCBlIG9mIHQpZSBpbnN0YW5jZW9mIFJlZiYmdGhpcy5yZWZTZXQucmVtb3ZlKGUpO2F3YWl0IHRoaXMuI0NlKHQpfX1zdGF0aWMgYXN5bmMgbG9hZChlLHQscil7aWYoci5zdHJlYW0uaXNEYXRhTG9hZGVkKXJldHVybjtjb25zdCBhPW5ldyBPYmplY3RMb2FkZXIoZSx0LHIpO2F3YWl0IGEubG9hZCgpfX1jb25zdCBQaT1TeW1ib2woKSxfaT1TeW1ib2woKSxqaT1TeW1ib2woKSxxaT1TeW1ib2woKSxYaT1TeW1ib2woKSxIaT1TeW1ib2woKSxXaT1TeW1ib2woKSx6aT1TeW1ib2woKSxHaT1TeW1ib2woKSwkaT1TeW1ib2woImNvbnRlbnQiKSxWaT1TeW1ib2woImRhdGEiKSxLaT1TeW1ib2woKSxKaT1TeW1ib2woImV4dHJhIiksWWk9U3ltYm9sKCksWmk9U3ltYm9sKCksUWk9U3ltYm9sKCksZXM9U3ltYm9sKCksdHM9U3ltYm9sKCkscnM9U3ltYm9sKCksYXM9U3ltYm9sKCksbnM9U3ltYm9sKCksaXM9U3ltYm9sKCksc3M9U3ltYm9sKCksb3M9U3ltYm9sKCksY3M9U3ltYm9sKCksbHM9U3ltYm9sKCksaHM9U3ltYm9sKCksdXM9U3ltYm9sKCksZHM9U3ltYm9sKCksZnM9U3ltYm9sKCksZ3M9U3ltYm9sKCkscHM9U3ltYm9sKCksbXM9U3ltYm9sKCksYnM9U3ltYm9sKCkseXM9U3ltYm9sKCksd3M9U3ltYm9sKCkseHM9U3ltYm9sKCksU3M9U3ltYm9sKCksQXM9U3ltYm9sKCksa3M9U3ltYm9sKCksQ3M9U3ltYm9sKCksdnM9U3ltYm9sKCksRnM9U3ltYm9sKCksSXM9U3ltYm9sKCksVHM9U3ltYm9sKCksT3M9U3ltYm9sKCJuYW1lc3BhY2VJZCIpLE1zPVN5bWJvbCgibm9kZU5hbWUiKSxEcz1TeW1ib2woKSxCcz1TeW1ib2woKSxScz1TeW1ib2woKSxFcz1TeW1ib2woKSxOcz1TeW1ib2woKSxfcz1TeW1ib2woKSxMcz1TeW1ib2woKSxqcz1TeW1ib2woKSxVcz1TeW1ib2woInJvb3QiKSxxcz1TeW1ib2woKSxYcz1TeW1ib2woKSxIcz1TeW1ib2woKSxXcz1TeW1ib2woKSx6cz1TeW1ib2woKSxHcz1TeW1ib2woKSwkcz1TeW1ib2woKSxWcz1TeW1ib2woKSxLcz1TeW1ib2woKSxKcz1TeW1ib2woKSxZcz1TeW1ib2woKSxacz1TeW1ib2woInVpZCIpO19fd2VicGFja19yZXF1aXJlX18oNTMxKTtjb25zdCBRcz1TeW1ib2woKSxlbz17Y29uZmlnOntpZDowLGNoZWNrOmU9PmUuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94Y2kvIil9LGNvbm5lY3Rpb25TZXQ6e2lkOjEsY2hlY2s6ZT0+ZS5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1jb25uZWN0aW9uLXNldC8iKX0sZGF0YXNldHM6e2lkOjIsY2hlY2s6ZT0+ZS5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1kYXRhLyIpfSxmb3JtOntpZDozLGNoZWNrOmU9PmUuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZm9ybS8iKX0sbG9jYWxlU2V0OntpZDo0LGNoZWNrOmU9PmUuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtbG9jYWxlLXNldC8iKX0scGRmOntpZDo1LGNoZWNrOmU9PiJodHRwOi8vbnMuYWRvYmUuY29tL3hkcC9wZGYvIj09PWV9LHNpZ25hdHVyZTp7aWQ6NixjaGVjazplPT4iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI9PT1lfSxzb3VyY2VTZXQ6e2lkOjcsY2hlY2s6ZT0+ZS5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1zb3VyY2Utc2V0LyIpfSxzdHlsZXNoZWV0OntpZDo4LGNoZWNrOmU9PiJodHRwOi8vd3d3LnczLm9yZy8xOTk5L1hTTC9UcmFuc2Zvcm0iPT09ZX0sdGVtcGxhdGU6e2lkOjksY2hlY2s6ZT0+ZS5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS10ZW1wbGF0ZS8iKX0seGRjOntpZDoxMCxjaGVjazplPT5lLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGRjLyIpfSx4ZHA6e2lkOjExLGNoZWNrOmU9PiJodHRwOi8vbnMuYWRvYmUuY29tL3hkcC8iPT09ZX0seGZkZjp7aWQ6MTIsY2hlY2s6ZT0+Imh0dHA6Ly9ucy5hZG9iZS5jb20veGZkZi8iPT09ZX0seGh0bWw6e2lkOjEzLGNoZWNrOmU9PiJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIj09PWV9LHhtcG1ldGE6e2lkOjE0LGNoZWNrOmU9PiJodHRwOi8vbnMuYWRvYmUuY29tL3htcG1ldGEvIj09PWV9fSx0bz17cHQ6ZT0+ZSxjbTplPT5lLzIuNTQqNzIsbW06ZT0+ZS8yNS40KjcyLGluOmU9PjcyKmUscHg6ZT0+ZX0scm89LyhbKy1dP1xkK1wuP1xkKikoLiopLztmdW5jdGlvbiBzdHJpcFF1b3RlcyhlKXtyZXR1cm4gZS5zdGFydHNXaXRoKCInIil8fGUuc3RhcnRzV2l0aCgnIicpP2Uuc2xpY2UoMSwtMSk6ZX1mdW5jdGlvbiBnZXRJbnRlZ2VyKHtkYXRhOmUsZGVmYXVsdFZhbHVlOnQsdmFsaWRhdGU6cn0pe2lmKCFlKXJldHVybiB0O2U9ZS50cmltKCk7Y29uc3QgYT1wYXJzZUludChlLDEwKTtyZXR1cm4haXNOYU4oYSkmJnIoYSk/YTp0fWZ1bmN0aW9uIGdldEZsb2F0KHtkYXRhOmUsZGVmYXVsdFZhbHVlOnQsdmFsaWRhdGU6cn0pe2lmKCFlKXJldHVybiB0O2U9ZS50cmltKCk7Y29uc3QgYT1wYXJzZUZsb2F0KGUpO3JldHVybiFpc05hTihhKSYmcihhKT9hOnR9ZnVuY3Rpb24gZ2V0S2V5d29yZCh7ZGF0YTplLGRlZmF1bHRWYWx1ZTp0LHZhbGlkYXRlOnJ9KXtyZXR1cm4gZSYmcihlPWUudHJpbSgpKT9lOnR9ZnVuY3Rpb24gZ2V0U3RyaW5nT3B0aW9uKGUsdCl7cmV0dXJuIGdldEtleXdvcmQoe2RhdGE6ZSxkZWZhdWx0VmFsdWU6dFswXSx2YWxpZGF0ZTplPT50LmluY2x1ZGVzKGUpfSl9ZnVuY3Rpb24gZ2V0TWVhc3VyZW1lbnQoZSx0PSIwIil7dHx8PSIwIjtpZighZSlyZXR1cm4gZ2V0TWVhc3VyZW1lbnQodCk7Y29uc3Qgcj1lLnRyaW0oKS5tYXRjaChybyk7aWYoIXIpcmV0dXJuIGdldE1lYXN1cmVtZW50KHQpO2NvbnN0WyxhLG5dPXIsaT1wYXJzZUZsb2F0KGEpO2lmKGlzTmFOKGkpKXJldHVybiBnZXRNZWFzdXJlbWVudCh0KTtpZigwPT09aSlyZXR1cm4gMDtjb25zdCBzPXRvW25dO3JldHVybiBzP3MoaSk6aX1mdW5jdGlvbiBnZXRSYXRpbyhlKXtpZighZSlyZXR1cm57bnVtOjEsZGVuOjF9O2NvbnN0IHQ9ZS5zcGxpdCgiOiIsMikubWFwKGU9PnBhcnNlRmxvYXQoZS50cmltKCkpKS5maWx0ZXIoZT0+IWlzTmFOKGUpKTsxPT09dC5sZW5ndGgmJnQucHVzaCgxKTtpZigwPT09dC5sZW5ndGgpcmV0dXJue251bToxLGRlbjoxfTtjb25zdFtyLGFdPXQ7cmV0dXJue251bTpyLGRlbjphfX1mdW5jdGlvbiBnZXRSZWxldmFudChlKXtyZXR1cm4gZT9lLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKGU9Pih7ZXhjbHVkZWQ6Ii0iPT09ZVswXSx2aWV3bmFtZTplLnN1YnN0cmluZygxKX0pKTpbXX1jbGFzcyBIVE1MUmVzdWx0e3N0YXRpYyBnZXQgRkFJTFVSRSgpe3JldHVybiBzaGFkb3codGhpcywiRkFJTFVSRSIsbmV3IEhUTUxSZXN1bHQoITEsbnVsbCxudWxsLG51bGwpKX1zdGF0aWMgZ2V0IEVNUFRZKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJFTVBUWSIsbmV3IEhUTUxSZXN1bHQoITAsbnVsbCxudWxsLG51bGwpKX1jb25zdHJ1Y3RvcihlLHQscixhKXt0aGlzLnN1Y2Nlc3M9ZTt0aGlzLmh0bWw9dDt0aGlzLmJib3g9cjt0aGlzLmJyZWFrTm9kZT1hfWlzQnJlYWsoKXtyZXR1cm4hIXRoaXMuYnJlYWtOb2RlfXN0YXRpYyBicmVha05vZGUoZSl7cmV0dXJuIG5ldyBIVE1MUmVzdWx0KCExLG51bGwsbnVsbCxlKX1zdGF0aWMgc3VjY2VzcyhlLHQ9bnVsbCl7cmV0dXJuIG5ldyBIVE1MUmVzdWx0KCEwLGUsdCxudWxsKX19Y2xhc3MgRm9udEZpbmRlcntjb25zdHJ1Y3RvcihlKXt0aGlzLmZvbnRzPW5ldyBNYXA7dGhpcy5jYWNoZT1uZXcgTWFwO3RoaXMud2FybmVkPW5ldyBTZXQ7dGhpcy5kZWZhdWx0Rm9udD1udWxsO3RoaXMuYWRkKGUpfWFkZChlLHQ9bnVsbCl7Zm9yKGNvbnN0IHQgb2YgZSl0aGlzLmFkZFBkZkZvbnQodCk7Zm9yKGNvbnN0IGUgb2YgdGhpcy5mb250cy52YWx1ZXMoKSllLnJlZ3VsYXJ8fChlLnJlZ3VsYXI9ZS5pdGFsaWN8fGUuYm9sZHx8ZS5ib2xkaXRhbGljKTtpZighdHx8MD09PXQuc2l6ZSlyZXR1cm47Y29uc3Qgcj10aGlzLmZvbnRzLmdldCgiUGRmSlMtRmFsbGJhY2stUGRmSlMtWEZBIik7Zm9yKGNvbnN0IGUgb2YgdCl0aGlzLmZvbnRzLnNldChlLHIpfWFkZFBkZkZvbnQoZSl7Y29uc3QgdD1lLmNzc0ZvbnRJbmZvLHI9dC5mb250RmFtaWx5O2xldCBhPXRoaXMuZm9udHMuZ2V0KHIpO2lmKCFhKXthPU9iamVjdC5jcmVhdGUobnVsbCk7dGhpcy5mb250cy5zZXQocixhKTt0aGlzLmRlZmF1bHRGb250fHwodGhpcy5kZWZhdWx0Rm9udD1hKX1sZXQgbj0iIjtjb25zdCBpPXBhcnNlRmxvYXQodC5mb250V2VpZ2h0KTswIT09cGFyc2VGbG9hdCh0Lml0YWxpY0FuZ2xlKT9uPWk+PTcwMD8iYm9sZGl0YWxpYyI6Iml0YWxpYyI6aT49NzAwJiYobj0iYm9sZCIpO2lmKCFuKXsoZS5uYW1lLmluY2x1ZGVzKCJCb2xkIil8fGUucHNOYW1lPy5pbmNsdWRlcygiQm9sZCIpKSYmKG49ImJvbGQiKTsoZS5uYW1lLmluY2x1ZGVzKCJJdGFsaWMiKXx8ZS5uYW1lLmVuZHNXaXRoKCJJdCIpfHxlLnBzTmFtZT8uaW5jbHVkZXMoIkl0YWxpYyIpfHxlLnBzTmFtZT8uZW5kc1dpdGgoIkl0IikpJiYobis9Iml0YWxpYyIpfW58fChuPSJyZWd1bGFyIik7YVtuXT1lfWdldERlZmF1bHQoKXtyZXR1cm4gdGhpcy5kZWZhdWx0Rm9udH1maW5kKGUsdD0hMCl7bGV0IHI9dGhpcy5mb250cy5nZXQoZSl8fHRoaXMuY2FjaGUuZ2V0KGUpO2lmKHIpcmV0dXJuIHI7Y29uc3QgYT0vLHwtfF98IHxib2xkaXRhbGljfGJvbGR8aXRhbGljfHJlZ3VsYXJ8aXQvZ2k7bGV0IG49ZS5yZXBsYWNlQWxsKGEsIiIpO3I9dGhpcy5mb250cy5nZXQobik7aWYocil7dGhpcy5jYWNoZS5zZXQoZSxyKTtyZXR1cm4gcn1uPW4udG9Mb3dlckNhc2UoKTtjb25zdCBpPVtdO2Zvcihjb25zdFtlLHRdb2YgdGhpcy5mb250cy5lbnRyaWVzKCkpZS5yZXBsYWNlQWxsKGEsIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuKSYmaS5wdXNoKHQpO2lmKDA9PT1pLmxlbmd0aClmb3IoY29uc3RbLGVdb2YgdGhpcy5mb250cy5lbnRyaWVzKCkpZS5yZWd1bGFyLm5hbWU/LnJlcGxhY2VBbGwoYSwiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG4pJiZpLnB1c2goZSk7aWYoMD09PWkubGVuZ3RoKXtuPW4ucmVwbGFjZUFsbCgvcHNtdHxtdC9naSwiIik7Zm9yKGNvbnN0W2UsdF1vZiB0aGlzLmZvbnRzLmVudHJpZXMoKSllLnJlcGxhY2VBbGwoYSwiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG4pJiZpLnB1c2godCl9aWYoMD09PWkubGVuZ3RoKWZvcihjb25zdCBlIG9mIHRoaXMuZm9udHMudmFsdWVzKCkpZS5yZWd1bGFyLm5hbWU/LnJlcGxhY2VBbGwoYSwiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG4pJiZpLnB1c2goZSk7aWYoaS5sZW5ndGg+PTEpezEhPT1pLmxlbmd0aCYmdCYmd2FybihgWEZBIC0gVG9vIG1hbnkgY2hvaWNlcyB0byBndWVzcyB0aGUgY29ycmVjdCBmb250OiAke2V9YCk7dGhpcy5jYWNoZS5zZXQoZSxpWzBdKTtyZXR1cm4gaVswXX1pZih0JiYhdGhpcy53YXJuZWQuaGFzKGUpKXt0aGlzLndhcm5lZC5hZGQoZSk7d2FybihgWEZBIC0gQ2Fubm90IGZpbmQgdGhlIGZvbnQ6ICR7ZX1gKX1yZXR1cm4gbnVsbH19ZnVuY3Rpb24gc2VsZWN0Rm9udChlLHQpe3JldHVybiJpdGFsaWMiPT09ZS5wb3N0dXJlPyJib2xkIj09PWUud2VpZ2h0P3QuYm9sZGl0YWxpYzp0Lml0YWxpYzoiYm9sZCI9PT1lLndlaWdodD90LmJvbGQ6dC5yZWd1bGFyfWNsYXNzIHRleHRfRm9udEluZm97Y29uc3RydWN0b3IoZSx0LHIsYSl7dGhpcy5saW5lSGVpZ2h0PXI7dGhpcy5wYXJhTWFyZ2luPXR8fHt0b3A6MCxib3R0b206MCxsZWZ0OjAscmlnaHQ6MH07aWYoIWUpe1t0aGlzLnBkZkZvbnQsdGhpcy54ZmFGb250XT10aGlzLmRlZmF1bHRGb250KGEpO3JldHVybn10aGlzLnhmYUZvbnQ9e3R5cGVmYWNlOmUudHlwZWZhY2UscG9zdHVyZTplLnBvc3R1cmUsd2VpZ2h0OmUud2VpZ2h0LHNpemU6ZS5zaXplLGxldHRlclNwYWNpbmc6ZS5sZXR0ZXJTcGFjaW5nfTtjb25zdCBuPWEuZmluZChlLnR5cGVmYWNlKTtpZihuKXt0aGlzLnBkZkZvbnQ9c2VsZWN0Rm9udChlLG4pO3RoaXMucGRmRm9udHx8KFt0aGlzLnBkZkZvbnQsdGhpcy54ZmFGb250XT10aGlzLmRlZmF1bHRGb250KGEpKX1lbHNlW3RoaXMucGRmRm9udCx0aGlzLnhmYUZvbnRdPXRoaXMuZGVmYXVsdEZvbnQoYSl9ZGVmYXVsdEZvbnQoZSl7Y29uc3QgdD1lLmZpbmQoIkhlbHZldGljYSIsITEpfHxlLmZpbmQoIk15cmlhZCBQcm8iLCExKXx8ZS5maW5kKCJBcmlhbCIsITEpfHxlLmdldERlZmF1bHQoKTtpZih0Py5yZWd1bGFyKXtjb25zdCBlPXQucmVndWxhcjtyZXR1cm5bZSx7dHlwZWZhY2U6ZS5jc3NGb250SW5mby5mb250RmFtaWx5LHBvc3R1cmU6Im5vcm1hbCIsd2VpZ2h0OiJub3JtYWwiLHNpemU6MTAsbGV0dGVyU3BhY2luZzowfV19cmV0dXJuW251bGwse3R5cGVmYWNlOiJDb3VyaWVyIixwb3N0dXJlOiJub3JtYWwiLHdlaWdodDoibm9ybWFsIixzaXplOjEwLGxldHRlclNwYWNpbmc6MH1dfX1jbGFzcyBGb250U2VsZWN0b3J7Y29uc3RydWN0b3IoZSx0LHIsYSl7dGhpcy5mb250RmluZGVyPWE7dGhpcy5zdGFjaz1bbmV3IHRleHRfRm9udEluZm8oZSx0LHIsYSldfXB1c2hEYXRhKGUsdCxyKXtjb25zdCBhPXRoaXMuc3RhY2suYXQoLTEpO2Zvcihjb25zdCB0IG9mWyJ0eXBlZmFjZSIsInBvc3R1cmUiLCJ3ZWlnaHQiLCJzaXplIiwibGV0dGVyU3BhY2luZyJdKWVbdF18fChlW3RdPWEueGZhRm9udFt0XSk7Zm9yKGNvbnN0IGUgb2ZbInRvcCIsImJvdHRvbSIsImxlZnQiLCJyaWdodCJdKWlzTmFOKHRbZV0pJiYodFtlXT1hLnBhcmFNYXJnaW5bZV0pO2NvbnN0IG49bmV3IHRleHRfRm9udEluZm8oZSx0LHJ8fGEubGluZUhlaWdodCx0aGlzLmZvbnRGaW5kZXIpO24ucGRmRm9udHx8KG4ucGRmRm9udD1hLnBkZkZvbnQpO3RoaXMuc3RhY2sucHVzaChuKX1wb3BGb250KCl7dGhpcy5zdGFjay5wb3AoKX10b3BGb250KCl7cmV0dXJuIHRoaXMuc3RhY2suYXQoLTEpfX1jbGFzcyBUZXh0TWVhc3VyZXtjb25zdHJ1Y3RvcihlLHQscixhKXt0aGlzLmdseXBocz1bXTt0aGlzLmZvbnRTZWxlY3Rvcj1uZXcgRm9udFNlbGVjdG9yKGUsdCxyLGEpO3RoaXMuZXh0cmFIZWlnaHQ9MH1wdXNoRGF0YShlLHQscil7dGhpcy5mb250U2VsZWN0b3IucHVzaERhdGEoZSx0LHIpfXBvcEZvbnQoZSl7cmV0dXJuIHRoaXMuZm9udFNlbGVjdG9yLnBvcEZvbnQoKX1hZGRQYXJhKCl7Y29uc3QgZT10aGlzLmZvbnRTZWxlY3Rvci50b3BGb250KCk7dGhpcy5leHRyYUhlaWdodCs9ZS5wYXJhTWFyZ2luLnRvcCtlLnBhcmFNYXJnaW4uYm90dG9tfWFkZFN0cmluZyhlKXtpZighZSlyZXR1cm47Y29uc3QgdD10aGlzLmZvbnRTZWxlY3Rvci50b3BGb250KCkscj10LnhmYUZvbnQuc2l6ZTtpZih0LnBkZkZvbnQpe2NvbnN0IGE9dC54ZmFGb250LmxldHRlclNwYWNpbmcsbj10LnBkZkZvbnQsaT1uLmxpbmVIZWlnaHR8fDEuMixzPXQubGluZUhlaWdodHx8TWF0aC5tYXgoMS4yLGkpKnIsbz1pLSh2b2lkIDA9PT1uLmxpbmVHYXA/LjI6bi5saW5lR2FwKSxjPU1hdGgubWF4KDEsbykqcixsPXIvMWUzLGg9bi5kZWZhdWx0V2lkdGh8fG4uY2hhcnNUb0dseXBocygiICIpWzBdLndpZHRoO2Zvcihjb25zdCB0IG9mIGUuc3BsaXQoL1tcdTIwMjlcbl0vKSl7Y29uc3QgZT1uLmVuY29kZVN0cmluZyh0KS5qb2luKCIiKSxyPW4uY2hhcnNUb0dseXBocyhlKTtmb3IoY29uc3QgZSBvZiByKXtjb25zdCB0PWUud2lkdGh8fGg7dGhpcy5nbHlwaHMucHVzaChbdCpsK2EscyxjLGUudW5pY29kZSwhMV0pfXRoaXMuZ2x5cGhzLnB1c2goWzAsMCwwLCJcbiIsITBdKX10aGlzLmdseXBocy5wb3AoKTtyZXR1cm59Zm9yKGNvbnN0IHQgb2YgZS5zcGxpdCgvW1x1MjAyOVxuXS8pKXtmb3IoY29uc3QgZSBvZiB0LnNwbGl0KCIiKSl0aGlzLmdseXBocy5wdXNoKFtyLDEuMipyLHIsZSwhMV0pO3RoaXMuZ2x5cGhzLnB1c2goWzAsMCwwLCJcbiIsITBdKX10aGlzLmdseXBocy5wb3AoKX1jb21wdXRlKGUpe2xldCB0PS0xLHI9MCxhPTAsbj0wLGk9MCxzPTAsbz0hMSxjPSEwO2ZvcihsZXQgbD0wLGg9dGhpcy5nbHlwaHMubGVuZ3RoO2w8aDtsKyspe2NvbnN0W2gsdSxkLGYsZ109dGhpcy5nbHlwaHNbbF0scD0iICI9PT1mLG09Yz9kOnU7aWYoZyl7YT1NYXRoLm1heChhLGkpO2k9MDtuKz1zO3M9bTt0PS0xO3I9MDtjPSExfWVsc2UgaWYocClpZihpK2g+ZSl7YT1NYXRoLm1heChhLGkpO2k9MDtuKz1zO3M9bTt0PS0xO3I9MDtvPSEwO2M9ITF9ZWxzZXtzPU1hdGgubWF4KG0scyk7cj1pO2krPWg7dD1sfWVsc2UgaWYoaStoPmUpe24rPXM7cz1tO2lmKC0xIT09dCl7bD10O2E9TWF0aC5tYXgoYSxyKTtpPTA7dD0tMTtyPTB9ZWxzZXthPU1hdGgubWF4KGEsaSk7aT1ofW89ITA7Yz0hMX1lbHNle2krPWg7cz1NYXRoLm1heChtLHMpfX1hPU1hdGgubWF4KGEsaSk7bis9cyt0aGlzLmV4dHJhSGVpZ2h0O3JldHVybnt3aWR0aDoxLjAyKmEsaGVpZ2h0Om4saXNCcm9rZW46b319fWNvbnN0IGFvPS9eW14uW10rLyxubz0vXlteXF1dKy8saW89MCxzbz0xLG9vPTIsY289Myxsbz00LGhvPW5ldyBNYXAoW1siJGRhdGEiLChlLHQpPT5lLmRhdGFzZXRzP2UuZGF0YXNldHMuZGF0YTplXSxbIiRyZWNvcmQiLChlLHQpPT4oZS5kYXRhc2V0cz9lLmRhdGFzZXRzLmRhdGE6ZSlbY3NdKClbMF1dLFsiJHRlbXBsYXRlIiwoZSx0KT0+ZS50ZW1wbGF0ZV0sWyIkY29ubmVjdGlvblNldCIsKGUsdCk9PmUuY29ubmVjdGlvblNldF0sWyIkZm9ybSIsKGUsdCk9PmUuZm9ybV0sWyIkbGF5b3V0IiwoZSx0KT0+ZS5sYXlvdXRdLFsiJGhvc3QiLChlLHQpPT5lLmhvc3RdLFsiJGRhdGFXaW5kb3ciLChlLHQpPT5lLmRhdGFXaW5kb3ddLFsiJGV2ZW50IiwoZSx0KT0+ZS5ldmVudF0sWyIhIiwoZSx0KT0+ZS5kYXRhc2V0c10sWyIkeGZhIiwoZSx0KT0+ZV0sWyJ4ZmEiLChlLHQpPT5lXSxbIiQiLChlLHQpPT50XV0pLHVvPW5ldyBXZWFrTWFwO2Z1bmN0aW9uIHBhcnNlSW5kZXgoZSl7cmV0dXJuIioiPT09KGU9ZS50cmltKCkpPzEvMDpwYXJzZUludChlLDEwKXx8MH1mdW5jdGlvbiBwYXJzZUV4cHJlc3Npb24oZSx0LHI9ITApe2xldCBhPWUubWF0Y2goYW8pO2lmKCFhKXJldHVybiBudWxsO2xldFtuXT1hO2NvbnN0IGk9W3tuYW1lOm4sY2FjaGVOYW1lOiIuIituLGluZGV4OjAsanM6bnVsbCxmb3JtQ2FsYzpudWxsLG9wZXJhdG9yOmlvfV07bGV0IHM9bi5sZW5ndGg7Zm9yKDtzPGUubGVuZ3RoOyl7Y29uc3Qgbz1zO2lmKCJbIj09PWUuY2hhckF0KHMrKykpe2E9ZS5zbGljZShzKS5tYXRjaChubyk7aWYoIWEpe3dhcm4oIlhGQSAtIEludmFsaWQgaW5kZXggaW4gU09NIGV4cHJlc3Npb24iKTtyZXR1cm4gbnVsbH1pLmF0KC0xKS5pbmRleD1wYXJzZUluZGV4KGFbMF0pO3MrPWFbMF0ubGVuZ3RoKzE7Y29udGludWV9bGV0IGM7c3dpdGNoKGUuY2hhckF0KHMpKXtjYXNlIi4iOmlmKCF0KXJldHVybiBudWxsO3MrKztjPXNvO2JyZWFrO2Nhc2UiIyI6cysrO2M9b287YnJlYWs7Y2FzZSJbIjppZihyKXt3YXJuKCJYRkEgLSBTT00gZXhwcmVzc2lvbiBjb250YWlucyBhIEZvcm1DYWxjIHN1YmV4cHJlc3Npb24gd2hpY2ggaXMgbm90IHN1cHBvcnRlZCBmb3Igbm93LiIpO3JldHVybiBudWxsfWM9Y287YnJlYWs7Y2FzZSIoIjppZihyKXt3YXJuKCJYRkEgLSBTT00gZXhwcmVzc2lvbiBjb250YWlucyBhIEphdmFTY3JpcHQgc3ViZXhwcmVzc2lvbiB3aGljaCBpcyBub3Qgc3VwcG9ydGVkIGZvciBub3cuIik7cmV0dXJuIG51bGx9Yz1sbzticmVhaztkZWZhdWx0OmM9aW99YT1lLnNsaWNlKHMpLm1hdGNoKGFvKTtpZighYSlicmVhaztbbl09YTtzKz1uLmxlbmd0aDtpLnB1c2goe25hbWU6bixjYWNoZU5hbWU6ZS5zbGljZShvLHMpLG9wZXJhdG9yOmMsaW5kZXg6MCxqczpudWxsLGZvcm1DYWxjOm51bGx9KX1yZXR1cm4gaX1mdW5jdGlvbiBzZWFyY2hOb2RlKGUsdCxyLGE9ITAsbj0hMCl7Y29uc3QgaT1wYXJzZUV4cHJlc3Npb24ocixhKTtpZighaSlyZXR1cm4gbnVsbDtjb25zdCBzPWhvLmdldChpWzBdLm5hbWUpO2xldCBvLGM9MDtpZihzKXtvPSEwO2U9W3MoZSx0KV07Yz0xfWVsc2V7bz1udWxsPT09dDtlPVt0fHxlXX1mb3IobGV0IHI9aS5sZW5ndGg7YzxyO2MrKyl7Y29uc3R7bmFtZTpyLGNhY2hlTmFtZTphLG9wZXJhdG9yOnMsaW5kZXg6bH09aVtjXSxoPVtdO2Zvcihjb25zdCB0IG9mIGUpe2lmKCF0LmlzWEZBT2JqZWN0KWNvbnRpbnVlO2xldCBlLGk7aWYobil7aT11by5nZXQodCk7aWYoIWkpe2k9bmV3IE1hcDt1by5zZXQodCxpKX1lPWkuZ2V0KGEpfWlmKCFlKXtzd2l0Y2gocyl7Y2FzZSBpbzplPXRbYXNdKHIsITEpO2JyZWFrO2Nhc2Ugc286ZT10W2FzXShyLCEwKTticmVhaztjYXNlIG9vOmU9dFtyc10ocik7ZT1lLmlzWEZBT2JqZWN0QXJyYXk/ZS5jaGlsZHJlbjpbZV19biYmaS5zZXQoYSxlKX1lLmxlbmd0aD4wJiZoLnB1c2goZSl9aWYoMD09PWgubGVuZ3RoJiYhbyYmMD09PWMpe2NvbnN0IHI9dFtkc10oKTtpZighKHQ9cikpcmV0dXJuIG51bGw7Yz0tMTtlPVt0XTtjb250aW51ZX1lPWlzRmluaXRlKGwpP2guZmlsdGVyKGU9Pmw8ZS5sZW5ndGgpLm1hcChlPT5lW2xdKTpoLmZsYXQoKX1yZXR1cm4gMD09PWUubGVuZ3RoP251bGw6ZX1mdW5jdGlvbiBjcmVhdGVEYXRhTm9kZShlLHQscil7Y29uc3QgYT1wYXJzZUV4cHJlc3Npb24ocik7aWYoIWEpcmV0dXJuIG51bGw7aWYoYS5zb21lKGU9PmUub3BlcmF0b3I9PT1zbykpcmV0dXJuIG51bGw7Y29uc3Qgbj1oby5nZXQoYVswXS5uYW1lKTtsZXQgaT0wO2lmKG4pe2U9bihlLHQpO2k9MX1lbHNlIGU9dHx8ZTtmb3IobGV0IHQ9YS5sZW5ndGg7aTx0O2krKyl7Y29uc3R7bmFtZTp0LG9wZXJhdG9yOnIsaW5kZXg6bn09YVtpXTtpZighaXNGaW5pdGUobikpe2FbaV0uaW5kZXg9MDtyZXR1cm4gZS5jcmVhdGVOb2RlcyhhLnNsaWNlKGkpKX1sZXQgcztzd2l0Y2gocil7Y2FzZSBpbzpzPWVbYXNdKHQsITEpO2JyZWFrO2Nhc2Ugc286cz1lW2FzXSh0LCEwKTticmVhaztjYXNlIG9vOnM9ZVtyc10odCk7cz1zLmlzWEZBT2JqZWN0QXJyYXk/cy5jaGlsZHJlbjpbc119aWYoMD09PXMubGVuZ3RoKXJldHVybiBlLmNyZWF0ZU5vZGVzKGEuc2xpY2UoaSkpO2lmKCEobjxzLmxlbmd0aCkpe2FbaV0uaW5kZXg9bi1zLmxlbmd0aDtyZXR1cm4gZS5jcmVhdGVOb2RlcyhhLnNsaWNlKGkpKX17Y29uc3QgdD1zW25dO2lmKCF0LmlzWEZBT2JqZWN0KXt3YXJuKCJYRkEgLSBDYW5ub3QgY3JlYXRlIGEgbm9kZS4iKTtyZXR1cm4gbnVsbH1lPXR9fXJldHVybiBudWxsfWNvbnN0IGZvPVN5bWJvbCgpLGdvPVN5bWJvbCgpLHBvPVN5bWJvbCgpLG1vPVN5bWJvbCgiX2NoaWxkcmVuIiksYm89U3ltYm9sKCkseW89U3ltYm9sKCksd289U3ltYm9sKCkseG89U3ltYm9sKCksU289U3ltYm9sKCksQW89U3ltYm9sKCksa289U3ltYm9sKCksQ289U3ltYm9sKCksdm89U3ltYm9sKCksRm89U3ltYm9sKCJwYXJlbnQiKSxJbz1TeW1ib2woKSxPbz1TeW1ib2woKSxNbz1TeW1ib2woKTtsZXQgRG89MDtjb25zdCBCbz1lby5kYXRhc2V0cy5pZDtjbGFzcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSx0LHI9ITEpe3RoaXNbT3NdPWU7dGhpc1tNc109dDt0aGlzW2tvXT1yO3RoaXNbRm9dPW51bGw7dGhpc1ttb109W107dGhpc1tac109YCR7dH0ke0RvKyt9YDt0aGlzW2dzXT1udWxsfWdldCBpc1hGQU9iamVjdCgpe3JldHVybiEwfWdldCBpc1hGQU9iamVjdEFycmF5KCl7cmV0dXJuITF9Y3JlYXRlTm9kZXMoZSl7bGV0IHQ9dGhpcyxyPW51bGw7Zm9yKGNvbnN0e25hbWU6YSxpbmRleDpufW9mIGUpe2ZvcihsZXQgZT0wLGk9aXNGaW5pdGUobik/bjowO2U8PWk7ZSsrKXtjb25zdCBlPXRbT3NdPT09Qm8/LTE6dFtPc107cj1uZXcgWG1sT2JqZWN0KGUsYSk7dFtqaV0ocil9dD1yfXJldHVybiByfVtCc10oZSl7aWYoIXRoaXNba29dfHwhdGhpc1tSc10oZSkpcmV0dXJuITE7Y29uc3QgdD1lW01zXSxyPXRoaXNbdF07aWYoIShyIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpKXtudWxsIT09ciYmdGhpc1tqc10ocik7dGhpc1t0XT1lO3RoaXNbamldKGUpO3JldHVybiEwfWlmKHIucHVzaChlKSl7dGhpc1tqaV0oZSk7cmV0dXJuITB9bGV0IGE9IiI7dGhpcy5pZD9hPWAgKGlkOiAke3RoaXMuaWR9KWA6dGhpcy5uYW1lJiYoYT1gIChuYW1lOiAke3RoaXMubmFtZX0gJHt0aGlzLmgudmFsdWV9KWApO3dhcm4oYFhGQSAtIG5vZGUgIiR7dGhpc1tNc119IiR7YX0gaGFzIGFscmVhZHkgZW5vdWdoICIke3R9IiFgKTtyZXR1cm4hMX1bUnNdKGUpe3JldHVybiB0aGlzLmhhc093blByb3BlcnR5KGVbTXNdKSYmZVtPc109PT10aGlzW09zXX1ba3NdKCl7cmV0dXJuITF9W1BpXSgpe3JldHVybiExfVt3c10oKXtyZXR1cm4hMX1beHNdKCl7cmV0dXJuITF9W19zXSgpe3RoaXMucGFyYSYmdGhpc1tmc10oKVtKaV0ucGFyYVN0YWNrLnBvcCgpfVtMc10oKXt0aGlzW2ZzXSgpW0ppXS5wYXJhU3RhY2sucHVzaCh0aGlzLnBhcmEpfVtIc10oZSl7dGhpcy5pZCYmdGhpc1tPc109PT1lby50ZW1wbGF0ZS5pZCYmZS5zZXQodGhpcy5pZCx0aGlzKX1bZnNdKCl7cmV0dXJuIHRoaXNbZ3NdLnRlbXBsYXRlfVtDc10oKXtyZXR1cm4hMX1bdnNdKCl7cmV0dXJuITF9W2ppXShlKXtlW0ZvXT10aGlzO3RoaXNbbW9dLnB1c2goZSk7IWVbZ3NdJiZ0aGlzW2dzXSYmKGVbZ3NdPXRoaXNbZ3NdKX1banNdKGUpe2NvbnN0IHQ9dGhpc1ttb10uaW5kZXhPZihlKTt0aGlzW21vXS5zcGxpY2UodCwxKX1bcHNdKCl7cmV0dXJuIHRoaXMuaGFzT3duUHJvcGVydHkoInZhbHVlIil9W3pzXShlKXt9W0VzXShlKXt9W1lpXSgpe31bWGldKGUpe2RlbGV0ZSB0aGlzW2tvXTtpZih0aGlzW1dpXSl7ZS5jbGVhbih0aGlzW1dpXSk7ZGVsZXRlIHRoaXNbV2ldfX1bYnNdKGUpe3JldHVybiB0aGlzW21vXS5pbmRleE9mKGUpfVt5c10oZSx0KXt0W0ZvXT10aGlzO3RoaXNbbW9dLnNwbGljZShlLDAsdCk7IXRbZ3NdJiZ0aGlzW2dzXSYmKHRbZ3NdPXRoaXNbZ3NdKX1bRnNdKCl7cmV0dXJuIXRoaXMubmFtZX1bVHNdKCl7cmV0dXJuIiJ9WyRzXSgpe3JldHVybiAwPT09dGhpc1ttb10ubGVuZ3RoP3RoaXNbJGldOnRoaXNbbW9dLm1hcChlPT5lWyRzXSgpKS5qb2luKCIiKX1nZXRbcG9dKCl7Y29uc3QgZT1PYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcyk7aWYoIWUuX2F0dHJpYnV0ZXMpe2NvbnN0IHQ9ZS5fYXR0cmlidXRlcz1uZXcgU2V0O2Zvcihjb25zdCBlIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKXtpZihudWxsPT09dGhpc1tlXXx8dGhpc1tlXWluc3RhbmNlb2YgWEZBT2JqZWN0fHx0aGlzW2VdaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSlicmVhazt0LmFkZChlKX19cmV0dXJuIHNoYWRvdyh0aGlzLHBvLGUuX2F0dHJpYnV0ZXMpfVtBc10oZSl7bGV0IHQ9dGhpcztmb3IoO3Q7KXtpZih0PT09ZSlyZXR1cm4hMDt0PXRbZHNdKCl9cmV0dXJuITF9W2RzXSgpe3JldHVybiB0aGlzW0ZvXX1bdXNdKCl7cmV0dXJuIHRoaXNbZHNdKCl9W2NzXShlPW51bGwpe3JldHVybiBlP3RoaXNbZV06dGhpc1ttb119W0tpXSgpe2NvbnN0IGU9T2JqZWN0LmNyZWF0ZShudWxsKTt0aGlzWyRpXSYmKGUuJGNvbnRlbnQ9dGhpc1skaV0pO2Zvcihjb25zdCB0IG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKXtjb25zdCByPXRoaXNbdF07bnVsbCE9PXImJihyIGluc3RhbmNlb2YgWEZBT2JqZWN0P2VbdF09cltLaV0oKTpyIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXk/ci5pc0VtcHR5KCl8fChlW3RdPXIuZHVtcCgpKTplW3RdPXIpfXJldHVybiBlfVtZc10oKXtyZXR1cm4gbnVsbH1bS3NdKCl7cmV0dXJuIEhUTUxSZXN1bHQuRU1QVFl9Kltsc10oKXtmb3IoY29uc3QgZSBvZiB0aGlzW2NzXSgpKXlpZWxkIGV9Klt4b10oZSx0KXtmb3IoY29uc3QgciBvZiB0aGlzW2xzXSgpKWlmKCFlfHx0PT09ZS5oYXMocltNc10pKXtjb25zdCBlPXRoaXNbdHNdKCksdD1yW0tzXShlKTt0LnN1Y2Nlc3N8fCh0aGlzW0ppXS5mYWlsaW5nTm9kZT1yKTt5aWVsZCB0fX1bWmldKCl7cmV0dXJuIG51bGx9W19pXShlLHQpe3RoaXNbSmldLmNoaWxkcmVuLnB1c2goZSl9W3RzXSgpe31bcWldKHtmaWx0ZXI6ZT1udWxsLGluY2x1ZGU6dD0hMH0pe2lmKHRoaXNbSmldLmdlbmVyYXRvcil7Y29uc3QgZT10aGlzW3RzXSgpLHQ9dGhpc1tKaV0uZmFpbGluZ05vZGVbS3NdKGUpO2lmKCF0LnN1Y2Nlc3MpcmV0dXJuIHQ7dC5odG1sJiZ0aGlzW19pXSh0Lmh0bWwsdC5iYm94KTtkZWxldGUgdGhpc1tKaV0uZmFpbGluZ05vZGV9ZWxzZSB0aGlzW0ppXS5nZW5lcmF0b3I9dGhpc1t4b10oZSx0KTtmb3IoOzspe2NvbnN0IGU9dGhpc1tKaV0uZ2VuZXJhdG9yLm5leHQoKTtpZihlLmRvbmUpYnJlYWs7Y29uc3QgdD1lLnZhbHVlO2lmKCF0LnN1Y2Nlc3MpcmV0dXJuIHQ7dC5odG1sJiZ0aGlzW19pXSh0Lmh0bWwsdC5iYm94KX10aGlzW0ppXS5nZW5lcmF0b3I9bnVsbDtyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWX1bV3NdKGUpe3RoaXNbT29dPW5ldyBTZXQoT2JqZWN0LmtleXMoZSkpfVtBb10oZSl7Y29uc3QgdD10aGlzW3BvXSxyPXRoaXNbT29dO3JldHVyblsuLi5lXS5maWx0ZXIoZT0+dC5oYXMoZSkmJiFyLmhhcyhlKSl9W3FzXShlLHQ9bmV3IFNldCl7Zm9yKGNvbnN0IHIgb2YgdGhpc1ttb10pcltJb10oZSx0KX1bSW9dKGUsdCl7Y29uc3Qgcj10aGlzW1NvXShlLHQpO3I/dGhpc1tmb10ocixlLHQpOnRoaXNbcXNdKGUsdCl9W1NvXShlLHQpe2NvbnN0e3VzZTpyLHVzZWhyZWY6YX09dGhpcztpZighciYmIWEpcmV0dXJuIG51bGw7bGV0IG49bnVsbCxpPW51bGwscz1udWxsLG89cjtpZihhKXtvPWE7YS5zdGFydHNXaXRoKCIjc29tKCIpJiZhLmVuZHNXaXRoKCIpIik/aT1hLnNsaWNlKDUsLTEpOmEuc3RhcnRzV2l0aCgiLiNzb20oIikmJmEuZW5kc1dpdGgoIikiKT9pPWEuc2xpY2UoNiwtMSk6YS5zdGFydHNXaXRoKCIjIik/cz1hLnNsaWNlKDEpOmEuc3RhcnRzV2l0aCgiLiMiKSYmKHM9YS5zbGljZSgyKSl9ZWxzZSByLnN0YXJ0c1dpdGgoIiMiKT9zPXIuc2xpY2UoMSk6aT1yO3RoaXMudXNlPXRoaXMudXNlaHJlZj0iIjtpZihzKW49ZS5nZXQocyk7ZWxzZXtuPXNlYXJjaE5vZGUoZS5nZXQoVXMpLHRoaXMsaSwhMCwhMSk7biYmKG49blswXSl9aWYoIW4pe3dhcm4oYFhGQSAtIEludmFsaWQgcHJvdG90eXBlIHJlZmVyZW5jZTogJHtvfS5gKTtyZXR1cm4gbnVsbH1pZihuW01zXSE9PXRoaXNbTXNdKXt3YXJuKGBYRkEgLSBJbmNvbXBhdGlibGUgcHJvdG90eXBlOiAke25bTXNdfSAhPT0gJHt0aGlzW01zXX0uYCk7cmV0dXJuIG51bGx9aWYodC5oYXMobikpe3dhcm4oIlhGQSAtIEN5Y2xlIGRldGVjdGVkIGluIHByb3RvdHlwZXMgdXNlLiIpO3JldHVybiBudWxsfXQuYWRkKG4pO2NvbnN0IGM9bltTb10oZSx0KTtjJiZuW2ZvXShjLGUsdCk7bltxc10oZSx0KTt0LmRlbGV0ZShuKTtyZXR1cm4gbn1bZm9dKGUsdCxyKXtpZihyLmhhcyhlKSl7d2FybigiWEZBIC0gQ3ljbGUgZGV0ZWN0ZWQgaW4gcHJvdG90eXBlcyB1c2UuIik7cmV0dXJufSF0aGlzWyRpXSYmZVskaV0mJih0aGlzWyRpXT1lWyRpXSk7bmV3IFNldChyKS5hZGQoZSk7Zm9yKGNvbnN0IHQgb2YgdGhpc1tBb10oZVtPb10pKXt0aGlzW3RdPWVbdF07dGhpc1tPb10mJnRoaXNbT29dLmFkZCh0KX1mb3IoY29uc3QgYSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSl7aWYodGhpc1twb10uaGFzKGEpKWNvbnRpbnVlO2NvbnN0IG49dGhpc1thXSxpPWVbYV07aWYobiBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KXtmb3IoY29uc3QgZSBvZiBuW21vXSllW0lvXSh0LHIpO2ZvcihsZXQgYT1uW21vXS5sZW5ndGgscz1pW21vXS5sZW5ndGg7YTxzO2ErKyl7Y29uc3QgaT1lW21vXVthXVt6aV0oKTtpZighbi5wdXNoKGkpKWJyZWFrO2lbRm9dPXRoaXM7dGhpc1ttb10ucHVzaChpKTtpW0lvXSh0LHIpfX1lbHNlIGlmKG51bGw9PT1uKXtpZihudWxsIT09aSl7Y29uc3QgZT1pW3ppXSgpO2VbRm9dPXRoaXM7dGhpc1thXT1lO3RoaXNbbW9dLnB1c2goZSk7ZVtJb10odCxyKX19ZWxzZXtuW3FzXSh0LHIpO2kmJm5bZm9dKGksdCxyKX19fXN0YXRpY1tib10oZSl7cmV0dXJuIEFycmF5LmlzQXJyYXkoZSk/ZS5tYXAoZT0+WEZBT2JqZWN0W2JvXShlKSk6Im9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZT9PYmplY3QuYXNzaWduKHt9LGUpOmV9W3ppXSgpe2NvbnN0IGU9T2JqZWN0LmNyZWF0ZShPYmplY3QuZ2V0UHJvdG90eXBlT2YodGhpcykpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHModGhpcykpdHJ5e2VbdF09dGhpc1t0XX1jYXRjaHtzaGFkb3coZSx0LHRoaXNbdF0pfWVbWnNdPWAke2VbTXNdfSR7RG8rK31gO2VbbW9dPVtdO2Zvcihjb25zdCB0IG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKXtpZih0aGlzW3BvXS5oYXModCkpe2VbdF09WEZBT2JqZWN0W2JvXSh0aGlzW3RdKTtjb250aW51ZX1jb25zdCByPXRoaXNbdF07ZVt0XT1yIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXk/bmV3IFhGQU9iamVjdEFycmF5KHJbQ29dKTpudWxsfWZvcihjb25zdCB0IG9mIHRoaXNbbW9dKXtjb25zdCByPXRbTXNdLGE9dFt6aV0oKTtlW21vXS5wdXNoKGEpO2FbRm9dPWU7bnVsbD09PWVbcl0/ZVtyXT1hOmVbcl1bbW9dLnB1c2goYSl9cmV0dXJuIGV9W2NzXShlPW51bGwpe3JldHVybiBlP3RoaXNbbW9dLmZpbHRlcih0PT50W01zXT09PWUpOnRoaXNbbW9dfVtyc10oZSl7cmV0dXJuIHRoaXNbZV19W2FzXShlLHQscj0hMCl7cmV0dXJuIEFycmF5LmZyb20odGhpc1tuc10oZSx0LHIpKX0qW25zXShlLHQscj0hMCl7aWYoInBhcmVudCIhPT1lKXtmb3IoY29uc3QgciBvZiB0aGlzW21vXSl7cltNc109PT1lJiYoeWllbGQgcik7ci5uYW1lPT09ZSYmKHlpZWxkIHIpOyh0fHxyW0ZzXSgpKSYmKHlpZWxkKnJbbnNdKGUsdCwhMSkpfXImJnRoaXNbcG9dLmhhcyhlKSYmKHlpZWxkIG5ldyBYRkFBdHRyaWJ1dGUodGhpcyxlLHRoaXNbZV0pKX1lbHNlIHlpZWxkIHRoaXNbRm9dfX1jbGFzcyBYRkFPYmplY3RBcnJheXtjb25zdHJ1Y3RvcihlPTEvMCl7dGhpc1tDb109ZTt0aGlzW21vXT1bXX1nZXQgaXNYRkFPYmplY3QoKXtyZXR1cm4hMX1nZXQgaXNYRkFPYmplY3RBcnJheSgpe3JldHVybiEwfXB1c2goZSl7aWYodGhpc1ttb10ubGVuZ3RoPD10aGlzW0NvXSl7dGhpc1ttb10ucHVzaChlKTtyZXR1cm4hMH13YXJuKGBYRkEgLSBub2RlICIke2VbTXNdfSIgYWNjZXB0cyBubyBtb3JlIHRoYW4gJHt0aGlzW0NvXX0gY2hpbGRyZW5gKTtyZXR1cm4hMX1pc0VtcHR5KCl7cmV0dXJuIDA9PT10aGlzW21vXS5sZW5ndGh9ZHVtcCgpe3JldHVybiAxPT09dGhpc1ttb10ubGVuZ3RoP3RoaXNbbW9dWzBdW0tpXSgpOnRoaXNbbW9dLm1hcChlPT5lW0tpXSgpKX1bemldKCl7Y29uc3QgZT1uZXcgWEZBT2JqZWN0QXJyYXkodGhpc1tDb10pO2VbbW9dPXRoaXNbbW9dLm1hcChlPT5lW3ppXSgpKTtyZXR1cm4gZX1nZXQgY2hpbGRyZW4oKXtyZXR1cm4gdGhpc1ttb119Y2xlYXIoKXt0aGlzW21vXS5sZW5ndGg9MH19Y2xhc3MgWEZBQXR0cmlidXRle2NvbnN0cnVjdG9yKGUsdCxyKXt0aGlzW0ZvXT1lO3RoaXNbTXNdPXQ7dGhpc1skaV09cjt0aGlzW0dpXT0hMTt0aGlzW1pzXT0iYXR0cmlidXRlIitEbysrfVtkc10oKXtyZXR1cm4gdGhpc1tGb119W1NzXSgpe3JldHVybiEwfVtpc10oKXtyZXR1cm4gdGhpc1skaV0udHJpbSgpfVt6c10oZSl7ZT1lLnZhbHVlfHwiIjt0aGlzWyRpXT1lLnRvU3RyaW5nKCl9WyRzXSgpe3JldHVybiB0aGlzWyRpXX1bQXNdKGUpe3JldHVybiB0aGlzW0ZvXT09PWV8fHRoaXNbRm9dW0FzXShlKX19Y2xhc3MgWG1sT2JqZWN0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUsdCxyPXt9KXtzdXBlcihlLHQpO3RoaXNbJGldPSIiO3RoaXNbeW9dPW51bGw7aWYoIiN0ZXh0IiE9PXQpe2NvbnN0IGU9bmV3IE1hcDt0aGlzW2dvXT1lO2Zvcihjb25zdFt0LGFdb2YgT2JqZWN0LmVudHJpZXMocikpZS5zZXQodCxuZXcgWEZBQXR0cmlidXRlKHRoaXMsdCxhKSk7aWYoci5oYXNPd25Qcm9wZXJ0eShEcykpe2NvbnN0IGU9cltEc10ueGZhLmRhdGFOb2RlO3ZvaWQgMCE9PWUmJigiZGF0YUdyb3VwIj09PWU/dGhpc1t5b109ITE6ImRhdGFWYWx1ZSI9PT1lJiYodGhpc1t5b109ITApKX19dGhpc1tHaV09ITF9W0pzXShlKXtjb25zdCB0PXRoaXNbTXNdO2lmKCIjdGV4dCI9PT10KXtlLnB1c2goZW5jb2RlVG9YbWxTdHJpbmcodGhpc1skaV0pKTtyZXR1cm59Y29uc3Qgcj11dGY4U3RyaW5nVG9TdHJpbmcodCksYT10aGlzW09zXT09PUJvPyJ4ZmE6IjoiIjtlLnB1c2goYDwke2F9JHtyfWApO2Zvcihjb25zdFt0LHJdb2YgdGhpc1tnb10uZW50cmllcygpKXtjb25zdCBhPXV0ZjhTdHJpbmdUb1N0cmluZyh0KTtlLnB1c2goYCAke2F9PSIke2VuY29kZVRvWG1sU3RyaW5nKHJbJGldKX0iYCl9bnVsbCE9PXRoaXNbeW9dJiYodGhpc1t5b10/ZS5wdXNoKCcgeGZhOmRhdGFOb2RlPSJkYXRhVmFsdWUiJyk6ZS5wdXNoKCcgeGZhOmRhdGFOb2RlPSJkYXRhR3JvdXAiJykpO2lmKHRoaXNbJGldfHwwIT09dGhpc1ttb10ubGVuZ3RoKXtlLnB1c2goIj4iKTtpZih0aGlzWyRpXSkic3RyaW5nIj09dHlwZW9mIHRoaXNbJGldP2UucHVzaChlbmNvZGVUb1htbFN0cmluZyh0aGlzWyRpXSkpOnRoaXNbJGldW0pzXShlKTtlbHNlIGZvcihjb25zdCB0IG9mIHRoaXNbbW9dKXRbSnNdKGUpO2UucHVzaChgPC8ke2F9JHtyfT5gKX1lbHNlIGUucHVzaCgiLz4iKX1bQnNdKGUpe2lmKHRoaXNbJGldKXtjb25zdCBlPW5ldyBYbWxPYmplY3QodGhpc1tPc10sIiN0ZXh0Iik7dGhpc1tqaV0oZSk7ZVskaV09dGhpc1skaV07dGhpc1skaV09IiJ9dGhpc1tqaV0oZSk7cmV0dXJuITB9W0VzXShlKXt0aGlzWyRpXSs9ZX1bWWldKCl7aWYodGhpc1skaV0mJnRoaXNbbW9dLmxlbmd0aD4wKXtjb25zdCBlPW5ldyBYbWxPYmplY3QodGhpc1tPc10sIiN0ZXh0Iik7dGhpc1tqaV0oZSk7ZVskaV09dGhpc1skaV07ZGVsZXRlIHRoaXNbJGldfX1bS3NdKCl7cmV0dXJuIiN0ZXh0Ij09PXRoaXNbTXNdP0hUTUxSZXN1bHQuc3VjY2Vzcyh7bmFtZToiI3RleHQiLHZhbHVlOnRoaXNbJGldfSk6SFRNTFJlc3VsdC5FTVBUWX1bY3NdKGU9bnVsbCl7cmV0dXJuIGU/dGhpc1ttb10uZmlsdGVyKHQ9PnRbTXNdPT09ZSk6dGhpc1ttb119W2VzXSgpe3JldHVybiB0aGlzW2dvXX1bcnNdKGUpe2NvbnN0IHQ9dGhpc1tnb10uZ2V0KGUpO3JldHVybiB2b2lkIDAhPT10P3Q6dGhpc1tjc10oZSl9Kltuc10oZSx0KXtjb25zdCByPXRoaXNbZ29dLmdldChlKTtyJiYoeWllbGQgcik7Zm9yKGNvbnN0IHIgb2YgdGhpc1ttb10pe3JbTXNdPT09ZSYmKHlpZWxkIHIpO3QmJih5aWVsZCpyW25zXShlLHQpKX19KltRaV0oZSx0KXtjb25zdCByPXRoaXNbZ29dLmdldChlKTshcnx8dCYmcltHaV18fCh5aWVsZCByKTtmb3IoY29uc3QgciBvZiB0aGlzW21vXSl5aWVsZCpyW1FpXShlLHQpfSpbb3NdKGUsdCxyKXtmb3IoY29uc3QgYSBvZiB0aGlzW21vXSl7YVtNc10hPT1lfHxyJiZhW0dpXXx8KHlpZWxkIGEpO3QmJih5aWVsZCphW29zXShlLHQscikpfX1bU3NdKCl7cmV0dXJuIG51bGw9PT10aGlzW3lvXT8wPT09dGhpc1ttb10ubGVuZ3RofHx0aGlzW21vXVswXVtPc109PT1lby54aHRtbC5pZDp0aGlzW3lvXX1baXNdKCl7cmV0dXJuIG51bGw9PT10aGlzW3lvXT8wPT09dGhpc1ttb10ubGVuZ3RoP3RoaXNbJGldLnRyaW0oKTp0aGlzW21vXVswXVtPc109PT1lby54aHRtbC5pZD90aGlzW21vXVswXVskc10oKS50cmltKCk6bnVsbDp0aGlzWyRpXS50cmltKCl9W3pzXShlKXtlPWUudmFsdWV8fCIiO3RoaXNbJGldPWUudG9TdHJpbmcoKX1bS2ldKGU9ITEpe2NvbnN0IHQ9T2JqZWN0LmNyZWF0ZShudWxsKTtlJiYodC4kbnM9dGhpc1tPc10pO3RoaXNbJGldJiYodC4kY29udGVudD10aGlzWyRpXSk7dC4kbmFtZT10aGlzW01zXTt0LmNoaWxkcmVuPVtdO2Zvcihjb25zdCByIG9mIHRoaXNbbW9dKXQuY2hpbGRyZW4ucHVzaChyW0tpXShlKSk7dC5hdHRyaWJ1dGVzPU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGNvbnN0W2Uscl1vZiB0aGlzW2dvXSl0LmF0dHJpYnV0ZXNbZV09clskaV07cmV0dXJuIHR9fWNsYXNzIENvbnRlbnRPYmplY3QgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihlLHQpO3RoaXNbJGldPSIifVtFc10oZSl7dGhpc1skaV0rPWV9W1lpXSgpe319Y2xhc3MgT3B0aW9uT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlLHQscil7c3VwZXIoZSx0KTt0aGlzW3ZvXT1yfVtZaV0oKXt0aGlzWyRpXT1nZXRLZXl3b3JkKHtkYXRhOnRoaXNbJGldLGRlZmF1bHRWYWx1ZTp0aGlzW3ZvXVswXSx2YWxpZGF0ZTplPT50aGlzW3ZvXS5pbmNsdWRlcyhlKX0pfVtYaV0oZSl7c3VwZXJbWGldKGUpO2RlbGV0ZSB0aGlzW3ZvXX19Y2xhc3MgU3RyaW5nT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdHtbWWldKCl7dGhpc1skaV09dGhpc1skaV0udHJpbSgpfX1jbGFzcyBJbnRlZ2VyT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlLHQscixhKXtzdXBlcihlLHQpO3RoaXNbd29dPXI7dGhpc1tNb109YX1bWWldKCl7dGhpc1skaV09Z2V0SW50ZWdlcih7ZGF0YTp0aGlzWyRpXSxkZWZhdWx0VmFsdWU6dGhpc1t3b10sdmFsaWRhdGU6dGhpc1tNb119KX1bWGldKGUpe3N1cGVyW1hpXShlKTtkZWxldGUgdGhpc1t3b107ZGVsZXRlIHRoaXNbTW9dfX1jbGFzcyBPcHRpb24wMSBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSx0KXtzdXBlcihlLHQsMCxlPT4xPT09ZSl9fWNsYXNzIE9wdGlvbjEwIGV4dGVuZHMgSW50ZWdlck9iamVjdHtjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKGUsdCwxLGU9PjA9PT1lKX19ZnVuY3Rpb24gbWVhc3VyZVRvU3RyaW5nKGUpe3JldHVybiJzdHJpbmciPT10eXBlb2YgZT8iMHB4IjpOdW1iZXIuaXNJbnRlZ2VyKGUpP2Ake2V9cHhgOmAke2UudG9GaXhlZCgyKX1weGB9Y29uc3QgUm89e2FuY2hvclR5cGUoZSx0KXtjb25zdCByPWVbdXNdKCk7aWYociYmKCFyLmxheW91dHx8InBvc2l0aW9uIj09PXIubGF5b3V0KSl7InRyYW5zZm9ybSJpbiB0fHwodC50cmFuc2Zvcm09IiIpO3N3aXRjaChlLmFuY2hvclR5cGUpe2Nhc2UiYm90dG9tQ2VudGVyIjp0LnRyYW5zZm9ybSs9InRyYW5zbGF0ZSgtNTAlLCAtMTAwJSkiO2JyZWFrO2Nhc2UiYm90dG9tTGVmdCI6dC50cmFuc2Zvcm0rPSJ0cmFuc2xhdGUoMCwtMTAwJSkiO2JyZWFrO2Nhc2UiYm90dG9tUmlnaHQiOnQudHJhbnNmb3JtKz0idHJhbnNsYXRlKC0xMDAlLC0xMDAlKSI7YnJlYWs7Y2FzZSJtaWRkbGVDZW50ZXIiOnQudHJhbnNmb3JtKz0idHJhbnNsYXRlKC01MCUsLTUwJSkiO2JyZWFrO2Nhc2UibWlkZGxlTGVmdCI6dC50cmFuc2Zvcm0rPSJ0cmFuc2xhdGUoMCwtNTAlKSI7YnJlYWs7Y2FzZSJtaWRkbGVSaWdodCI6dC50cmFuc2Zvcm0rPSJ0cmFuc2xhdGUoLTEwMCUsLTUwJSkiO2JyZWFrO2Nhc2UidG9wQ2VudGVyIjp0LnRyYW5zZm9ybSs9InRyYW5zbGF0ZSgtNTAlLDApIjticmVhaztjYXNlInRvcFJpZ2h0Ijp0LnRyYW5zZm9ybSs9InRyYW5zbGF0ZSgtMTAwJSwwKSJ9fX0sZGltZW5zaW9ucyhlLHQpe2NvbnN0IHI9ZVt1c10oKTtsZXQgYT1lLnc7Y29uc3Qgbj1lLmg7aWYoci5sYXlvdXQ/LmluY2x1ZGVzKCJyb3ciKSl7Y29uc3QgdD1yW0ppXSxuPWUuY29sU3BhbjtsZXQgaTtpZigtMT09PW4pe2k9TWF0aC5zdW1QcmVjaXNlKHQuY29sdW1uV2lkdGhzLnNsaWNlKHQuY3VycmVudENvbHVtbikpO3QuY3VycmVudENvbHVtbj0wfWVsc2V7aT1NYXRoLnN1bVByZWNpc2UodC5jb2x1bW5XaWR0aHMuc2xpY2UodC5jdXJyZW50Q29sdW1uLHQuY3VycmVudENvbHVtbituKSk7dC5jdXJyZW50Q29sdW1uPSh0LmN1cnJlbnRDb2x1bW4rZS5jb2xTcGFuKSV0LmNvbHVtbldpZHRocy5sZW5ndGh9aXNOYU4oaSl8fChhPWUudz1pKX10LndpZHRoPSIiIT09YT9tZWFzdXJlVG9TdHJpbmcoYSk6ImF1dG8iO3QuaGVpZ2h0PSIiIT09bj9tZWFzdXJlVG9TdHJpbmcobik6ImF1dG8ifSxwb3NpdGlvbihlLHQpe2NvbnN0IHI9ZVt1c10oKTtpZighcj8ubGF5b3V0fHwicG9zaXRpb24iPT09ci5sYXlvdXQpe3QucG9zaXRpb249ImFic29sdXRlIjt0LmxlZnQ9bWVhc3VyZVRvU3RyaW5nKGUueCk7dC50b3A9bWVhc3VyZVRvU3RyaW5nKGUueSl9fSxyb3RhdGUoZSx0KXtpZihlLnJvdGF0ZSl7InRyYW5zZm9ybSJpbiB0fHwodC50cmFuc2Zvcm09IiIpO3QudHJhbnNmb3JtKz1gcm90YXRlKC0ke2Uucm90YXRlfWRlZylgO3QudHJhbnNmb3JtT3JpZ2luPSJ0b3AgbGVmdCJ9fSxwcmVzZW5jZShlLHQpe3N3aXRjaChlLnByZXNlbmNlKXtjYXNlImludmlzaWJsZSI6dC52aXNpYmlsaXR5PSJoaWRkZW4iO2JyZWFrO2Nhc2UiaGlkZGVuIjpjYXNlImluYWN0aXZlIjp0LmRpc3BsYXk9Im5vbmUifX0saEFsaWduKGUsdCl7aWYoInBhcmEiPT09ZVtNc10pc3dpdGNoKGUuaEFsaWduKXtjYXNlImp1c3RpZnlBbGwiOnQudGV4dEFsaWduPSJqdXN0aWZ5LWFsbCI7YnJlYWs7Y2FzZSJyYWRpeCI6dC50ZXh0QWxpZ249ImxlZnQiO2JyZWFrO2RlZmF1bHQ6dC50ZXh0QWxpZ249ZS5oQWxpZ259ZWxzZSBzd2l0Y2goZS5oQWxpZ24pe2Nhc2UibGVmdCI6dC5hbGlnblNlbGY9InN0YXJ0IjticmVhaztjYXNlImNlbnRlciI6dC5hbGlnblNlbGY9ImNlbnRlciI7YnJlYWs7Y2FzZSJyaWdodCI6dC5hbGlnblNlbGY9ImVuZCJ9fSxtYXJnaW4oZSx0KXtlLm1hcmdpbiYmKHQubWFyZ2luPWUubWFyZ2luW1lzXSgpLm1hcmdpbil9fTtmdW5jdGlvbiBzZXRNaW5NYXhEaW1lbnNpb25zKGUsdCl7aWYoInBvc2l0aW9uIj09PWVbdXNdKCkubGF5b3V0KXtlLm1pblc+MCYmKHQubWluV2lkdGg9bWVhc3VyZVRvU3RyaW5nKGUubWluVykpO2UubWF4Vz4wJiYodC5tYXhXaWR0aD1tZWFzdXJlVG9TdHJpbmcoZS5tYXhXKSk7ZS5taW5IPjAmJih0Lm1pbkhlaWdodD1tZWFzdXJlVG9TdHJpbmcoZS5taW5IKSk7ZS5tYXhIPjAmJih0Lm1heEhlaWdodD1tZWFzdXJlVG9TdHJpbmcoZS5tYXhIKSl9fWZ1bmN0aW9uIGxheW91dFRleHQoZSx0LHIsYSxuLGkpe2NvbnN0IHM9bmV3IFRleHRNZWFzdXJlKHQscixhLG4pOyJzdHJpbmciPT10eXBlb2YgZT9zLmFkZFN0cmluZyhlKTplW05zXShzKTtyZXR1cm4gcy5jb21wdXRlKGkpfWZ1bmN0aW9uIGxheW91dE5vZGUoZSx0KXtsZXQgcj1udWxsLGE9bnVsbCxuPSExO2lmKCghZS53fHwhZS5oKSYmZS52YWx1ZSl7bGV0IGk9MCxzPTA7aWYoZS5tYXJnaW4pe2k9ZS5tYXJnaW4ubGVmdEluc2V0K2UubWFyZ2luLnJpZ2h0SW5zZXQ7cz1lLm1hcmdpbi50b3BJbnNldCtlLm1hcmdpbi5ib3R0b21JbnNldH1sZXQgbz1udWxsLGM9bnVsbDtpZihlLnBhcmEpe2M9T2JqZWN0LmNyZWF0ZShudWxsKTtvPSIiPT09ZS5wYXJhLmxpbmVIZWlnaHQ/bnVsbDplLnBhcmEubGluZUhlaWdodDtjLnRvcD0iIj09PWUucGFyYS5zcGFjZUFib3ZlPzA6ZS5wYXJhLnNwYWNlQWJvdmU7Yy5ib3R0b209IiI9PT1lLnBhcmEuc3BhY2VCZWxvdz8wOmUucGFyYS5zcGFjZUJlbG93O2MubGVmdD0iIj09PWUucGFyYS5tYXJnaW5MZWZ0PzA6ZS5wYXJhLm1hcmdpbkxlZnQ7Yy5yaWdodD0iIj09PWUucGFyYS5tYXJnaW5SaWdodD8wOmUucGFyYS5tYXJnaW5SaWdodH1sZXQgbD1lLmZvbnQ7aWYoIWwpe2NvbnN0IHQ9ZVtmc10oKTtsZXQgcj1lW2RzXSgpO2Zvcig7ciYmciE9PXQ7KXtpZihyLmZvbnQpe2w9ci5mb250O2JyZWFrfXI9cltkc10oKX19Y29uc3QgaD0oZS53fHx0LndpZHRoKS1pLHU9ZVtnc10uZm9udEZpbmRlcjtpZihlLnZhbHVlLmV4RGF0YSYmZS52YWx1ZS5leERhdGFbJGldJiYidGV4dC9odG1sIj09PWUudmFsdWUuZXhEYXRhLmNvbnRlbnRUeXBlKXtjb25zdCB0PWxheW91dFRleHQoZS52YWx1ZS5leERhdGFbJGldLGwsYyxvLHUsaCk7YT10LndpZHRoO3I9dC5oZWlnaHQ7bj10LmlzQnJva2VufWVsc2V7Y29uc3QgdD1lLnZhbHVlWyRzXSgpO2lmKHQpe2NvbnN0IGU9bGF5b3V0VGV4dCh0LGwsYyxvLHUsaCk7YT1lLndpZHRoO3I9ZS5oZWlnaHQ7bj1lLmlzQnJva2VufX1udWxsPT09YXx8ZS53fHwoYSs9aSk7bnVsbD09PXJ8fGUuaHx8KHIrPXMpfXJldHVybnt3OmEsaDpyLGlzQnJva2VuOm59fWZ1bmN0aW9uIGNvbXB1dGVCYm94KGUsdCxyKXtsZXQgYTtpZigiIiE9PWUudyYmIiIhPT1lLmgpYT1bZS54LGUueSxlLncsZS5oXTtlbHNle2lmKCFyKXJldHVybiBudWxsO2xldCBuPWUudztpZigiIj09PW4pe2lmKDA9PT1lLm1heFcpe2NvbnN0IHQ9ZVt1c10oKTtuPSJwb3NpdGlvbiI9PT10LmxheW91dCYmIiIhPT10Lnc/MDplLm1pbld9ZWxzZSBuPU1hdGgubWluKGUubWF4VyxyLndpZHRoKTt0LmF0dHJpYnV0ZXMuc3R5bGUud2lkdGg9bWVhc3VyZVRvU3RyaW5nKG4pfWxldCBpPWUuaDtpZigiIj09PWkpe2lmKDA9PT1lLm1heEgpe2NvbnN0IHQ9ZVt1c10oKTtpPSJwb3NpdGlvbiI9PT10LmxheW91dCYmIiIhPT10Lmg/MDplLm1pbkh9ZWxzZSBpPU1hdGgubWluKGUubWF4SCxyLmhlaWdodCk7dC5hdHRyaWJ1dGVzLnN0eWxlLmhlaWdodD1tZWFzdXJlVG9TdHJpbmcoaSl9YT1bZS54LGUueSxuLGldfXJldHVybiBhfWZ1bmN0aW9uIGZpeERpbWVuc2lvbnMoZSl7Y29uc3QgdD1lW3VzXSgpO2lmKHQubGF5b3V0Py5pbmNsdWRlcygicm93Iikpe2NvbnN0IHI9dFtKaV0sYT1lLmNvbFNwYW47bGV0IG47bj0tMT09PWE/TWF0aC5zdW1QcmVjaXNlKHIuY29sdW1uV2lkdGhzLnNsaWNlKHIuY3VycmVudENvbHVtbikpOk1hdGguc3VtUHJlY2lzZShyLmNvbHVtbldpZHRocy5zbGljZShyLmN1cnJlbnRDb2x1bW4sci5jdXJyZW50Q29sdW1uK2EpKTtpc05hTihuKXx8KGUudz1uKX10LmxheW91dCYmInBvc2l0aW9uIiE9PXQubGF5b3V0JiYoZS54PWUueT0wKTsidGFibGUiPT09ZS5sYXlvdXQmJiIiPT09ZS53JiZBcnJheS5pc0FycmF5KGUuY29sdW1uV2lkdGhzKSYmKGUudz1NYXRoLnN1bVByZWNpc2UoZS5jb2x1bW5XaWR0aHMpKX1mdW5jdGlvbiBsYXlvdXRDbGFzcyhlKXtzd2l0Y2goZS5sYXlvdXQpe2Nhc2UicG9zaXRpb24iOmRlZmF1bHQ6cmV0dXJuInhmYVBvc2l0aW9uIjtjYXNlImxyLXRiIjpyZXR1cm4ieGZhTHJUYiI7Y2FzZSJybC1yb3ciOnJldHVybiJ4ZmFSbFJvdyI7Y2FzZSJybC10YiI6cmV0dXJuInhmYVJsVGIiO2Nhc2Uicm93IjpyZXR1cm4ieGZhUm93IjtjYXNlInRhYmxlIjpyZXR1cm4ieGZhVGFibGUiO2Nhc2UidGIiOnJldHVybiJ4ZmFUYiJ9fWZ1bmN0aW9uIHRvU3R5bGUoZSwuLi50KXtjb25zdCByPU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGNvbnN0IGEgb2YgdCl7Y29uc3QgdD1lW2FdO2lmKG51bGwhPT10KWlmKFJvLmhhc093blByb3BlcnR5KGEpKVJvW2FdKGUscik7ZWxzZSBpZih0IGluc3RhbmNlb2YgWEZBT2JqZWN0KXtjb25zdCBlPXRbWXNdKCk7ZT9PYmplY3QuYXNzaWduKHIsZSk6d2FybihgKERFQlVHKSAtIFhGQSAtIHN0eWxlIGZvciAke2F9IG5vdCBpbXBsZW1lbnRlZCB5ZXRgKX19cmV0dXJuIHJ9ZnVuY3Rpb24gY3JlYXRlV3JhcHBlcihlLHQpe2NvbnN0e2F0dHJpYnV0ZXM6cn09dCx7c3R5bGU6YX09cixuPXtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhV3JhcHBlciJdLHN0eWxlOk9iamVjdC5jcmVhdGUobnVsbCl9LGNoaWxkcmVuOltdfTtyLmNsYXNzLnB1c2goInhmYVdyYXBwZWQiKTtpZihlLmJvcmRlcil7Y29uc3R7d2lkdGhzOnIsaW5zZXRzOml9PWUuYm9yZGVyW0ppXTtsZXQgcyxvLGM9aVswXSxsPWlbM107Y29uc3QgaD1pWzBdK2lbMl0sdT1pWzFdK2lbM107c3dpdGNoKGUuYm9yZGVyLmhhbmQpe2Nhc2UiZXZlbiI6Yy09clswXS8yO2wtPXJbM10vMjtzPWBjYWxjKDEwMCUgKyAkeyhyWzFdK3JbM10pLzItdX1weClgO289YGNhbGMoMTAwJSArICR7KHJbMF0rclsyXSkvMi1ofXB4KWA7YnJlYWs7Y2FzZSJsZWZ0IjpjLT1yWzBdO2wtPXJbM107cz1gY2FsYygxMDAlICsgJHtyWzFdK3JbM10tdX1weClgO289YGNhbGMoMTAwJSArICR7clswXStyWzJdLWh9cHgpYDticmVhaztjYXNlInJpZ2h0IjpzPXU/YGNhbGMoMTAwJSAtICR7dX1weClgOiIxMDAlIjtvPWg/YGNhbGMoMTAwJSAtICR7aH1weClgOiIxMDAlIn1jb25zdCBkPVsieGZhQm9yZGVyIl07aXNQcmludE9ubHkoZS5ib3JkZXIpJiZkLnB1c2goInhmYVByaW50T25seSIpO2NvbnN0IGY9e25hbWU6ImRpdiIsYXR0cmlidXRlczp7Y2xhc3M6ZCxzdHlsZTp7dG9wOmAke2N9cHhgLGxlZnQ6YCR7bH1weGAsd2lkdGg6cyxoZWlnaHQ6b319LGNoaWxkcmVuOltdfTtmb3IoY29uc3QgZSBvZlsiYm9yZGVyIiwiYm9yZGVyV2lkdGgiLCJib3JkZXJDb2xvciIsImJvcmRlclJhZGl1cyIsImJvcmRlclN0eWxlIl0paWYodm9pZCAwIT09YVtlXSl7Zi5hdHRyaWJ1dGVzLnN0eWxlW2VdPWFbZV07ZGVsZXRlIGFbZV19bi5jaGlsZHJlbi5wdXNoKGYsdCl9ZWxzZSBuLmNoaWxkcmVuLnB1c2godCk7Zm9yKGNvbnN0IGUgb2ZbImJhY2tncm91bmQiLCJiYWNrZ3JvdW5kQ2xpcCIsInRvcCIsImxlZnQiLCJ3aWR0aCIsImhlaWdodCIsIm1pbldpZHRoIiwibWluSGVpZ2h0IiwibWF4V2lkdGgiLCJtYXhIZWlnaHQiLCJ0cmFuc2Zvcm0iLCJ0cmFuc2Zvcm1PcmlnaW4iLCJ2aXNpYmlsaXR5Il0paWYodm9pZCAwIT09YVtlXSl7bi5hdHRyaWJ1dGVzLnN0eWxlW2VdPWFbZV07ZGVsZXRlIGFbZV19bi5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uPSJhYnNvbHV0ZSI9PT1hLnBvc2l0aW9uPyJhYnNvbHV0ZSI6InJlbGF0aXZlIjtkZWxldGUgYS5wb3NpdGlvbjtpZihhLmFsaWduU2VsZil7bi5hdHRyaWJ1dGVzLnN0eWxlLmFsaWduU2VsZj1hLmFsaWduU2VsZjtkZWxldGUgYS5hbGlnblNlbGZ9cmV0dXJuIG59ZnVuY3Rpb24gZml4VGV4dEluZGVudChlKXtjb25zdCB0PWdldE1lYXN1cmVtZW50KGUudGV4dEluZGVudCwiMHB4Iik7aWYodD49MClyZXR1cm47Y29uc3Qgcj0icGFkZGluZyIrKCJsZWZ0Ij09PSgicmlnaHQiPT09ZS50ZXh0QWxpZ24/InJpZ2h0IjoibGVmdCIpPyJMZWZ0IjoiUmlnaHQiKSxhPWdldE1lYXN1cmVtZW50KGVbcl0sIjBweCIpO2Vbcl09YS10KyJweCJ9ZnVuY3Rpb24gc2V0QWNjZXNzKGUsdCl7c3dpdGNoKGUuYWNjZXNzKXtjYXNlIm5vbkludGVyYWN0aXZlIjp0LnB1c2goInhmYU5vbkludGVyYWN0aXZlIik7YnJlYWs7Y2FzZSJyZWFkT25seSI6dC5wdXNoKCJ4ZmFSZWFkT25seSIpO2JyZWFrO2Nhc2UicHJvdGVjdGVkIjp0LnB1c2goInhmYURpc2FibGVkIil9fWZ1bmN0aW9uIGlzUHJpbnRPbmx5KGUpe3JldHVybiBlLnJlbGV2YW50Lmxlbmd0aD4wJiYhZS5yZWxldmFudFswXS5leGNsdWRlZCYmInByaW50Ij09PWUucmVsZXZhbnRbMF0udmlld25hbWV9ZnVuY3Rpb24gZ2V0Q3VycmVudFBhcmEoZSl7Y29uc3QgdD1lW2ZzXSgpW0ppXS5wYXJhU3RhY2s7cmV0dXJuIHQubGVuZ3RoP3QuYXQoLTEpOm51bGx9ZnVuY3Rpb24gc2V0UGFyYShlLHQscil7aWYoci5hdHRyaWJ1dGVzLmNsYXNzPy5pbmNsdWRlcygieGZhUmljaCIpKXtpZih0KXsiIj09PWUuaCYmKHQuaGVpZ2h0PSJhdXRvIik7IiI9PT1lLncmJih0LndpZHRoPSJhdXRvIil9Y29uc3QgYT1nZXRDdXJyZW50UGFyYShlKTtpZihhKXtjb25zdCBlPXIuYXR0cmlidXRlcy5zdHlsZTtlLmRpc3BsYXk9ImZsZXgiO2UuZmxleERpcmVjdGlvbj0iY29sdW1uIjtzd2l0Y2goYS52QWxpZ24pe2Nhc2UidG9wIjplLmp1c3RpZnlDb250ZW50PSJzdGFydCI7YnJlYWs7Y2FzZSJib3R0b20iOmUuanVzdGlmeUNvbnRlbnQ9ImVuZCI7YnJlYWs7Y2FzZSJtaWRkbGUiOmUuanVzdGlmeUNvbnRlbnQ9ImNlbnRlciJ9Y29uc3QgdD1hW1lzXSgpO2Zvcihjb25zdFtyLGFdb2YgT2JqZWN0LmVudHJpZXModCkpciBpbiBlfHwoZVtyXT1hKX19fWZ1bmN0aW9uIHNldEZvbnRGYW1pbHkoZSx0LHIsYSl7aWYoIXIpe2RlbGV0ZSBhLmZvbnRGYW1pbHk7cmV0dXJufWNvbnN0IG49c3RyaXBRdW90ZXMoZS50eXBlZmFjZSk7YS5mb250RmFtaWx5PWAiJHtufSJgO2NvbnN0IGk9ci5maW5kKG4pO2lmKGkpe2NvbnN0e2ZvbnRGYW1pbHk6cn09aS5yZWd1bGFyLmNzc0ZvbnRJbmZvO3IhPT1uJiYoYS5mb250RmFtaWx5PWAiJHtyfSJgKTtjb25zdCBzPWdldEN1cnJlbnRQYXJhKHQpO2lmKHMmJiIiIT09cy5saW5lSGVpZ2h0KXJldHVybjtpZihhLmxpbmVIZWlnaHQpcmV0dXJuO2NvbnN0IG89c2VsZWN0Rm9udChlLGkpO28mJihhLmxpbmVIZWlnaHQ9TWF0aC5tYXgoMS4yLG8ubGluZUhlaWdodCkpfX1mdW5jdGlvbiBmaXhVUkwoZSl7Y29uc3QgdD1jcmVhdGVWYWxpZEFic29sdXRlVXJsKGUsbnVsbCx7YWRkRGVmYXVsdFByb3RvY29sOiEwLHRyeUNvbnZlcnRFbmNvZGluZzohMH0pO3JldHVybiB0P3QuaHJlZjpudWxsfWZ1bmN0aW9uIGNyZWF0ZUxpbmUoZSx0KXtyZXR1cm57bmFtZToiZGl2IixhdHRyaWJ1dGVzOntjbGFzczpbImxyLXRiIj09PWUubGF5b3V0PyJ4ZmFMciI6InhmYVJsIl19LGNoaWxkcmVuOnR9fWZ1bmN0aW9uIGZsdXNoSFRNTChlKXtpZighZVtKaV0pcmV0dXJuIG51bGw7Y29uc3QgdD17bmFtZToiZGl2IixhdHRyaWJ1dGVzOmVbSmldLmF0dHJpYnV0ZXMsY2hpbGRyZW46ZVtKaV0uY2hpbGRyZW59O2lmKGVbSmldLmZhaWxpbmdOb2RlKXtjb25zdCByPWVbSmldLmZhaWxpbmdOb2RlW1ppXSgpO3ImJihlLmxheW91dC5lbmRzV2l0aCgiLXRiIik/dC5jaGlsZHJlbi5wdXNoKGNyZWF0ZUxpbmUoZSxbcl0pKTp0LmNoaWxkcmVuLnB1c2gocikpfXJldHVybiAwPT09dC5jaGlsZHJlbi5sZW5ndGg/bnVsbDp0fWZ1bmN0aW9uIGFkZEhUTUwoZSx0LHIpe2NvbnN0IGE9ZVtKaV0sbj1hLmF2YWlsYWJsZVNwYWNlLFtpLHMsbyxjXT1yO3N3aXRjaChlLmxheW91dCl7Y2FzZSJwb3NpdGlvbiI6YS53aWR0aD1NYXRoLm1heChhLndpZHRoLGkrbyk7YS5oZWlnaHQ9TWF0aC5tYXgoYS5oZWlnaHQscytjKTthLmNoaWxkcmVuLnB1c2godCk7YnJlYWs7Y2FzZSJsci10YiI6Y2FzZSJybC10YiI6aWYoIWEubGluZXx8MT09PWEuYXR0ZW1wdCl7YS5saW5lPWNyZWF0ZUxpbmUoZSxbXSk7YS5jaGlsZHJlbi5wdXNoKGEubGluZSk7YS5udW1iZXJJbkxpbmU9MH1hLm51bWJlckluTGluZSs9MTthLmxpbmUuY2hpbGRyZW4ucHVzaCh0KTtpZigwPT09YS5hdHRlbXB0KXthLmN1cnJlbnRXaWR0aCs9bzthLmhlaWdodD1NYXRoLm1heChhLmhlaWdodCxhLnByZXZIZWlnaHQrYyl9ZWxzZXthLmN1cnJlbnRXaWR0aD1vO2EucHJldkhlaWdodD1hLmhlaWdodDthLmhlaWdodCs9YzthLmF0dGVtcHQ9MH1hLndpZHRoPU1hdGgubWF4KGEud2lkdGgsYS5jdXJyZW50V2lkdGgpO2JyZWFrO2Nhc2Uicmwtcm93IjpjYXNlInJvdyI6e2EuY2hpbGRyZW4ucHVzaCh0KTthLndpZHRoKz1vO2EuaGVpZ2h0PU1hdGgubWF4KGEuaGVpZ2h0LGMpO2NvbnN0IGU9bWVhc3VyZVRvU3RyaW5nKGEuaGVpZ2h0KTtmb3IoY29uc3QgdCBvZiBhLmNoaWxkcmVuKXQuYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQ9ZTticmVha31jYXNlInRhYmxlIjpjYXNlInRiIjphLndpZHRoPU1hdGhDbGFtcChvLGEud2lkdGgsbi53aWR0aCk7YS5oZWlnaHQrPWM7YS5jaGlsZHJlbi5wdXNoKHQpfX1mdW5jdGlvbiBnZXRBdmFpbGFibGVTcGFjZShlKXtjb25zdCB0PWVbSmldLmF2YWlsYWJsZVNwYWNlLHI9ZS5tYXJnaW4/ZS5tYXJnaW4udG9wSW5zZXQrZS5tYXJnaW4uYm90dG9tSW5zZXQ6MCxhPWUubWFyZ2luP2UubWFyZ2luLmxlZnRJbnNldCtlLm1hcmdpbi5yaWdodEluc2V0OjA7c3dpdGNoKGUubGF5b3V0KXtjYXNlImxyLXRiIjpjYXNlInJsLXRiIjpyZXR1cm4gMD09PWVbSmldLmF0dGVtcHQ/e3dpZHRoOnQud2lkdGgtYS1lW0ppXS5jdXJyZW50V2lkdGgsaGVpZ2h0OnQuaGVpZ2h0LXItZVtKaV0ucHJldkhlaWdodH06e3dpZHRoOnQud2lkdGgtYSxoZWlnaHQ6dC5oZWlnaHQtci1lW0ppXS5oZWlnaHR9O2Nhc2Uicmwtcm93IjpjYXNlInJvdyI6cmV0dXJue3dpZHRoOk1hdGguc3VtUHJlY2lzZShlW0ppXS5jb2x1bW5XaWR0aHMuc2xpY2UoZVtKaV0uY3VycmVudENvbHVtbikpLGhlaWdodDp0LmhlaWdodC1hfTtjYXNlInRhYmxlIjpjYXNlInRiIjpyZXR1cm57d2lkdGg6dC53aWR0aC1hLGhlaWdodDp0LmhlaWdodC1yLWVbSmldLmhlaWdodH07ZGVmYXVsdDpyZXR1cm4gdH19ZnVuY3Rpb24gY2hlY2tEaW1lbnNpb25zKGUsdCl7aWYobnVsbD09PWVbZnNdKClbSmldLmZpcnN0VW5zcGxpdHRhYmxlKXJldHVybiEwO2lmKDA9PT1lLnd8fDA9PT1lLmgpcmV0dXJuITA7Y29uc3Qgcj1lW3VzXSgpLGE9cltKaV0/LmF0dGVtcHR8fDAsWyxuLGksc109ZnVuY3Rpb24gZ2V0VHJhbnNmb3JtZWRCQm94KGUpe2xldCB0LHIsYT0iIj09PWUudz9OYU46ZS53LG49IiI9PT1lLmg/TmFOOmUuaCxbaSxzXT1bMCwwXTtzd2l0Y2goZS5hbmNob3JUeXBlfHwiIil7Y2FzZSJib3R0b21DZW50ZXIiOltpLHNdPVthLzIsbl07YnJlYWs7Y2FzZSJib3R0b21MZWZ0IjpbaSxzXT1bMCxuXTticmVhaztjYXNlImJvdHRvbVJpZ2h0IjpbaSxzXT1bYSxuXTticmVhaztjYXNlIm1pZGRsZUNlbnRlciI6W2ksc109W2EvMixuLzJdO2JyZWFrO2Nhc2UibWlkZGxlTGVmdCI6W2ksc109WzAsbi8yXTticmVhaztjYXNlIm1pZGRsZVJpZ2h0IjpbaSxzXT1bYSxuLzJdO2JyZWFrO2Nhc2UidG9wQ2VudGVyIjpbaSxzXT1bYS8yLDBdO2JyZWFrO2Nhc2UidG9wUmlnaHQiOltpLHNdPVthLDBdfXN3aXRjaChlLnJvdGF0ZXx8MCl7Y2FzZSAwOlt0LHJdPVstaSwtc107YnJlYWs7Y2FzZSA5MDpbdCxyXT1bLXMsaV07W2Esbl09W24sLWFdO2JyZWFrO2Nhc2UgMTgwOlt0LHJdPVtpLHNdO1thLG5dPVstYSwtbl07YnJlYWs7Y2FzZSAyNzA6W3Qscl09W3MsLWldO1thLG5dPVstbixhXX1yZXR1cm5bZS54K3QrTWF0aC5taW4oMCxhKSxlLnkrcitNYXRoLm1pbigwLG4pLE1hdGguYWJzKGEpLE1hdGguYWJzKG4pXX0oZSk7c3dpdGNoKHIubGF5b3V0KXtjYXNlImxyLXRiIjpjYXNlInJsLXRiIjpyZXR1cm4gMD09PWE/ZVtmc10oKVtKaV0ubm9MYXlvdXRGYWlsdXJlPyIiIT09ZS53P01hdGgucm91bmQoaS10LndpZHRoKTw9Mjp0LndpZHRoPjI6ISgiIiE9PWUuaCYmTWF0aC5yb3VuZChzLXQuaGVpZ2h0KT4yKSYmKCIiIT09ZS53P01hdGgucm91bmQoaS10LndpZHRoKTw9Mnx8MD09PXJbSmldLm51bWJlckluTGluZSYmdC5oZWlnaHQ+Mjp0LndpZHRoPjIpOiEhZVtmc10oKVtKaV0ubm9MYXlvdXRGYWlsdXJlfHwhKCIiIT09ZS5oJiZNYXRoLnJvdW5kKHMtdC5oZWlnaHQpPjIpJiYoKCIiPT09ZS53fHxNYXRoLnJvdW5kKGktdC53aWR0aCk8PTJ8fCFyW3ZzXSgpKSYmdC5oZWlnaHQ+Mik7Y2FzZSJ0YWJsZSI6Y2FzZSJ0YiI6cmV0dXJuISFlW2ZzXSgpW0ppXS5ub0xheW91dEZhaWx1cmV8fCgiIj09PWUuaHx8ZVtDc10oKT8oIiI9PT1lLnd8fE1hdGgucm91bmQoaS10LndpZHRoKTw9Mnx8IXJbdnNdKCkpJiZ0LmhlaWdodD4yOk1hdGgucm91bmQocy10LmhlaWdodCk8PTIpO2Nhc2UicG9zaXRpb24iOmlmKGVbZnNdKClbSmldLm5vTGF5b3V0RmFpbHVyZSlyZXR1cm4hMDtpZigiIj09PWUuaHx8TWF0aC5yb3VuZChzK24tdC5oZWlnaHQpPD0yKXJldHVybiEwO3JldHVybiBzK24+ZVtmc10oKVtKaV0uY3VycmVudENvbnRlbnRBcmVhLmg7Y2FzZSJybC1yb3ciOmNhc2Uicm93IjpyZXR1cm4hIWVbZnNdKClbSmldLm5vTGF5b3V0RmFpbHVyZXx8KCIiPT09ZS5ofHxNYXRoLnJvdW5kKHMtdC5oZWlnaHQpPD0yKTtkZWZhdWx0OnJldHVybiEwfX1jb25zdCBFbz1lby50ZW1wbGF0ZS5pZCxObz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLFBvPS9eSChcZCspJC8sX289bmV3IFNldChbImltYWdlL2dpZiIsImltYWdlL2pwZWciLCJpbWFnZS9qcGciLCJpbWFnZS9wanBlZyIsImltYWdlL3BuZyIsImltYWdlL2FwbmciLCJpbWFnZS94LXBuZyIsImltYWdlL2JtcCIsImltYWdlL3gtbXMtYm1wIiwiaW1hZ2UvdGlmZiIsImltYWdlL3RpZiIsImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSJdKSxMbz1bW1s2Niw3N10sImltYWdlL2JtcCJdLFtbMjU1LDIxNiwyNTVdLCJpbWFnZS9qcGVnIl0sW1s3Myw3Myw0MiwwXSwiaW1hZ2UvdGlmZiJdLFtbNzcsNzcsMCw0Ml0sImltYWdlL3RpZmYiXSxbWzcxLDczLDcwLDU2LDU3LDk3XSwiaW1hZ2UvZ2lmIl0sW1sxMzcsODAsNzgsNzEsMTMsMTAsMjYsMTBdLCJpbWFnZS9wbmciXV07ZnVuY3Rpb24gZ2V0Qm9yZGVyRGltcyhlKXtpZighZXx8IWUuYm9yZGVyKXJldHVybnt3OjAsaDowfTtjb25zdCB0PWUuYm9yZGVyW3NzXSgpO3JldHVybiB0P3t3OnQud2lkdGhzWzBdK3Qud2lkdGhzWzJdK3QuaW5zZXRzWzBdK3QuaW5zZXRzWzJdLGg6dC53aWR0aHNbMV0rdC53aWR0aHNbM10rdC5pbnNldHNbMV0rdC5pbnNldHNbM119Ont3OjAsaDowfX1mdW5jdGlvbiBoYXNNYXJnaW4oZSl7cmV0dXJuIGUubWFyZ2luJiYoZS5tYXJnaW4udG9wSW5zZXR8fGUubWFyZ2luLnJpZ2h0SW5zZXR8fGUubWFyZ2luLmJvdHRvbUluc2V0fHxlLm1hcmdpbi5sZWZ0SW5zZXQpfWZ1bmN0aW9uIF9zZXRWYWx1ZShlLHQpe2lmKCFlLnZhbHVlKXtjb25zdCB0PW5ldyBWYWx1ZSh7fSk7ZVtqaV0odCk7ZS52YWx1ZT10fWUudmFsdWVbenNdKHQpfWZ1bmN0aW9uKmdldENvbnRhaW5lZENoaWxkcmVuKGUpe2Zvcihjb25zdCB0IG9mIGVbY3NdKCkpdCBpbnN0YW5jZW9mIFN1YmZvcm1TZXQ/eWllbGQqdFtsc10oKTp5aWVsZCB0fWZ1bmN0aW9uIGlzUmVxdWlyZWQoZSl7cmV0dXJuImVycm9yIj09PWUudmFsaWRhdGU/Lm51bGxUZXN0fWZ1bmN0aW9uIHNldFRhYkluZGV4KGUpe2Zvcig7ZTspe2lmKCFlLnRyYXZlcnNhbCl7ZVtHc109ZVtkc10oKVtHc107cmV0dXJufWlmKGVbR3NdKXJldHVybjtsZXQgdD1udWxsO2Zvcihjb25zdCByIG9mIGUudHJhdmVyc2FsW2NzXSgpKWlmKCJuZXh0Ij09PXIub3BlcmF0aW9uKXt0PXI7YnJlYWt9aWYoIXR8fCF0LnJlZil7ZVtHc109ZVtkc10oKVtHc107cmV0dXJufWNvbnN0IHI9ZVtmc10oKTtlW0dzXT0rK3JbR3NdO2NvbnN0IGE9cltYc10odC5yZWYsZSk7aWYoIWEpcmV0dXJuO2U9YVswXX19ZnVuY3Rpb24gYXBwbHlBc3Npc3QoZSx0KXtjb25zdCByPWUuYXNzaXN0O2lmKHIpe2NvbnN0IGU9cltLc10oKTtlJiYodC50aXRsZT1lKTtjb25zdCBhPXIucm9sZS5tYXRjaChQbyk7aWYoYSl7Y29uc3QgZT0iaGVhZGluZyIscj1hWzFdO3Qucm9sZT1lO3RbImFyaWEtbGV2ZWwiXT1yfX1pZigidGFibGUiPT09ZS5sYXlvdXQpdC5yb2xlPSJ0YWJsZSI7ZWxzZSBpZigicm93Ij09PWUubGF5b3V0KXQucm9sZT0icm93IjtlbHNle2NvbnN0IHI9ZVtkc10oKTsicm93Ij09PXIubGF5b3V0JiYodC5yb2xlPSJUSCI9PT1yLmFzc2lzdD8ucm9sZT8iY29sdW1uaGVhZGVyIjoiY2VsbCIpfX1mdW5jdGlvbiBhcmlhTGFiZWwoZSl7aWYoIWUuYXNzaXN0KXJldHVybiBudWxsO2NvbnN0IHQ9ZS5hc3Npc3Q7cmV0dXJuIHQuc3BlYWsmJiIiIT09dC5zcGVha1skaV0/dC5zcGVha1skaV06dC50b29sVGlwP3QudG9vbFRpcFskaV06bnVsbH1mdW5jdGlvbiB2YWx1ZVRvSHRtbChlKXtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhUmljaCJdLHN0eWxlOk9iamVjdC5jcmVhdGUobnVsbCl9LGNoaWxkcmVuOlt7bmFtZToic3BhbiIsYXR0cmlidXRlczp7c3R5bGU6T2JqZWN0LmNyZWF0ZShudWxsKX0sdmFsdWU6ZX1dfSl9ZnVuY3Rpb24gc2V0Rmlyc3RVbnNwbGl0dGFibGUoZSl7Y29uc3QgdD1lW2ZzXSgpO2lmKG51bGw9PT10W0ppXS5maXJzdFVuc3BsaXR0YWJsZSl7dFtKaV0uZmlyc3RVbnNwbGl0dGFibGU9ZTt0W0ppXS5ub0xheW91dEZhaWx1cmU9ITB9fWZ1bmN0aW9uIHVuc2V0Rmlyc3RVbnNwbGl0dGFibGUoZSl7Y29uc3QgdD1lW2ZzXSgpO3RbSmldLmZpcnN0VW5zcGxpdHRhYmxlPT09ZSYmKHRbSmldLm5vTGF5b3V0RmFpbHVyZT0hMSl9ZnVuY3Rpb24gaGFuZGxlQnJlYWsoZSl7aWYoZVtKaV0pcmV0dXJuITE7ZVtKaV09T2JqZWN0LmNyZWF0ZShudWxsKTtpZigiYXV0byI9PT1lLnRhcmdldFR5cGUpcmV0dXJuITE7Y29uc3QgdD1lW2ZzXSgpO2xldCByPW51bGw7aWYoZS50YXJnZXQpe3I9dFtYc10oZS50YXJnZXQsZVtkc10oKSk7aWYoIXIpcmV0dXJuITE7cj1yWzBdfWNvbnN0e2N1cnJlbnRQYWdlQXJlYTphLGN1cnJlbnRDb250ZW50QXJlYTpufT10W0ppXTtpZigicGFnZUFyZWEiPT09ZS50YXJnZXRUeXBlKXtyIGluc3RhbmNlb2YgUGFnZUFyZWF8fChyPW51bGwpO2lmKGUuc3RhcnROZXcpe2VbSmldLnRhcmdldD1yfHxhO3JldHVybiEwfWlmKHImJnIhPT1hKXtlW0ppXS50YXJnZXQ9cjtyZXR1cm4hMH1yZXR1cm4hMX1yIGluc3RhbmNlb2YgQ29udGVudEFyZWF8fChyPW51bGwpO2NvbnN0IGk9ciYmcltkc10oKTtsZXQgcyxvPWk7aWYoZS5zdGFydE5ldylpZihyKXtjb25zdCBlPWkuY29udGVudEFyZWEuY2hpbGRyZW4sdD1lLmluZGV4T2YobiksYT1lLmluZGV4T2Yocik7LTEhPT10JiZ0PGEmJihvPW51bGwpO3M9YS0xfWVsc2Ugcz1hLmNvbnRlbnRBcmVhLmNoaWxkcmVuLmluZGV4T2Yobik7ZWxzZXtpZighcnx8cj09PW4pcmV0dXJuITE7cz1pLmNvbnRlbnRBcmVhLmNoaWxkcmVuLmluZGV4T2YociktMTtvPWk9PT1hP251bGw6aX1lW0ppXS50YXJnZXQ9bztlW0ppXS5pbmRleD1zO3JldHVybiEwfWZ1bmN0aW9uIGhhbmRsZU92ZXJmbG93KGUsdCxyKXtjb25zdCBhPWVbZnNdKCksbj1hW0ppXS5ub0xheW91dEZhaWx1cmUsaT10W3VzXTt0W3VzXT0oKT0+ZTthW0ppXS5ub0xheW91dEZhaWx1cmU9ITA7Y29uc3Qgcz10W0tzXShyKTtlW19pXShzLmh0bWwscy5iYm94KTthW0ppXS5ub0xheW91dEZhaWx1cmU9bjt0W3VzXT1pfWNsYXNzIEFwcGVhcmFuY2VGaWx0ZXIgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImFwcGVhcmFuY2VGaWx0ZXIiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudHlwZT1nZXRTdHJpbmdPcHRpb24oZS50eXBlLFsib3B0aW9uYWwiLCJyZXF1aXJlZCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIEFyYyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYXJjIiwhMCk7dGhpcy5jaXJjdWxhcj1nZXRJbnRlZ2VyKHtkYXRhOmUuY2lyY3VsYXIsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLmhhbmQ9Z2V0U3RyaW5nT3B0aW9uKGUuaGFuZCxbImV2ZW4iLCJsZWZ0IiwicmlnaHQiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnN0YXJ0QW5nbGU9Z2V0RmxvYXQoe2RhdGE6ZS5zdGFydEFuZ2xlLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PiEwfSk7dGhpcy5zd2VlcEFuZ2xlPWdldEZsb2F0KHtkYXRhOmUuc3dlZXBBbmdsZSxkZWZhdWx0VmFsdWU6MzYwLHZhbGlkYXRlOmU9PiEwfSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZWRnZT1udWxsO3RoaXMuZmlsbD1udWxsfVtLc10oKXtjb25zdCBlPXRoaXMuZWRnZXx8bmV3IEVkZ2Uoe30pLHQ9ZVtZc10oKSxyPU9iamVjdC5jcmVhdGUobnVsbCk7InZpc2libGUiPT09dGhpcy5maWxsPy5wcmVzZW5jZT9PYmplY3QuYXNzaWduKHIsdGhpcy5maWxsW1lzXSgpKTpyLmZpbGw9InRyYW5zcGFyZW50IjtyLnN0cm9rZVdpZHRoPW1lYXN1cmVUb1N0cmluZygidmlzaWJsZSI9PT1lLnByZXNlbmNlP2UudGhpY2tuZXNzOjApO3Iuc3Ryb2tlPXQuY29sb3I7bGV0IGE7Y29uc3Qgbj17eG1sbnM6Tm8sc3R5bGU6e3dpZHRoOiIxMDAlIixoZWlnaHQ6IjEwMCUiLG92ZXJmbG93OiJ2aXNpYmxlIn19O2lmKDM2MD09PXRoaXMuc3dlZXBBbmdsZSlhPXtuYW1lOiJlbGxpcHNlIixhdHRyaWJ1dGVzOnt4bWxuczpObyxjeDoiNTAlIixjeToiNTAlIixyeDoiNTAlIixyeToiNTAlIixzdHlsZTpyfX07ZWxzZXtjb25zdCBlPXRoaXMuc3RhcnRBbmdsZSpNYXRoLlBJLzE4MCx0PXRoaXMuc3dlZXBBbmdsZSpNYXRoLlBJLzE4MCxpPXRoaXMuc3dlZXBBbmdsZT4xODA/MTowLFtzLG8sYyxsXT1bNTAqKDErTWF0aC5jb3MoZSkpLDUwKigxLU1hdGguc2luKGUpKSw1MCooMStNYXRoLmNvcyhlK3QpKSw1MCooMS1NYXRoLnNpbihlK3QpKV07YT17bmFtZToicGF0aCIsYXR0cmlidXRlczp7eG1sbnM6Tm8sZDpgTSAke3N9ICR7b30gQSA1MCA1MCAwICR7aX0gMCAke2N9ICR7bH1gLHZlY3RvckVmZmVjdDoibm9uLXNjYWxpbmctc3Ryb2tlIixzdHlsZTpyfX07T2JqZWN0LmFzc2lnbihuLHt2aWV3Qm94OiIwIDAgMTAwIDEwMCIscHJlc2VydmVBc3BlY3RSYXRpbzoibm9uZSJ9KX1jb25zdCBpPXtuYW1lOiJzdmciLGNoaWxkcmVuOlthXSxhdHRyaWJ1dGVzOm59O2lmKGhhc01hcmdpbih0aGlzW2RzXSgpW2RzXSgpKSlyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e3N0eWxlOntkaXNwbGF5OiJpbmxpbmUiLHdpZHRoOiIxMDAlIixoZWlnaHQ6IjEwMCUifX0sY2hpbGRyZW46W2ldfSk7aS5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uPSJhYnNvbHV0ZSI7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhpKX19Y2xhc3MgQXJlYSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYXJlYSIsITApO3RoaXMuY29sU3Bhbj1nZXRJbnRlZ2VyKHtkYXRhOmUuY29sU3BhbixkZWZhdWx0VmFsdWU6MSx2YWxpZGF0ZTplPT5lPj0xfHwtMT09PWV9KTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucmVsZXZhbnQ9Z2V0UmVsZXZhbnQoZS5yZWxldmFudCk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMueD1nZXRNZWFzdXJlbWVudChlLngsIjBwdCIpO3RoaXMueT1nZXRNZWFzdXJlbWVudChlLnksIjBwdCIpO3RoaXMuZGVzYz1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5hcmVhPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRyYXc9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhPYmplY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhjbEdyb3VwPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmZpZWxkPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnN1YmZvcm09bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViZm9ybVNldD1uZXcgWEZBT2JqZWN0QXJyYXl9Kltsc10oKXt5aWVsZCpnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKX1bRnNdKCl7cmV0dXJuITB9W3hzXSgpe3JldHVybiEwfVtfaV0oZSx0KXtjb25zdFtyLGEsbixpXT10O3RoaXNbSmldLndpZHRoPU1hdGgubWF4KHRoaXNbSmldLndpZHRoLHIrbik7dGhpc1tKaV0uaGVpZ2h0PU1hdGgubWF4KHRoaXNbSmldLmhlaWdodCxhK2kpO3RoaXNbSmldLmNoaWxkcmVuLnB1c2goZSl9W3RzXSgpe3JldHVybiB0aGlzW0ppXS5hdmFpbGFibGVTcGFjZX1bS3NdKGUpe2NvbnN0IHQ9dG9TdHlsZSh0aGlzLCJwb3NpdGlvbiIpLHI9e3N0eWxlOnQsaWQ6dGhpc1tac10sY2xhc3M6WyJ4ZmFBcmVhIl19O2lzUHJpbnRPbmx5KHRoaXMpJiZyLmNsYXNzLnB1c2goInhmYVByaW50T25seSIpO3RoaXMubmFtZSYmKHIueGZhTmFtZT10aGlzLm5hbWUpO2NvbnN0IGE9W107dGhpc1tKaV09e2NoaWxkcmVuOmEsd2lkdGg6MCxoZWlnaHQ6MCxhdmFpbGFibGVTcGFjZTplfTtjb25zdCBuPXRoaXNbcWldKHtmaWx0ZXI6bmV3IFNldChbImFyZWEiLCJkcmF3IiwiZmllbGQiLCJleGNsR3JvdXAiLCJzdWJmb3JtIiwic3ViZm9ybVNldCJdKSxpbmNsdWRlOiEwfSk7aWYoIW4uc3VjY2Vzcyl7aWYobi5pc0JyZWFrKCkpcmV0dXJuIG47ZGVsZXRlIHRoaXNbSmldO3JldHVybiBIVE1MUmVzdWx0LkZBSUxVUkV9dC53aWR0aD1tZWFzdXJlVG9TdHJpbmcodGhpc1tKaV0ud2lkdGgpO3QuaGVpZ2h0PW1lYXN1cmVUb1N0cmluZyh0aGlzW0ppXS5oZWlnaHQpO2NvbnN0IGk9e25hbWU6ImRpdiIsYXR0cmlidXRlczpyLGNoaWxkcmVuOmF9LHM9W3RoaXMueCx0aGlzLnksdGhpc1tKaV0ud2lkdGgsdGhpc1tKaV0uaGVpZ2h0XTtkZWxldGUgdGhpc1tKaV07cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhpLHMpfX1jbGFzcyBBc3Npc3QgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImFzc2lzdCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5yb2xlPWUucm9sZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuc3BlYWs9bnVsbDt0aGlzLnRvb2xUaXA9bnVsbH1bS3NdKCl7cmV0dXJuIHRoaXMudG9vbFRpcD8uWyRpXXx8bnVsbH19Y2xhc3MgQmFyY29kZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYmFyY29kZSIsITApO3RoaXMuY2hhckVuY29kaW5nPWdldEtleXdvcmQoe2RhdGE6ZS5jaGFyRW5jb2Rpbmc/ZS5jaGFyRW5jb2RpbmcudG9Mb3dlckNhc2UoKToiIixkZWZhdWx0VmFsdWU6IiIsdmFsaWRhdGU6ZT0+WyJ1dGYtOCIsImJpZy1maXZlIiwiZm9udHNwZWNpZmljIiwiZ2JrIiwiZ2ItMTgwMzAiLCJnYi0yMzEyIiwia3NjLTU2MDEiLCJub25lIiwic2hpZnQtamlzIiwidWNzLTIiLCJ1dGYtMTYiXS5pbmNsdWRlcyhlKXx8ZS5tYXRjaCgvaXNvLTg4NTktXGR7Mn0vKX0pO3RoaXMuY2hlY2tzdW09Z2V0U3RyaW5nT3B0aW9uKGUuY2hlY2tzdW0sWyJub25lIiwiMW1vZDEwIiwiMW1vZDEwXzFtb2QxMSIsIjJtb2QxMCIsImF1dG8iXSk7dGhpcy5kYXRhQ29sdW1uQ291bnQ9Z2V0SW50ZWdlcih7ZGF0YTplLmRhdGFDb2x1bW5Db3VudCxkZWZhdWx0VmFsdWU6LTEsdmFsaWRhdGU6ZT0+ZT49MH0pO3RoaXMuZGF0YUxlbmd0aD1nZXRJbnRlZ2VyKHtkYXRhOmUuZGF0YUxlbmd0aCxkZWZhdWx0VmFsdWU6LTEsdmFsaWRhdGU6ZT0+ZT49MH0pO3RoaXMuZGF0YVByZXA9Z2V0U3RyaW5nT3B0aW9uKGUuZGF0YVByZXAsWyJub25lIiwiZmxhdGVDb21wcmVzcyJdKTt0aGlzLmRhdGFSb3dDb3VudD1nZXRJbnRlZ2VyKHtkYXRhOmUuZGF0YVJvd0NvdW50LGRlZmF1bHRWYWx1ZTotMSx2YWxpZGF0ZTplPT5lPj0wfSk7dGhpcy5lbmRDaGFyPWUuZW5kQ2hhcnx8IiI7dGhpcy5lcnJvckNvcnJlY3Rpb25MZXZlbD1nZXRJbnRlZ2VyKHtkYXRhOmUuZXJyb3JDb3JyZWN0aW9uTGV2ZWwsZGVmYXVsdFZhbHVlOi0xLHZhbGlkYXRlOmU9PmU+PTAmJmU8PTh9KTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubW9kdWxlSGVpZ2h0PWdldE1lYXN1cmVtZW50KGUubW9kdWxlSGVpZ2h0LCI1bW0iKTt0aGlzLm1vZHVsZVdpZHRoPWdldE1lYXN1cmVtZW50KGUubW9kdWxlV2lkdGgsIjAuMjVtbSIpO3RoaXMucHJpbnRDaGVja0RpZ2l0PWdldEludGVnZXIoe2RhdGE6ZS5wcmludENoZWNrRGlnaXQsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLnJvd0NvbHVtblJhdGlvPWdldFJhdGlvKGUucm93Q29sdW1uUmF0aW8pO3RoaXMuc3RhcnRDaGFyPWUuc3RhcnRDaGFyfHwiIjt0aGlzLnRleHRMb2NhdGlvbj1nZXRTdHJpbmdPcHRpb24oZS50ZXh0TG9jYXRpb24sWyJiZWxvdyIsImFib3ZlIiwiYWJvdmVFbWJlZGRlZCIsImJlbG93RW1iZWRkZWQiLCJub25lIl0pO3RoaXMudHJ1bmNhdGU9Z2V0SW50ZWdlcih7ZGF0YTplLnRydW5jYXRlLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PjE9PT1lfSk7dGhpcy50eXBlPWdldFN0cmluZ09wdGlvbihlLnR5cGU/ZS50eXBlLnRvTG93ZXJDYXNlKCk6IiIsWyJhenRlYyIsImNvZGFiYXIiLCJjb2RlMm9mNWluZHVzdHJpYWwiLCJjb2RlMm9mNWludGVybGVhdmVkIiwiY29kZTJvZjVtYXRyaXgiLCJjb2RlMm9mNXN0YW5kYXJkIiwiY29kZTNvZjkiLCJjb2RlM29mOWV4dGVuZGVkIiwiY29kZTExIiwiY29kZTQ5IiwiY29kZTkzIiwiY29kZTEyOCIsImNvZGUxMjhhIiwiY29kZTEyOGIiLCJjb2RlMTI4YyIsImNvZGUxMjhzc2NjIiwiZGF0YW1hdHJpeCIsImVhbjgiLCJlYW44YWRkMiIsImVhbjhhZGQ1IiwiZWFuMTMiLCJlYW4xM2FkZDIiLCJlYW4xM2FkZDUiLCJlYW4xM3B3Y2QiLCJmaW0iLCJsb2dtYXJzIiwibWF4aWNvZGUiLCJtc2kiLCJwZGY0MTciLCJwZGY0MTdtYWNybyIsInBsZXNzZXkiLCJwb3N0YXVzY3VzdDIiLCJwb3N0YXVzY3VzdDMiLCJwb3N0YXVzcmVwbHlwYWlkIiwicG9zdGF1c3N0YW5kYXJkIiwicG9zdHVrcm00c2NjIiwicG9zdHVzZHBiYyIsInBvc3R1c2ltYiIsInBvc3R1c3N0YW5kYXJkIiwicG9zdHVzNXppcCIsInFyY29kZSIsInJmaWQiLCJyc3MxNCIsInJzczE0ZXhwYW5kZWQiLCJyc3MxNGxpbWl0ZWQiLCJyc3MxNHN0YWNrZWQiLCJyc3MxNHN0YWNrZWRvbW5pIiwicnNzMTR0cnVuY2F0ZWQiLCJ0ZWxlcGVuIiwidWNjMTI4IiwidWNjMTI4cmFuZG9tIiwidWNjMTI4c3NjYyIsInVwY2EiLCJ1cGNhYWRkMiIsInVwY2FhZGQ1IiwidXBjYXB3Y2QiLCJ1cGNlIiwidXBjZWFkZDIiLCJ1cGNlYWRkNSIsInVwY2VhbjIiLCJ1cGNlYW41IiwidXBzbWF4aWNvZGUiXSk7dGhpcy51cHNNb2RlPWdldFN0cmluZ09wdGlvbihlLnVwc01vZGUsWyJ1c0NhcnJpZXIiLCJpbnRlcm5hdGlvbmFsQ2FycmllciIsInNlY3VyZVN5bWJvbCIsInN0YW5kYXJkU3ltYm9sIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLndpZGVOYXJyb3dSYXRpbz1nZXRSYXRpbyhlLndpZGVOYXJyb3dSYXRpbyk7dGhpcy5lbmNyeXB0PW51bGw7dGhpcy5leHRyYXM9bnVsbH19Y2xhc3MgQmluZCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYmluZCIsITApO3RoaXMubWF0Y2g9Z2V0U3RyaW5nT3B0aW9uKGUubWF0Y2gsWyJvbmNlIiwiZGF0YVJlZiIsImdsb2JhbCIsIm5vbmUiXSk7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMucGljdHVyZT1udWxsfX1jbGFzcyBCaW5kSXRlbXMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImJpbmRJdGVtcyIpO3RoaXMuY29ubmVjdGlvbj1lLmNvbm5lY3Rpb258fCIiO3RoaXMubGFiZWxSZWY9ZS5sYWJlbFJlZnx8IiI7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMudmFsdWVSZWY9ZS52YWx1ZVJlZnx8IiJ9fWNsYXNzIEJvb2tlbmQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImJvb2tlbmQiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubGVhZGVyPWUubGVhZGVyfHwiIjt0aGlzLnRyYWlsZXI9ZS50cmFpbGVyfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIEJvb2xlYW5FbGVtZW50IGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImJvb2xlYW4iKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn1bS3NdKGUpe3JldHVybiB2YWx1ZVRvSHRtbCgxPT09dGhpc1skaV0/IjEiOiIwIil9fWNsYXNzIEJvcmRlciBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYm9yZGVyIiwhMCk7dGhpcy5icmVhaz1nZXRTdHJpbmdPcHRpb24oZS5icmVhayxbImNsb3NlIiwib3BlbiJdKTt0aGlzLmhhbmQ9Z2V0U3RyaW5nT3B0aW9uKGUuaGFuZCxbImV2ZW4iLCJsZWZ0IiwicmlnaHQiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnByZXNlbmNlPWdldFN0cmluZ09wdGlvbihlLnByZXNlbmNlLFsidmlzaWJsZSIsImhpZGRlbiIsImluYWN0aXZlIiwiaW52aXNpYmxlIl0pO3RoaXMucmVsZXZhbnQ9Z2V0UmVsZXZhbnQoZS5yZWxldmFudCk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuY29ybmVyPW5ldyBYRkFPYmplY3RBcnJheSg0KTt0aGlzLmVkZ2U9bmV3IFhGQU9iamVjdEFycmF5KDQpO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5maWxsPW51bGw7dGhpcy5tYXJnaW49bnVsbH1bc3NdKCl7aWYoIXRoaXNbSmldKXtjb25zdCBlPXRoaXMuZWRnZS5jaGlsZHJlbi5zbGljZSgpO2lmKGUubGVuZ3RoPDQpe2NvbnN0IHQ9ZS5hdCgtMSl8fG5ldyBFZGdlKHt9KTtmb3IobGV0IHI9ZS5sZW5ndGg7cjw0O3IrKyllLnB1c2godCl9Y29uc3QgdD1lLm1hcChlPT5lLnRoaWNrbmVzcykscj1bMCwwLDAsMF07aWYodGhpcy5tYXJnaW4pe3JbMF09dGhpcy5tYXJnaW4udG9wSW5zZXQ7clsxXT10aGlzLm1hcmdpbi5yaWdodEluc2V0O3JbMl09dGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7clszXT10aGlzLm1hcmdpbi5sZWZ0SW5zZXR9dGhpc1tKaV09e3dpZHRoczp0LGluc2V0czpyLGVkZ2VzOmV9fXJldHVybiB0aGlzW0ppXX1bWXNdKCl7Y29uc3R7ZWRnZXM6ZX09dGhpc1tzc10oKSx0PWUubWFwKGU9Pntjb25zdCB0PWVbWXNdKCk7dC5jb2xvcnx8PSIjMDAwMDAwIjtyZXR1cm4gdH0pLHI9T2JqZWN0LmNyZWF0ZShudWxsKTt0aGlzLm1hcmdpbiYmT2JqZWN0LmFzc2lnbihyLHRoaXMubWFyZ2luW1lzXSgpKTsidmlzaWJsZSI9PT10aGlzLmZpbGw/LnByZXNlbmNlJiZPYmplY3QuYXNzaWduKHIsdGhpcy5maWxsW1lzXSgpKTtpZih0aGlzLmNvcm5lci5jaGlsZHJlbi5zb21lKGU9PjAhPT1lLnJhZGl1cykpe2NvbnN0IGU9dGhpcy5jb3JuZXIuY2hpbGRyZW4ubWFwKGU9PmVbWXNdKCkpO2lmKDI9PT1lLmxlbmd0aHx8Mz09PWUubGVuZ3RoKXtjb25zdCB0PWUuYXQoLTEpO2ZvcihsZXQgcj1lLmxlbmd0aDtyPDQ7cisrKWUucHVzaCh0KX1yLmJvcmRlclJhZGl1cz1lLm1hcChlPT5lLnJhZGl1cykuam9pbigiICIpfXN3aXRjaCh0aGlzLnByZXNlbmNlKXtjYXNlImludmlzaWJsZSI6Y2FzZSJoaWRkZW4iOnIuYm9yZGVyU3R5bGU9IiI7YnJlYWs7Y2FzZSJpbmFjdGl2ZSI6ci5ib3JkZXJTdHlsZT0ibm9uZSI7YnJlYWs7ZGVmYXVsdDpyLmJvcmRlclN0eWxlPXQubWFwKGU9PmUuc3R5bGUpLmpvaW4oIiAiKX1yLmJvcmRlcldpZHRoPXQubWFwKGU9PmUud2lkdGgpLmpvaW4oIiAiKTtyLmJvcmRlckNvbG9yPXQubWFwKGU9PmUuY29sb3IpLmpvaW4oIiAiKTtyZXR1cm4gcn19Y2xhc3MgQnJlYWsgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImJyZWFrIiwhMCk7dGhpcy5hZnRlcj1nZXRTdHJpbmdPcHRpb24oZS5hZnRlcixbImF1dG8iLCJjb250ZW50QXJlYSIsInBhZ2VBcmVhIiwicGFnZUV2ZW4iLCJwYWdlT2RkIl0pO3RoaXMuYWZ0ZXJUYXJnZXQ9ZS5hZnRlclRhcmdldHx8IiI7dGhpcy5iZWZvcmU9Z2V0U3RyaW5nT3B0aW9uKGUuYmVmb3JlLFsiYXV0byIsImNvbnRlbnRBcmVhIiwicGFnZUFyZWEiLCJwYWdlRXZlbiIsInBhZ2VPZGQiXSk7dGhpcy5iZWZvcmVUYXJnZXQ9ZS5iZWZvcmVUYXJnZXR8fCIiO3RoaXMuYm9va2VuZExlYWRlcj1lLmJvb2tlbmRMZWFkZXJ8fCIiO3RoaXMuYm9va2VuZFRyYWlsZXI9ZS5ib29rZW5kVHJhaWxlcnx8IiI7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm92ZXJmbG93TGVhZGVyPWUub3ZlcmZsb3dMZWFkZXJ8fCIiO3RoaXMub3ZlcmZsb3dUYXJnZXQ9ZS5vdmVyZmxvd1RhcmdldHx8IiI7dGhpcy5vdmVyZmxvd1RyYWlsZXI9ZS5vdmVyZmxvd1RyYWlsZXJ8fCIiO3RoaXMuc3RhcnROZXc9Z2V0SW50ZWdlcih7ZGF0YTplLnN0YXJ0TmV3LGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PjE9PT1lfSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGx9fWNsYXNzIEJyZWFrQWZ0ZXIgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImJyZWFrQWZ0ZXIiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubGVhZGVyPWUubGVhZGVyfHwiIjt0aGlzLnN0YXJ0TmV3PWdldEludGVnZXIoe2RhdGE6ZS5zdGFydE5ldyxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIjt0aGlzLnRhcmdldFR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudGFyZ2V0VHlwZSxbImF1dG8iLCJjb250ZW50QXJlYSIsInBhZ2VBcmVhIl0pO3RoaXMudHJhaWxlcj1lLnRyYWlsZXJ8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnNjcmlwdD1udWxsfX1jbGFzcyBCcmVha0JlZm9yZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiYnJlYWtCZWZvcmUiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubGVhZGVyPWUubGVhZGVyfHwiIjt0aGlzLnN0YXJ0TmV3PWdldEludGVnZXIoe2RhdGE6ZS5zdGFydE5ldyxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIjt0aGlzLnRhcmdldFR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudGFyZ2V0VHlwZSxbImF1dG8iLCJjb250ZW50QXJlYSIsInBhZ2VBcmVhIl0pO3RoaXMudHJhaWxlcj1lLnRyYWlsZXJ8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnNjcmlwdD1udWxsfVtLc10oZSl7dGhpc1tKaV09e307cmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRX19Y2xhc3MgQnV0dG9uIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJidXR0b24iLCEwKTt0aGlzLmhpZ2hsaWdodD1nZXRTdHJpbmdPcHRpb24oZS5oaWdobGlnaHQsWyJpbnZlcnRlZCIsIm5vbmUiLCJvdXRsaW5lIiwicHVzaCJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsfVtLc10oZSl7Y29uc3QgdD10aGlzW2RzXSgpW2RzXSgpLHI9e25hbWU6ImJ1dHRvbiIsYXR0cmlidXRlczp7aWQ6dGhpc1tac10sY2xhc3M6WyJ4ZmFCdXR0b24iXSxzdHlsZTp7fX0sY2hpbGRyZW46W119O2Zvcihjb25zdCBlIG9mIHQuZXZlbnQuY2hpbGRyZW4pe2lmKCJjbGljayIhPT1lLmFjdGl2aXR5fHwhZS5zY3JpcHQpY29udGludWU7Y29uc3QgdD1yZWNvdmVySnNVUkwoZS5zY3JpcHRbJGldKTtpZighdCljb250aW51ZTtjb25zdCBhPWZpeFVSTCh0LnVybCk7YSYmci5jaGlsZHJlbi5wdXNoKHtuYW1lOiJhIixhdHRyaWJ1dGVzOntpZDoibGluayIrdGhpc1tac10saHJlZjphLG5ld1dpbmRvdzp0Lm5ld1dpbmRvdyxjbGFzczpbInhmYUxpbmsiXSxzdHlsZTp7fX0sY2hpbGRyZW46W119KX1yZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHIpfX1jbGFzcyBDYWxjdWxhdGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNhbGN1bGF0ZSIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5vdmVycmlkZT1nZXRTdHJpbmdPcHRpb24oZS5vdmVycmlkZSxbImRpc2FibGVkIiwiZXJyb3IiLCJpZ25vcmUiLCJ3YXJuaW5nIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsO3RoaXMubWVzc2FnZT1udWxsO3RoaXMuc2NyaXB0PW51bGx9fWNsYXNzIENhcHRpb24gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNhcHRpb24iLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMucGxhY2VtZW50PWdldFN0cmluZ09wdGlvbihlLnBsYWNlbWVudCxbImxlZnQiLCJib3R0b20iLCJpbmxpbmUiLCJyaWdodCIsInRvcCJdKTt0aGlzLnByZXNlbmNlPWdldFN0cmluZ09wdGlvbihlLnByZXNlbmNlLFsidmlzaWJsZSIsImhpZGRlbiIsImluYWN0aXZlIiwiaW52aXNpYmxlIl0pO3RoaXMucmVzZXJ2ZT1NYXRoLmNlaWwoZ2V0TWVhc3VyZW1lbnQoZS5yZXNlcnZlKSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5mb250PW51bGw7dGhpcy5tYXJnaW49bnVsbDt0aGlzLnBhcmE9bnVsbDt0aGlzLnZhbHVlPW51bGx9W3pzXShlKXtfc2V0VmFsdWUodGhpcyxlKX1bc3NdKGUpe2lmKCF0aGlzW0ppXSl7bGV0e3dpZHRoOnQsaGVpZ2h0OnJ9PWU7c3dpdGNoKHRoaXMucGxhY2VtZW50KXtjYXNlImxlZnQiOmNhc2UicmlnaHQiOmNhc2UiaW5saW5lIjp0PXRoaXMucmVzZXJ2ZTw9MD90OnRoaXMucmVzZXJ2ZTticmVhaztjYXNlInRvcCI6Y2FzZSJib3R0b20iOnI9dGhpcy5yZXNlcnZlPD0wP3I6dGhpcy5yZXNlcnZlfXRoaXNbSmldPWxheW91dE5vZGUodGhpcyx7d2lkdGg6dCxoZWlnaHQ6cn0pfXJldHVybiB0aGlzW0ppXX1bS3NdKGUpe2lmKCF0aGlzLnZhbHVlKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO3RoaXNbTHNdKCk7Y29uc3QgdD10aGlzLnZhbHVlW0tzXShlKS5odG1sO2lmKCF0KXt0aGlzW19zXSgpO3JldHVybiBIVE1MUmVzdWx0LkVNUFRZfWNvbnN0IHI9dGhpcy5yZXNlcnZlO2lmKHRoaXMucmVzZXJ2ZTw9MCl7Y29uc3R7dzp0LGg6cn09dGhpc1tzc10oZSk7c3dpdGNoKHRoaXMucGxhY2VtZW50KXtjYXNlImxlZnQiOmNhc2UicmlnaHQiOmNhc2UiaW5saW5lIjp0aGlzLnJlc2VydmU9dDticmVhaztjYXNlInRvcCI6Y2FzZSJib3R0b20iOnRoaXMucmVzZXJ2ZT1yfX1jb25zdCBhPVtdOyJzdHJpbmciPT10eXBlb2YgdD9hLnB1c2goe25hbWU6IiN0ZXh0Iix2YWx1ZTp0fSk6YS5wdXNoKHQpO2NvbnN0IG49dG9TdHlsZSh0aGlzLCJmb250IiwibWFyZ2luIiwidmlzaWJpbGl0eSIpO3N3aXRjaCh0aGlzLnBsYWNlbWVudCl7Y2FzZSJsZWZ0IjpjYXNlInJpZ2h0Ijp0aGlzLnJlc2VydmU+MCYmKG4ud2lkdGg9bWVhc3VyZVRvU3RyaW5nKHRoaXMucmVzZXJ2ZSkpO2JyZWFrO2Nhc2UidG9wIjpjYXNlImJvdHRvbSI6dGhpcy5yZXNlcnZlPjAmJihuLmhlaWdodD1tZWFzdXJlVG9TdHJpbmcodGhpcy5yZXNlcnZlKSl9c2V0UGFyYSh0aGlzLG51bGwsdCk7dGhpc1tfc10oKTt0aGlzLnJlc2VydmU9cjtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e3N0eWxlOm4sY2xhc3M6WyJ4ZmFDYXB0aW9uIl19LGNoaWxkcmVuOmF9KX19Y2xhc3MgQ2VydGlmaWNhdGUgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNlcnRpZmljYXRlIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIENlcnRpZmljYXRlcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiY2VydGlmaWNhdGVzIiwhMCk7dGhpcy5jcmVkZW50aWFsU2VydmVyUG9saWN5PWdldFN0cmluZ09wdGlvbihlLmNyZWRlbnRpYWxTZXJ2ZXJQb2xpY3ksWyJvcHRpb25hbCIsInJlcXVpcmVkIl0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy51cmw9ZS51cmx8fCIiO3RoaXMudXJsUG9saWN5PWUudXJsUG9saWN5fHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5lbmNyeXB0aW9uPW51bGw7dGhpcy5pc3N1ZXJzPW51bGw7dGhpcy5rZXlVc2FnZT1udWxsO3RoaXMub2lkcz1udWxsO3RoaXMuc2lnbmluZz1udWxsO3RoaXMuc3ViamVjdEROcz1udWxsfX1jbGFzcyBDaGVja0J1dHRvbiBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiY2hlY2tCdXR0b24iLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubWFyaz1nZXRTdHJpbmdPcHRpb24oZS5tYXJrLFsiZGVmYXVsdCIsImNoZWNrIiwiY2lyY2xlIiwiY3Jvc3MiLCJkaWFtb25kIiwic3F1YXJlIiwic3RhciJdKTt0aGlzLnNoYXBlPWdldFN0cmluZ09wdGlvbihlLnNoYXBlLFsic3F1YXJlIiwicm91bmQiXSk7dGhpcy5zaXplPWdldE1lYXN1cmVtZW50KGUuc2l6ZSwiMTBwdCIpO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmJvcmRlcj1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5tYXJnaW49bnVsbH1bS3NdKGUpe2NvbnN0IHQ9dG9TdHlsZSh0aGlzLCJtYXJnaW4iKSxyPW1lYXN1cmVUb1N0cmluZyh0aGlzLnNpemUpO3Qud2lkdGg9dC5oZWlnaHQ9cjtsZXQgYSxuLGk7Y29uc3Qgcz10aGlzW2RzXSgpW2RzXSgpLG89cy5pdGVtcy5jaGlsZHJlbi5sZW5ndGgmJnMuaXRlbXMuY2hpbGRyZW5bMF1bS3NdKCkuaHRtbHx8W10sYz17b246KHZvaWQgMCE9PW9bMF0/b1swXToib24iKS50b1N0cmluZygpLG9mZjoodm9pZCAwIT09b1sxXT9vWzFdOiJvZmYiKS50b1N0cmluZygpfSxsPShzLnZhbHVlPy5bJHNdKCl8fCJvZmYiKT09PWMub258fHZvaWQgMCxoPXNbdXNdKCksdT1zW1pzXTtsZXQgZDtpZihoIGluc3RhbmNlb2YgRXhjbEdyb3VwKXtpPWhbWnNdO2E9InJhZGlvIjtuPSJ4ZmFSYWRpbyI7ZD1oW1ZpXT8uW1pzXXx8aFtac119ZWxzZXthPSJjaGVja2JveCI7bj0ieGZhQ2hlY2tib3giO2Q9c1tWaV0/Lltac118fHNbWnNdfWNvbnN0IGY9e25hbWU6ImlucHV0IixhdHRyaWJ1dGVzOntjbGFzczpbbl0sc3R5bGU6dCxmaWVsZElkOnUsZGF0YUlkOmQsdHlwZTphLGNoZWNrZWQ6bCx4ZmFPbjpjLm9uLHhmYU9mZjpjLm9mZiwiYXJpYS1sYWJlbCI6YXJpYUxhYmVsKHMpLCJhcmlhLXJlcXVpcmVkIjohMX19O2kmJihmLmF0dHJpYnV0ZXMubmFtZT1pKTtpZihpc1JlcXVpcmVkKHMpKXtmLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXT0hMDtmLmF0dHJpYnV0ZXMucmVxdWlyZWQ9ITB9cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7bmFtZToibGFiZWwiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhTGFiZWwiXX0sY2hpbGRyZW46W2ZdfSl9fWNsYXNzIENob2ljZUxpc3QgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNob2ljZUxpc3QiLCEwKTt0aGlzLmNvbW1pdE9uPWdldFN0cmluZ09wdGlvbihlLmNvbW1pdE9uLFsic2VsZWN0IiwiZXhpdCJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMub3Blbj1nZXRTdHJpbmdPcHRpb24oZS5vcGVuLFsidXNlckNvbnRyb2wiLCJhbHdheXMiLCJtdWx0aVNlbGVjdCIsIm9uRW50cnkiXSk7dGhpcy50ZXh0RW50cnk9Z2V0SW50ZWdlcih7ZGF0YTplLnRleHRFbnRyeSxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmJvcmRlcj1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5tYXJnaW49bnVsbH1bS3NdKGUpe2NvbnN0IHQ9dG9TdHlsZSh0aGlzLCJib3JkZXIiLCJtYXJnaW4iKSxyPXRoaXNbZHNdKClbZHNdKCksYT17Zm9udFNpemU6YGNhbGMoJHtyLmZvbnQ/LnNpemV8fDEwfXB4ICogdmFyKC0tdG90YWwtc2NhbGUtZmFjdG9yKSlgfSxuPVtdO2lmKHIuaXRlbXMuY2hpbGRyZW4ubGVuZ3RoPjApe2NvbnN0IGU9ci5pdGVtcztsZXQgdD0wLGk9MDtpZigyPT09ZS5jaGlsZHJlbi5sZW5ndGgpe3Q9ZS5jaGlsZHJlblswXS5zYXZlO2k9MS10fWNvbnN0IHM9ZS5jaGlsZHJlblt0XVtLc10oKS5odG1sLG89ZS5jaGlsZHJlbltpXVtLc10oKS5odG1sO2xldCBjPSExO2NvbnN0IGw9ci52YWx1ZT8uWyRzXSgpfHwiIjtmb3IobGV0IGU9MCx0PXMubGVuZ3RoO2U8dDtlKyspe2NvbnN0IHQ9e25hbWU6Im9wdGlvbiIsYXR0cmlidXRlczp7dmFsdWU6b1tlXXx8c1tlXSxzdHlsZTphfSx2YWx1ZTpzW2VdfTtvW2VdPT09bCYmKHQuYXR0cmlidXRlcy5zZWxlY3RlZD1jPSEwKTtuLnB1c2godCl9Y3x8bi5zcGxpY2UoMCwwLHtuYW1lOiJvcHRpb24iLGF0dHJpYnV0ZXM6e2hpZGRlbjohMCxzZWxlY3RlZDohMH0sdmFsdWU6IiAifSl9Y29uc3QgaT17Y2xhc3M6WyJ4ZmFTZWxlY3QiXSxmaWVsZElkOnJbWnNdLGRhdGFJZDpyW1ZpXT8uW1pzXXx8cltac10sc3R5bGU6dCwiYXJpYS1sYWJlbCI6YXJpYUxhYmVsKHIpLCJhcmlhLXJlcXVpcmVkIjohMX07aWYoaXNSZXF1aXJlZChyKSl7aVsiYXJpYS1yZXF1aXJlZCJdPSEwO2kucmVxdWlyZWQ9ITB9Im11bHRpU2VsZWN0Ij09PXRoaXMub3BlbiYmKGkubXVsdGlwbGU9ITApO3JldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moe25hbWU6ImxhYmVsIixhdHRyaWJ1dGVzOntjbGFzczpbInhmYUxhYmVsIl19LGNoaWxkcmVuOlt7bmFtZToic2VsZWN0IixjaGlsZHJlbjpuLGF0dHJpYnV0ZXM6aX1dfSl9fWNsYXNzIENvbG9yIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJjb2xvciIsITApO3RoaXMuY1NwYWNlPWdldFN0cmluZ09wdGlvbihlLmNTcGFjZSxbIlNSR0IiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy52YWx1ZT1lLnZhbHVlP2Z1bmN0aW9uIGdldENvbG9yKGUsdD1bMCwwLDBdKXtsZXRbcixhLG5dPXQ7aWYoIWUpcmV0dXJue3IsZzphLGI6bn07Y29uc3QgaT1lLnNwbGl0KCIsIiwzKS5tYXAoZT0+TWF0aENsYW1wKHBhcnNlSW50KGUudHJpbSgpLDEwKSwwLDI1NSkpLm1hcChlPT5pc05hTihlKT8wOmUpO2lmKGkubGVuZ3RoPDMpcmV0dXJue3IsZzphLGI6bn07W3IsYSxuXT1pO3JldHVybntyLGc6YSxiOm59fShlLnZhbHVlKToiIjt0aGlzLmV4dHJhcz1udWxsfVtwc10oKXtyZXR1cm4hMX1bWXNdKCl7cmV0dXJuIHRoaXMudmFsdWU/VXRpbC5tYWtlSGV4Q29sb3IodGhpcy52YWx1ZS5yLHRoaXMudmFsdWUuZyx0aGlzLnZhbHVlLmIpOm51bGx9fWNsYXNzIENvbWIgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNvbWIiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubnVtYmVyT2ZDZWxscz1nZXRJbnRlZ2VyKHtkYXRhOmUubnVtYmVyT2ZDZWxscyxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT5lPj0wfSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBDb25uZWN0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJjb25uZWN0IiwhMCk7dGhpcy5jb25uZWN0aW9uPWUuY29ubmVjdGlvbnx8IiI7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnJlZj1lLnJlZnx8IiI7dGhpcy51c2FnZT1nZXRTdHJpbmdPcHRpb24oZS51c2FnZSxbImV4cG9ydEFuZEltcG9ydCIsImV4cG9ydE9ubHkiLCJpbXBvcnRPbmx5Il0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnBpY3R1cmU9bnVsbH19Y2xhc3MgQ29udGVudEFyZWEgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImNvbnRlbnRBcmVhIiwhMCk7dGhpcy5oPWdldE1lYXN1cmVtZW50KGUuaCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnJlbGV2YW50PWdldFJlbGV2YW50KGUucmVsZXZhbnQpO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnc9Z2V0TWVhc3VyZW1lbnQoZS53KTt0aGlzLng9Z2V0TWVhc3VyZW1lbnQoZS54LCIwcHQiKTt0aGlzLnk9Z2V0TWVhc3VyZW1lbnQoZS55LCIwcHQiKTt0aGlzLmRlc2M9bnVsbDt0aGlzLmV4dHJhcz1udWxsfVtLc10oZSl7Y29uc3QgdD17bGVmdDptZWFzdXJlVG9TdHJpbmcodGhpcy54KSx0b3A6bWVhc3VyZVRvU3RyaW5nKHRoaXMueSksd2lkdGg6bWVhc3VyZVRvU3RyaW5nKHRoaXMudyksaGVpZ2h0Om1lYXN1cmVUb1N0cmluZyh0aGlzLmgpfSxyPVsieGZhQ29udGVudGFyZWEiXTtpc1ByaW50T25seSh0aGlzKSYmci5wdXNoKCJ4ZmFQcmludE9ubHkiKTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGNoaWxkcmVuOltdLGF0dHJpYnV0ZXM6e3N0eWxlOnQsY2xhc3M6cixpZDp0aGlzW1pzXX19KX19Y2xhc3MgQ29ybmVyIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJjb3JuZXIiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMuaW52ZXJ0ZWQ9Z2V0SW50ZWdlcih7ZGF0YTplLmludmVydGVkLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PjE9PT1lfSk7dGhpcy5qb2luPWdldFN0cmluZ09wdGlvbihlLmpvaW4sWyJzcXVhcmUiLCJyb3VuZCJdKTt0aGlzLnByZXNlbmNlPWdldFN0cmluZ09wdGlvbihlLnByZXNlbmNlLFsidmlzaWJsZSIsImhpZGRlbiIsImluYWN0aXZlIiwiaW52aXNpYmxlIl0pO3RoaXMucmFkaXVzPWdldE1lYXN1cmVtZW50KGUucmFkaXVzKTt0aGlzLnN0cm9rZT1nZXRTdHJpbmdPcHRpb24oZS5zdHJva2UsWyJzb2xpZCIsImRhc2hEb3QiLCJkYXNoRG90RG90IiwiZGFzaGVkIiwiZG90dGVkIiwiZW1ib3NzZWQiLCJldGNoZWQiLCJsb3dlcmVkIiwicmFpc2VkIl0pO3RoaXMudGhpY2tuZXNzPWdldE1lYXN1cmVtZW50KGUudGhpY2tuZXNzLCIwLjVwdCIpO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmNvbG9yPW51bGw7dGhpcy5leHRyYXM9bnVsbH1bWXNdKCl7Y29uc3QgZT10b1N0eWxlKHRoaXMsInZpc2liaWxpdHkiKTtlLnJhZGl1cz1tZWFzdXJlVG9TdHJpbmcoInNxdWFyZSI9PT10aGlzLmpvaW4/MDp0aGlzLnJhZGl1cyk7cmV0dXJuIGV9fWNsYXNzIERhdGVFbGVtZW50IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZGF0ZSIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifVtZaV0oKXtjb25zdCBlPXRoaXNbJGldLnRyaW0oKTt0aGlzWyRpXT1lP25ldyBEYXRlKGUpOm51bGx9W0tzXShlKXtyZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skaV0/dGhpc1skaV0udG9TdHJpbmcoKToiIil9fWNsYXNzIERhdGVUaW1lIGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZGF0ZVRpbWUiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn1bWWldKCl7Y29uc3QgZT10aGlzWyRpXS50cmltKCk7dGhpc1skaV09ZT9uZXcgRGF0ZShlKTpudWxsfVtLc10oZSl7cmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbJGldP3RoaXNbJGldLnRvU3RyaW5nKCk6IiIpfX1jbGFzcyBEYXRlVGltZUVkaXQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImRhdGVUaW1lRWRpdCIsITApO3RoaXMuaFNjcm9sbFBvbGljeT1nZXRTdHJpbmdPcHRpb24oZS5oU2Nyb2xsUG9saWN5LFsiYXV0byIsIm9mZiIsIm9uIl0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5waWNrZXI9Z2V0U3RyaW5nT3B0aW9uKGUucGlja2VyLFsiaG9zdCIsIm5vbmUiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuYm9yZGVyPW51bGw7dGhpcy5jb21iPW51bGw7dGhpcy5leHRyYXM9bnVsbDt0aGlzLm1hcmdpbj1udWxsfVtLc10oZSl7Y29uc3QgdD10b1N0eWxlKHRoaXMsImJvcmRlciIsImZvbnQiLCJtYXJnaW4iKSxyPXRoaXNbZHNdKClbZHNdKCksYT17bmFtZToiaW5wdXQiLGF0dHJpYnV0ZXM6e3R5cGU6InRleHQiLGZpZWxkSWQ6cltac10sZGF0YUlkOnJbVmldPy5bWnNdfHxyW1pzXSxjbGFzczpbInhmYVRleHRmaWVsZCJdLHN0eWxlOnQsImFyaWEtbGFiZWwiOmFyaWFMYWJlbChyKSwiYXJpYS1yZXF1aXJlZCI6ITF9fTtpZihpc1JlcXVpcmVkKHIpKXthLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXT0hMDthLmF0dHJpYnV0ZXMucmVxdWlyZWQ9ITB9cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7bmFtZToibGFiZWwiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhTGFiZWwiXX0sY2hpbGRyZW46W2FdfSl9fWNsYXNzIERlY2ltYWwgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJkZWNpbWFsIik7dGhpcy5mcmFjRGlnaXRzPWdldEludGVnZXIoe2RhdGE6ZS5mcmFjRGlnaXRzLGRlZmF1bHRWYWx1ZToyLHZhbGlkYXRlOmU9PiEwfSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmxlYWREaWdpdHM9Z2V0SW50ZWdlcih7ZGF0YTplLmxlYWREaWdpdHMsZGVmYXVsdFZhbHVlOi0xLHZhbGlkYXRlOmU9PiEwfSk7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifVtZaV0oKXtjb25zdCBlPXBhcnNlRmxvYXQodGhpc1skaV0udHJpbSgpKTt0aGlzWyRpXT1pc05hTihlKT9udWxsOmV9W0tzXShlKXtyZXR1cm4gdmFsdWVUb0h0bWwobnVsbCE9PXRoaXNbJGldP3RoaXNbJGldLnRvU3RyaW5nKCk6IiIpfX1jbGFzcyBEZWZhdWx0VWkgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImRlZmF1bHRVaSIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGx9fWNsYXNzIERlc2MgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImRlc2MiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmJvb2xlYW49bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5kYXRlVGltZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5kZWNpbWFsPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmV4RGF0YT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5mbG9hdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbWFnZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbnRlZ2VyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRleHQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudGltZT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIERpZ2VzdE1ldGhvZCBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZGlnZXN0TWV0aG9kIixbIiIsIlNIQTEiLCJTSEEyNTYiLCJTSEE1MTIiLCJSSVBFTUQxNjAiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIERpZ2VzdE1ldGhvZHMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImRpZ2VzdE1ldGhvZHMiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudHlwZT1nZXRTdHJpbmdPcHRpb24oZS50eXBlLFsib3B0aW9uYWwiLCJyZXF1aXJlZCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5kaWdlc3RNZXRob2Q9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBEcmF3IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJkcmF3IiwhMCk7dGhpcy5hbmNob3JUeXBlPWdldFN0cmluZ09wdGlvbihlLmFuY2hvclR5cGUsWyJ0b3BMZWZ0IiwiYm90dG9tQ2VudGVyIiwiYm90dG9tTGVmdCIsImJvdHRvbVJpZ2h0IiwibWlkZGxlQ2VudGVyIiwibWlkZGxlTGVmdCIsIm1pZGRsZVJpZ2h0IiwidG9wQ2VudGVyIiwidG9wUmlnaHQiXSk7dGhpcy5jb2xTcGFuPWdldEludGVnZXIoe2RhdGE6ZS5jb2xTcGFuLGRlZmF1bHRWYWx1ZToxLHZhbGlkYXRlOmU9PmU+PTF8fC0xPT09ZX0pO3RoaXMuaD1lLmg/Z2V0TWVhc3VyZW1lbnQoZS5oKToiIjt0aGlzLmhBbGlnbj1nZXRTdHJpbmdPcHRpb24oZS5oQWxpZ24sWyJsZWZ0IiwiY2VudGVyIiwianVzdGlmeSIsImp1c3RpZnlBbGwiLCJyYWRpeCIsInJpZ2h0Il0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5sb2NhbGU9ZS5sb2NhbGV8fCIiO3RoaXMubWF4SD1nZXRNZWFzdXJlbWVudChlLm1heEgsIjBwdCIpO3RoaXMubWF4Vz1nZXRNZWFzdXJlbWVudChlLm1heFcsIjBwdCIpO3RoaXMubWluSD1nZXRNZWFzdXJlbWVudChlLm1pbkgsIjBwdCIpO3RoaXMubWluVz1nZXRNZWFzdXJlbWVudChlLm1pblcsIjBwdCIpO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucHJlc2VuY2U9Z2V0U3RyaW5nT3B0aW9uKGUucHJlc2VuY2UsWyJ2aXNpYmxlIiwiaGlkZGVuIiwiaW5hY3RpdmUiLCJpbnZpc2libGUiXSk7dGhpcy5yZWxldmFudD1nZXRSZWxldmFudChlLnJlbGV2YW50KTt0aGlzLnJvdGF0ZT1nZXRJbnRlZ2VyKHtkYXRhOmUucm90YXRlLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PmUlOTA9PTB9KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy53PWUudz9nZXRNZWFzdXJlbWVudChlLncpOiIiO3RoaXMueD1nZXRNZWFzdXJlbWVudChlLngsIjBwdCIpO3RoaXMueT1nZXRNZWFzdXJlbWVudChlLnksIjBwdCIpO3RoaXMuYXNzaXN0PW51bGw7dGhpcy5ib3JkZXI9bnVsbDt0aGlzLmNhcHRpb249bnVsbDt0aGlzLmRlc2M9bnVsbDt0aGlzLmV4dHJhcz1udWxsO3RoaXMuZm9udD1udWxsO3RoaXMua2VlcD1udWxsO3RoaXMubWFyZ2luPW51bGw7dGhpcy5wYXJhPW51bGw7dGhpcy50cmF2ZXJzYWw9bnVsbDt0aGlzLnVpPW51bGw7dGhpcy52YWx1ZT1udWxsO3RoaXMuc2V0UHJvcGVydHk9bmV3IFhGQU9iamVjdEFycmF5fVt6c10oZSl7X3NldFZhbHVlKHRoaXMsZSl9W0tzXShlKXtzZXRUYWJJbmRleCh0aGlzKTtpZigiaGlkZGVuIj09PXRoaXMucHJlc2VuY2V8fCJpbmFjdGl2ZSI9PT10aGlzLnByZXNlbmNlKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO2ZpeERpbWVuc2lvbnModGhpcyk7dGhpc1tMc10oKTtjb25zdCB0PXRoaXMudyxyPXRoaXMuaCx7dzphLGg6bixpc0Jyb2tlbjppfT1sYXlvdXROb2RlKHRoaXMsZSk7aWYoYSYmIiI9PT10aGlzLncpe2lmKGkmJnRoaXNbdXNdKClbdnNdKCkpe3RoaXNbX3NdKCk7cmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRX10aGlzLnc9YX1uJiYiIj09PXRoaXMuaCYmKHRoaXMuaD1uKTtzZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTtpZighY2hlY2tEaW1lbnNpb25zKHRoaXMsZSkpe3RoaXMudz10O3RoaXMuaD1yO3RoaXNbX3NdKCk7cmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRX11bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpO2NvbnN0IHM9dG9TdHlsZSh0aGlzLCJmb250IiwiaEFsaWduIiwiZGltZW5zaW9ucyIsInBvc2l0aW9uIiwicHJlc2VuY2UiLCJyb3RhdGUiLCJhbmNob3JUeXBlIiwiYm9yZGVyIiwibWFyZ2luIik7c2V0TWluTWF4RGltZW5zaW9ucyh0aGlzLHMpO2lmKHMubWFyZ2luKXtzLnBhZGRpbmc9cy5tYXJnaW47ZGVsZXRlIHMubWFyZ2lufWNvbnN0IG89WyJ4ZmFEcmF3Il07dGhpcy5mb250JiZvLnB1c2goInhmYUZvbnQiKTtpc1ByaW50T25seSh0aGlzKSYmby5wdXNoKCJ4ZmFQcmludE9ubHkiKTtjb25zdCBjPXtzdHlsZTpzLGlkOnRoaXNbWnNdLGNsYXNzOm99O3RoaXMubmFtZSYmKGMueGZhTmFtZT10aGlzLm5hbWUpO2NvbnN0IGw9e25hbWU6ImRpdiIsYXR0cmlidXRlczpjLGNoaWxkcmVuOltdfTthcHBseUFzc2lzdCh0aGlzLGMpO2NvbnN0IGg9Y29tcHV0ZUJib3godGhpcyxsLGUpLHU9dGhpcy52YWx1ZT90aGlzLnZhbHVlW0tzXShlKS5odG1sOm51bGw7aWYobnVsbD09PXUpe3RoaXMudz10O3RoaXMuaD1yO3RoaXNbX3NdKCk7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsbCksaCl9bC5jaGlsZHJlbi5wdXNoKHUpO3NldFBhcmEodGhpcyxzLHUpO3RoaXMudz10O3RoaXMuaD1yO3RoaXNbX3NdKCk7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsbCksaCl9fWNsYXNzIEVkZ2UgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImVkZ2UiLCEwKTt0aGlzLmNhcD1nZXRTdHJpbmdPcHRpb24oZS5jYXAsWyJzcXVhcmUiLCJidXR0Iiwicm91bmQiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnByZXNlbmNlPWdldFN0cmluZ09wdGlvbihlLnByZXNlbmNlLFsidmlzaWJsZSIsImhpZGRlbiIsImluYWN0aXZlIiwiaW52aXNpYmxlIl0pO3RoaXMuc3Ryb2tlPWdldFN0cmluZ09wdGlvbihlLnN0cm9rZSxbInNvbGlkIiwiZGFzaERvdCIsImRhc2hEb3REb3QiLCJkYXNoZWQiLCJkb3R0ZWQiLCJlbWJvc3NlZCIsImV0Y2hlZCIsImxvd2VyZWQiLCJyYWlzZWQiXSk7dGhpcy50aGlja25lc3M9Z2V0TWVhc3VyZW1lbnQoZS50aGlja25lc3MsIjAuNXB0Iik7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuY29sb3I9bnVsbDt0aGlzLmV4dHJhcz1udWxsfVtZc10oKXtjb25zdCBlPXRvU3R5bGUodGhpcywidmlzaWJpbGl0eSIpO09iamVjdC5hc3NpZ24oZSx7bGluZWNhcDp0aGlzLmNhcCx3aWR0aDptZWFzdXJlVG9TdHJpbmcodGhpcy50aGlja25lc3MpLGNvbG9yOnRoaXMuY29sb3I/dGhpcy5jb2xvcltZc10oKToiIzAwMDAwMCIsc3R5bGU6IiJ9KTtpZigidmlzaWJsZSIhPT10aGlzLnByZXNlbmNlKWUuc3R5bGU9Im5vbmUiO2Vsc2Ugc3dpdGNoKHRoaXMuc3Ryb2tlKXtjYXNlInNvbGlkIjplLnN0eWxlPSJzb2xpZCI7YnJlYWs7Y2FzZSJkYXNoRG90IjpjYXNlImRhc2hEb3REb3QiOmNhc2UiZGFzaGVkIjplLnN0eWxlPSJkYXNoZWQiO2JyZWFrO2Nhc2UiZG90dGVkIjplLnN0eWxlPSJkb3R0ZWQiO2JyZWFrO2Nhc2UiZW1ib3NzZWQiOmUuc3R5bGU9InJpZGdlIjticmVhaztjYXNlImV0Y2hlZCI6ZS5zdHlsZT0iZ3Jvb3ZlIjticmVhaztjYXNlImxvd2VyZWQiOmUuc3R5bGU9Imluc2V0IjticmVhaztjYXNlInJhaXNlZCI6ZS5zdHlsZT0ib3V0c2V0In1yZXR1cm4gZX19Y2xhc3MgRW5jb2RpbmcgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImVuY29kaW5nIixbImFkYmUueDUwOS5yc2Ffc2hhMSIsImFkYmUucGtjczcuZGV0YWNoZWQiLCJhZGJlLnBrY3M3LnNoYTEiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIEVuY29kaW5ncyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZW5jb2RpbmdzIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZW5jb2Rpbmc9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBFbmNyeXB0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJlbmNyeXB0IiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jZXJ0aWZpY2F0ZT1udWxsfX1jbGFzcyBFbmNyeXB0RGF0YSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZW5jcnlwdERhdGEiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMub3BlcmF0aW9uPWdldFN0cmluZ09wdGlvbihlLm9wZXJhdGlvbixbImVuY3J5cHQiLCJkZWNyeXB0Il0pO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5maWx0ZXI9bnVsbDt0aGlzLm1hbmlmZXN0PW51bGx9fWNsYXNzIEVuY3J5cHRpb24gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImVuY3J5cHRpb24iLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudHlwZT1nZXRTdHJpbmdPcHRpb24oZS50eXBlLFsib3B0aW9uYWwiLCJyZXF1aXJlZCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jZXJ0aWZpY2F0ZT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIEVuY3J5cHRpb25NZXRob2QgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImVuY3J5cHRpb25NZXRob2QiLFsiIiwiQUVTMjU2LUNCQyIsIlRSSVBMRURFUy1DQkMiLCJBRVMxMjgtQ0JDIiwiQUVTMTkyLUNCQyJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgRW5jcnlwdGlvbk1ldGhvZHMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImVuY3J5cHRpb25NZXRob2RzIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZW5jcnlwdGlvbk1ldGhvZD1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIEV2ZW50IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJldmVudCIsITApO3RoaXMuYWN0aXZpdHk9Z2V0U3RyaW5nT3B0aW9uKGUuYWN0aXZpdHksWyJjbGljayIsImNoYW5nZSIsImRvY0Nsb3NlIiwiZG9jUmVhZHkiLCJlbnRlciIsImV4aXQiLCJmdWxsIiwiaW5kZXhDaGFuZ2UiLCJpbml0aWFsaXplIiwibW91c2VEb3duIiwibW91c2VFbnRlciIsIm1vdXNlRXhpdCIsIm1vdXNlVXAiLCJwb3N0RXhlY3V0ZSIsInBvc3RPcGVuIiwicG9zdFByaW50IiwicG9zdFNhdmUiLCJwb3N0U2lnbiIsInBvc3RTdWJtaXQiLCJwcmVFeGVjdXRlIiwicHJlT3BlbiIsInByZVByaW50IiwicHJlU2F2ZSIsInByZVNpZ24iLCJwcmVTdWJtaXQiLCJyZWFkeSIsInZhbGlkYXRpb25TdGF0ZSJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubGlzdGVuPWdldFN0cmluZ09wdGlvbihlLmxpc3RlbixbInJlZk9ubHkiLCJyZWZBbmREZXNjZW5kZW50cyJdKTt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnJlZj1lLnJlZnx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5lbmNyeXB0RGF0YT1udWxsO3RoaXMuZXhlY3V0ZT1udWxsO3RoaXMuc2NyaXB0PW51bGw7dGhpcy5zaWduRGF0YT1udWxsO3RoaXMuc3VibWl0PW51bGx9fWNsYXNzIEV4RGF0YSBleHRlbmRzIENvbnRlbnRPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImV4RGF0YSIpO3RoaXMuY29udGVudFR5cGU9ZS5jb250ZW50VHlwZXx8IiI7dGhpcy5ocmVmPWUuaHJlZnx8IiI7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm1heExlbmd0aD1nZXRJbnRlZ2VyKHtkYXRhOmUubWF4TGVuZ3RoLGRlZmF1bHRWYWx1ZTotMSx2YWxpZGF0ZTplPT5lPj0tMX0pO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucmlkPWUucmlkfHwiIjt0aGlzLnRyYW5zZmVyRW5jb2Rpbmc9Z2V0U3RyaW5nT3B0aW9uKGUudHJhbnNmZXJFbmNvZGluZyxbIm5vbmUiLCJiYXNlNjQiLCJwYWNrYWdlIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn1bd3NdKCl7cmV0dXJuInRleHQvaHRtbCI9PT10aGlzLmNvbnRlbnRUeXBlfVtCc10oZSl7aWYoInRleHQvaHRtbCI9PT10aGlzLmNvbnRlbnRUeXBlJiZlW09zXT09PWVvLnhodG1sLmlkKXt0aGlzWyRpXT1lO3JldHVybiEwfWlmKCJ0ZXh0L3htbCI9PT10aGlzLmNvbnRlbnRUeXBlKXt0aGlzWyRpXT1lO3JldHVybiEwfXJldHVybiExfVtLc10oZSl7cmV0dXJuInRleHQvaHRtbCI9PT10aGlzLmNvbnRlbnRUeXBlJiZ0aGlzWyRpXT90aGlzWyRpXVtLc10oZSk6SFRNTFJlc3VsdC5FTVBUWX19Y2xhc3MgRXhPYmplY3QgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImV4T2JqZWN0IiwhMCk7dGhpcy5hcmNoaXZlPWUuYXJjaGl2ZXx8IiI7dGhpcy5jbGFzc0lkPWUuY2xhc3NJZHx8IiI7dGhpcy5jb2RlQmFzZT1lLmNvZGVCYXNlfHwiIjt0aGlzLmNvZGVUeXBlPWUuY29kZVR5cGV8fCIiO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5ib29sZWFuPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRhdGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZVRpbWU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGVjaW1hbD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leERhdGE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhPYmplY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmxvYXQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW1hZ2U9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW50ZWdlcj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50ZXh0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRpbWU9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBFeGNsR3JvdXAgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImV4Y2xHcm91cCIsITApO3RoaXMuYWNjZXNzPWdldFN0cmluZ09wdGlvbihlLmFjY2VzcyxbIm9wZW4iLCJub25JbnRlcmFjdGl2ZSIsInByb3RlY3RlZCIsInJlYWRPbmx5Il0pO3RoaXMuYWNjZXNzS2V5PWUuYWNjZXNzS2V5fHwiIjt0aGlzLmFuY2hvclR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUuYW5jaG9yVHlwZSxbInRvcExlZnQiLCJib3R0b21DZW50ZXIiLCJib3R0b21MZWZ0IiwiYm90dG9tUmlnaHQiLCJtaWRkbGVDZW50ZXIiLCJtaWRkbGVMZWZ0IiwibWlkZGxlUmlnaHQiLCJ0b3BDZW50ZXIiLCJ0b3BSaWdodCJdKTt0aGlzLmNvbFNwYW49Z2V0SW50ZWdlcih7ZGF0YTplLmNvbFNwYW4sZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ZT49MXx8LTE9PT1lfSk7dGhpcy5oPWUuaD9nZXRNZWFzdXJlbWVudChlLmgpOiIiO3RoaXMuaEFsaWduPWdldFN0cmluZ09wdGlvbihlLmhBbGlnbixbImxlZnQiLCJjZW50ZXIiLCJqdXN0aWZ5IiwianVzdGlmeUFsbCIsInJhZGl4IiwicmlnaHQiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmxheW91dD1nZXRTdHJpbmdPcHRpb24oZS5sYXlvdXQsWyJwb3NpdGlvbiIsImxyLXRiIiwicmwtcm93IiwicmwtdGIiLCJyb3ciLCJ0YWJsZSIsInRiIl0pO3RoaXMubWF4SD1nZXRNZWFzdXJlbWVudChlLm1heEgsIjBwdCIpO3RoaXMubWF4Vz1nZXRNZWFzdXJlbWVudChlLm1heFcsIjBwdCIpO3RoaXMubWluSD1nZXRNZWFzdXJlbWVudChlLm1pbkgsIjBwdCIpO3RoaXMubWluVz1nZXRNZWFzdXJlbWVudChlLm1pblcsIjBwdCIpO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucHJlc2VuY2U9Z2V0U3RyaW5nT3B0aW9uKGUucHJlc2VuY2UsWyJ2aXNpYmxlIiwiaGlkZGVuIiwiaW5hY3RpdmUiLCJpbnZpc2libGUiXSk7dGhpcy5yZWxldmFudD1nZXRSZWxldmFudChlLnJlbGV2YW50KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy53PWUudz9nZXRNZWFzdXJlbWVudChlLncpOiIiO3RoaXMueD1nZXRNZWFzdXJlbWVudChlLngsIjBwdCIpO3RoaXMueT1nZXRNZWFzdXJlbWVudChlLnksIjBwdCIpO3RoaXMuYXNzaXN0PW51bGw7dGhpcy5iaW5kPW51bGw7dGhpcy5ib3JkZXI9bnVsbDt0aGlzLmNhbGN1bGF0ZT1udWxsO3RoaXMuY2FwdGlvbj1udWxsO3RoaXMuZGVzYz1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5tYXJnaW49bnVsbDt0aGlzLnBhcmE9bnVsbDt0aGlzLnRyYXZlcnNhbD1udWxsO3RoaXMudmFsaWRhdGU9bnVsbDt0aGlzLmNvbm5lY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXZlbnQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmllbGQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc2V0UHJvcGVydHk9bmV3IFhGQU9iamVjdEFycmF5fVt4c10oKXtyZXR1cm4hMH1bcHNdKCl7cmV0dXJuITB9W3pzXShlKXtmb3IoY29uc3QgdCBvZiB0aGlzLmZpZWxkLmNoaWxkcmVuKXtpZighdC52YWx1ZSl7Y29uc3QgZT1uZXcgVmFsdWUoe30pO3RbamldKGUpO3QudmFsdWU9ZX10LnZhbHVlW3pzXShlKX19W3ZzXSgpe3JldHVybiB0aGlzLmxheW91dC5lbmRzV2l0aCgiLXRiIikmJjA9PT10aGlzW0ppXS5hdHRlbXB0JiZ0aGlzW0ppXS5udW1iZXJJbkxpbmU+MHx8dGhpc1tkc10oKVt2c10oKX1bQ3NdKCl7Y29uc3QgZT10aGlzW3VzXSgpO2lmKCFlW0NzXSgpKXJldHVybiExO2lmKHZvaWQgMCE9PXRoaXNbSmldLl9pc1NwbGl0dGFibGUpcmV0dXJuIHRoaXNbSmldLl9pc1NwbGl0dGFibGU7aWYoInBvc2l0aW9uIj09PXRoaXMubGF5b3V0fHx0aGlzLmxheW91dC5pbmNsdWRlcygicm93Iikpe3RoaXNbSmldLl9pc1NwbGl0dGFibGU9ITE7cmV0dXJuITF9aWYoZS5sYXlvdXQ/LmVuZHNXaXRoKCItdGIiKSYmMCE9PWVbSmldLm51bWJlckluTGluZSlyZXR1cm4hMTt0aGlzW0ppXS5faXNTcGxpdHRhYmxlPSEwO3JldHVybiEwfVtaaV0oKXtyZXR1cm4gZmx1c2hIVE1MKHRoaXMpfVtfaV0oZSx0KXthZGRIVE1MKHRoaXMsZSx0KX1bdHNdKCl7cmV0dXJuIGdldEF2YWlsYWJsZVNwYWNlKHRoaXMpfVtLc10oZSl7c2V0VGFiSW5kZXgodGhpcyk7aWYoImhpZGRlbiI9PT10aGlzLnByZXNlbmNlfHwiaW5hY3RpdmUiPT09dGhpcy5wcmVzZW5jZXx8MD09PXRoaXMuaHx8MD09PXRoaXMudylyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTtmaXhEaW1lbnNpb25zKHRoaXMpO2NvbnN0IHQ9W10scj17aWQ6dGhpc1tac10sY2xhc3M6W119O3NldEFjY2Vzcyh0aGlzLHIuY2xhc3MpO3RoaXNbSmldfHw9T2JqZWN0LmNyZWF0ZShudWxsKTtPYmplY3QuYXNzaWduKHRoaXNbSmldLHtjaGlsZHJlbjp0LGF0dHJpYnV0ZXM6cixhdHRlbXB0OjAsbGluZTpudWxsLG51bWJlckluTGluZTowLGF2YWlsYWJsZVNwYWNlOnt3aWR0aDpNYXRoLm1pbih0aGlzLnd8fDEvMCxlLndpZHRoKSxoZWlnaHQ6TWF0aC5taW4odGhpcy5ofHwxLzAsZS5oZWlnaHQpfSx3aWR0aDowLGhlaWdodDowLHByZXZIZWlnaHQ6MCxjdXJyZW50V2lkdGg6MH0pO2NvbnN0IGE9dGhpc1tDc10oKTthfHxzZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTtpZighY2hlY2tEaW1lbnNpb25zKHRoaXMsZSkpcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTtjb25zdCBuPW5ldyBTZXQoWyJmaWVsZCJdKTtpZih0aGlzLmxheW91dC5pbmNsdWRlcygicm93Iikpe2NvbnN0IGU9dGhpc1t1c10oKS5jb2x1bW5XaWR0aHM7aWYoQXJyYXkuaXNBcnJheShlKSYmZS5sZW5ndGg+MCl7dGhpc1tKaV0uY29sdW1uV2lkdGhzPWU7dGhpc1tKaV0uY3VycmVudENvbHVtbj0wfX1jb25zdCBpPXRvU3R5bGUodGhpcywiYW5jaG9yVHlwZSIsImRpbWVuc2lvbnMiLCJwb3NpdGlvbiIsInByZXNlbmNlIiwiYm9yZGVyIiwibWFyZ2luIiwiaEFsaWduIikscz1bInhmYUV4Y2xncm91cCJdLG89bGF5b3V0Q2xhc3ModGhpcyk7byYmcy5wdXNoKG8pO2lzUHJpbnRPbmx5KHRoaXMpJiZzLnB1c2goInhmYVByaW50T25seSIpO3Iuc3R5bGU9aTtyLmNsYXNzPXM7dGhpcy5uYW1lJiYoci54ZmFOYW1lPXRoaXMubmFtZSk7dGhpc1tMc10oKTtjb25zdCBjPSJsci10YiI9PT10aGlzLmxheW91dHx8InJsLXRiIj09PXRoaXMubGF5b3V0LGw9Yz8yOjE7Zm9yKDt0aGlzW0ppXS5hdHRlbXB0PGw7dGhpc1tKaV0uYXR0ZW1wdCsrKXtjJiYxPT09dGhpc1tKaV0uYXR0ZW1wdCYmKHRoaXNbSmldLm51bWJlckluTGluZT0wKTtjb25zdCBlPXRoaXNbcWldKHtmaWx0ZXI6bixpbmNsdWRlOiEwfSk7aWYoZS5zdWNjZXNzKWJyZWFrO2lmKGUuaXNCcmVhaygpKXt0aGlzW19zXSgpO3JldHVybiBlfWlmKGMmJjA9PT10aGlzW0ppXS5hdHRlbXB0JiYwPT09dGhpc1tKaV0ubnVtYmVySW5MaW5lJiYhdGhpc1tmc10oKVtKaV0ubm9MYXlvdXRGYWlsdXJlKXt0aGlzW0ppXS5hdHRlbXB0PWw7YnJlYWt9fXRoaXNbX3NdKCk7YXx8dW5zZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTtpZih0aGlzW0ppXS5hdHRlbXB0PT09bCl7YXx8ZGVsZXRlIHRoaXNbSmldO3JldHVybiBIVE1MUmVzdWx0LkZBSUxVUkV9bGV0IGg9MCx1PTA7aWYodGhpcy5tYXJnaW4pe2g9dGhpcy5tYXJnaW4ubGVmdEluc2V0K3RoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7dT10aGlzLm1hcmdpbi50b3BJbnNldCt0aGlzLm1hcmdpbi5ib3R0b21JbnNldH1jb25zdCBkPU1hdGgubWF4KHRoaXNbSmldLndpZHRoK2gsdGhpcy53fHwwKSxmPU1hdGgubWF4KHRoaXNbSmldLmhlaWdodCt1LHRoaXMuaHx8MCksZz1bdGhpcy54LHRoaXMueSxkLGZdOyIiPT09dGhpcy53JiYoaS53aWR0aD1tZWFzdXJlVG9TdHJpbmcoZCkpOyIiPT09dGhpcy5oJiYoaS5oZWlnaHQ9bWVhc3VyZVRvU3RyaW5nKGYpKTtjb25zdCBwPXtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6cixjaGlsZHJlbjp0fTthcHBseUFzc2lzdCh0aGlzLHIpO2RlbGV0ZSB0aGlzW0ppXTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcyxwKSxnKX19Y2xhc3MgRXhlY3V0ZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZXhlY3V0ZSIpO3RoaXMuY29ubmVjdGlvbj1lLmNvbm5lY3Rpb258fCIiO3RoaXMuZXhlY3V0ZVR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUuZXhlY3V0ZVR5cGUsWyJpbXBvcnQiLCJyZW1lcmdlIl0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5ydW5BdD1nZXRTdHJpbmdPcHRpb24oZS5ydW5BdCxbImNsaWVudCIsImJvdGgiLCJzZXJ2ZXIiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBFeHRyYXMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImV4dHJhcyIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuYm9vbGVhbj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5kYXRlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRhdGVUaW1lPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRlY2ltYWw9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhEYXRhPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmV4dHJhcz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5mbG9hdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbWFnZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbnRlZ2VyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRleHQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudGltZT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIEZpZWxkIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJmaWVsZCIsITApO3RoaXMuYWNjZXNzPWdldFN0cmluZ09wdGlvbihlLmFjY2VzcyxbIm9wZW4iLCJub25JbnRlcmFjdGl2ZSIsInByb3RlY3RlZCIsInJlYWRPbmx5Il0pO3RoaXMuYWNjZXNzS2V5PWUuYWNjZXNzS2V5fHwiIjt0aGlzLmFuY2hvclR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUuYW5jaG9yVHlwZSxbInRvcExlZnQiLCJib3R0b21DZW50ZXIiLCJib3R0b21MZWZ0IiwiYm90dG9tUmlnaHQiLCJtaWRkbGVDZW50ZXIiLCJtaWRkbGVMZWZ0IiwibWlkZGxlUmlnaHQiLCJ0b3BDZW50ZXIiLCJ0b3BSaWdodCJdKTt0aGlzLmNvbFNwYW49Z2V0SW50ZWdlcih7ZGF0YTplLmNvbFNwYW4sZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ZT49MXx8LTE9PT1lfSk7dGhpcy5oPWUuaD9nZXRNZWFzdXJlbWVudChlLmgpOiIiO3RoaXMuaEFsaWduPWdldFN0cmluZ09wdGlvbihlLmhBbGlnbixbImxlZnQiLCJjZW50ZXIiLCJqdXN0aWZ5IiwianVzdGlmeUFsbCIsInJhZGl4IiwicmlnaHQiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmxvY2FsZT1lLmxvY2FsZXx8IiI7dGhpcy5tYXhIPWdldE1lYXN1cmVtZW50KGUubWF4SCwiMHB0Iik7dGhpcy5tYXhXPWdldE1lYXN1cmVtZW50KGUubWF4VywiMHB0Iik7dGhpcy5taW5IPWdldE1lYXN1cmVtZW50KGUubWluSCwiMHB0Iik7dGhpcy5taW5XPWdldE1lYXN1cmVtZW50KGUubWluVywiMHB0Iik7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy5wcmVzZW5jZT1nZXRTdHJpbmdPcHRpb24oZS5wcmVzZW5jZSxbInZpc2libGUiLCJoaWRkZW4iLCJpbmFjdGl2ZSIsImludmlzaWJsZSJdKTt0aGlzLnJlbGV2YW50PWdldFJlbGV2YW50KGUucmVsZXZhbnQpO3RoaXMucm90YXRlPWdldEludGVnZXIoe2RhdGE6ZS5yb3RhdGUsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+ZSU5MD09MH0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnc9ZS53P2dldE1lYXN1cmVtZW50KGUudyk6IiI7dGhpcy54PWdldE1lYXN1cmVtZW50KGUueCwiMHB0Iik7dGhpcy55PWdldE1lYXN1cmVtZW50KGUueSwiMHB0Iik7dGhpcy5hc3Npc3Q9bnVsbDt0aGlzLmJpbmQ9bnVsbDt0aGlzLmJvcmRlcj1udWxsO3RoaXMuY2FsY3VsYXRlPW51bGw7dGhpcy5jYXB0aW9uPW51bGw7dGhpcy5kZXNjPW51bGw7dGhpcy5leHRyYXM9bnVsbDt0aGlzLmZvbnQ9bnVsbDt0aGlzLmZvcm1hdD1udWxsO3RoaXMuaXRlbXM9bmV3IFhGQU9iamVjdEFycmF5KDIpO3RoaXMua2VlcD1udWxsO3RoaXMubWFyZ2luPW51bGw7dGhpcy5wYXJhPW51bGw7dGhpcy50cmF2ZXJzYWw9bnVsbDt0aGlzLnVpPW51bGw7dGhpcy52YWxpZGF0ZT1udWxsO3RoaXMudmFsdWU9bnVsbDt0aGlzLmJpbmRJdGVtcz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jb25uZWN0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmV2ZW50PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnNldFByb3BlcnR5PW5ldyBYRkFPYmplY3RBcnJheX1beHNdKCl7cmV0dXJuITB9W3pzXShlKXtfc2V0VmFsdWUodGhpcyxlKX1bS3NdKGUpe3NldFRhYkluZGV4KHRoaXMpO2lmKCF0aGlzLnVpKXt0aGlzLnVpPW5ldyBVaSh7fSk7dGhpcy51aVtnc109dGhpc1tnc107dGhpc1tqaV0odGhpcy51aSk7bGV0IGU7c3dpdGNoKHRoaXMuaXRlbXMuY2hpbGRyZW4ubGVuZ3RoKXtjYXNlIDA6ZT1uZXcgVGV4dEVkaXQoe30pO3RoaXMudWkudGV4dEVkaXQ9ZTticmVhaztjYXNlIDE6ZT1uZXcgQ2hlY2tCdXR0b24oe30pO3RoaXMudWkuY2hlY2tCdXR0b249ZTticmVhaztjYXNlIDI6ZT1uZXcgQ2hvaWNlTGlzdCh7fSk7dGhpcy51aS5jaG9pY2VMaXN0PWV9dGhpcy51aVtqaV0oZSl9aWYoIXRoaXMudWl8fCJoaWRkZW4iPT09dGhpcy5wcmVzZW5jZXx8ImluYWN0aXZlIj09PXRoaXMucHJlc2VuY2V8fDA9PT10aGlzLmh8fDA9PT10aGlzLncpcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7dGhpcy5jYXB0aW9uJiZkZWxldGUgdGhpcy5jYXB0aW9uW0ppXTt0aGlzW0xzXSgpO2NvbnN0IHQ9dGhpcy5jYXB0aW9uP3RoaXMuY2FwdGlvbltLc10oZSkuaHRtbDpudWxsLHI9dGhpcy53LGE9dGhpcy5oO2xldCBuPTAsaT0wO2lmKHRoaXMubWFyZ2luKXtuPXRoaXMubWFyZ2luLmxlZnRJbnNldCt0aGlzLm1hcmdpbi5yaWdodEluc2V0O2k9dGhpcy5tYXJnaW4udG9wSW5zZXQrdGhpcy5tYXJnaW4uYm90dG9tSW5zZXR9bGV0IHM9bnVsbDtpZigiIj09PXRoaXMud3x8IiI9PT10aGlzLmgpe2xldCB0PW51bGwscj1udWxsLGE9MCxvPTA7aWYodGhpcy51aS5jaGVja0J1dHRvbilhPW89dGhpcy51aS5jaGVja0J1dHRvbi5zaXplO2Vsc2V7Y29uc3R7dzp0LGg6cn09bGF5b3V0Tm9kZSh0aGlzLGUpO2lmKG51bGwhPT10KXthPXQ7bz1yfWVsc2Ugbz1mdW5jdGlvbiBmb250c19nZXRNZXRyaWNzKGUsdD0hMSl7bGV0IHI9bnVsbDtpZihlKXtjb25zdCB0PXN0cmlwUXVvdGVzKGUudHlwZWZhY2UpLGE9ZVtnc10uZm9udEZpbmRlci5maW5kKHQpO3I9c2VsZWN0Rm9udChlLGEpfWlmKCFyKXJldHVybntsaW5lSGVpZ2h0OjEyLGxpbmVHYXA6MixsaW5lTm9HYXA6MTB9O2NvbnN0IGE9ZS5zaXplfHwxMCxuPXIubGluZUhlaWdodD9NYXRoLm1heCh0PzA6MS4yLHIubGluZUhlaWdodCk6MS4yLGk9dm9pZCAwPT09ci5saW5lR2FwPy4yOnIubGluZUdhcDtyZXR1cm57bGluZUhlaWdodDpuKmEsbGluZUdhcDppKmEsbGluZU5vR2FwOk1hdGgubWF4KDEsbi1pKSphfX0odGhpcy5mb250LCEwKS5saW5lTm9HYXB9cz1nZXRCb3JkZXJEaW1zKHRoaXMudWlbc3NdKCkpO2ErPXMudztvKz1zLmg7aWYodGhpcy5jYXB0aW9uKXtjb25zdHt3Om4saDppLGlzQnJva2VuOnN9PXRoaXMuY2FwdGlvbltzc10oZSk7aWYocyYmdGhpc1t1c10oKVt2c10oKSl7dGhpc1tfc10oKTtyZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFfXQ9bjtyPWk7c3dpdGNoKHRoaXMuY2FwdGlvbi5wbGFjZW1lbnQpe2Nhc2UibGVmdCI6Y2FzZSJyaWdodCI6Y2FzZSJpbmxpbmUiOnQrPWE7YnJlYWs7Y2FzZSJ0b3AiOmNhc2UiYm90dG9tIjpyKz1vfX1lbHNle3Q9YTtyPW99aWYodCYmIiI9PT10aGlzLncpe3QrPW47dGhpcy53PU1hdGgubWluKHRoaXMubWF4Vzw9MD8xLzA6dGhpcy5tYXhXLHRoaXMubWluVysxPHQ/dDp0aGlzLm1pblcpfWlmKHImJiIiPT09dGhpcy5oKXtyKz1pO3RoaXMuaD1NYXRoLm1pbih0aGlzLm1heEg8PTA/MS8wOnRoaXMubWF4SCx0aGlzLm1pbkgrMTxyP3I6dGhpcy5taW5IKX19dGhpc1tfc10oKTtmaXhEaW1lbnNpb25zKHRoaXMpO3NldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpO2lmKCFjaGVja0RpbWVuc2lvbnModGhpcyxlKSl7dGhpcy53PXI7dGhpcy5oPWE7dGhpc1tfc10oKTtyZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFfXVuc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7Y29uc3Qgbz10b1N0eWxlKHRoaXMsImZvbnQiLCJkaW1lbnNpb25zIiwicG9zaXRpb24iLCJyb3RhdGUiLCJhbmNob3JUeXBlIiwicHJlc2VuY2UiLCJtYXJnaW4iLCJoQWxpZ24iKTtzZXRNaW5NYXhEaW1lbnNpb25zKHRoaXMsbyk7Y29uc3QgYz1bInhmYUZpZWxkIl07dGhpcy5mb250JiZjLnB1c2goInhmYUZvbnQiKTtpc1ByaW50T25seSh0aGlzKSYmYy5wdXNoKCJ4ZmFQcmludE9ubHkiKTtjb25zdCBsPXtzdHlsZTpvLGlkOnRoaXNbWnNdLGNsYXNzOmN9O2lmKG8ubWFyZ2luKXtvLnBhZGRpbmc9by5tYXJnaW47ZGVsZXRlIG8ubWFyZ2lufXNldEFjY2Vzcyh0aGlzLGMpO3RoaXMubmFtZSYmKGwueGZhTmFtZT10aGlzLm5hbWUpO2NvbnN0IGg9W10sdT17bmFtZToiZGl2IixhdHRyaWJ1dGVzOmwsY2hpbGRyZW46aH07YXBwbHlBc3Npc3QodGhpcyxsKTtjb25zdCBkPXRoaXMuYm9yZGVyP3RoaXMuYm9yZGVyW1lzXSgpOm51bGwsZj1jb21wdXRlQmJveCh0aGlzLHUsZSksZz10aGlzLnVpW0tzXSgpLmh0bWw7aWYoIWcpe09iamVjdC5hc3NpZ24obyxkKTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcyx1KSxmKX10aGlzW0dzXSYmKGcuY2hpbGRyZW4/LlswXT9nLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMudGFiaW5kZXg9dGhpc1tHc106Zy5hdHRyaWJ1dGVzLnRhYmluZGV4PXRoaXNbR3NdKTtnLmF0dHJpYnV0ZXMuc3R5bGV8fD1PYmplY3QuY3JlYXRlKG51bGwpO2xldCBwPW51bGw7aWYodGhpcy51aS5idXR0b24pezE9PT1nLmNoaWxkcmVuLmxlbmd0aCYmKFtwXT1nLmNoaWxkcmVuLnNwbGljZSgwLDEpKTtPYmplY3QuYXNzaWduKGcuYXR0cmlidXRlcy5zdHlsZSxkKX1lbHNlIE9iamVjdC5hc3NpZ24obyxkKTtoLnB1c2goZyk7aWYodGhpcy52YWx1ZSlpZih0aGlzLnVpLmltYWdlRWRpdClnLmNoaWxkcmVuLnB1c2godGhpcy52YWx1ZVtLc10oKS5odG1sKTtlbHNlIGlmKCF0aGlzLnVpLmJ1dHRvbil7bGV0IGU9IiI7aWYodGhpcy52YWx1ZS5leERhdGEpZT10aGlzLnZhbHVlLmV4RGF0YVskc10oKTtlbHNlIGlmKHRoaXMudmFsdWUudGV4dCllPXRoaXMudmFsdWUudGV4dFtzc10oKTtlbHNle2NvbnN0IHQ9dGhpcy52YWx1ZVtLc10oKS5odG1sO251bGwhPT10JiYoZT10LmNoaWxkcmVuWzBdLnZhbHVlKX10aGlzLnVpLnRleHRFZGl0JiZ0aGlzLnZhbHVlLnRleHQ/Lm1heENoYXJzJiYoZy5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLm1heExlbmd0aD10aGlzLnZhbHVlLnRleHQubWF4Q2hhcnMpO2lmKGUpe2lmKHRoaXMudWkubnVtZXJpY0VkaXQpe2U9cGFyc2VGbG9hdChlKTtlPWlzTmFOKGUpPyIiOmUudG9TdHJpbmcoKX0idGV4dGFyZWEiPT09Zy5jaGlsZHJlblswXS5uYW1lP2cuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy50ZXh0Q29udGVudD1lOmcuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy52YWx1ZT1lfX1pZighdGhpcy51aS5pbWFnZUVkaXQmJmcuY2hpbGRyZW4/LlswXSYmdGhpcy5oKXtzPXN8fGdldEJvcmRlckRpbXModGhpcy51aVtzc10oKSk7bGV0IHQ9MDtpZih0aGlzLmNhcHRpb24mJlsidG9wIiwiYm90dG9tIl0uaW5jbHVkZXModGhpcy5jYXB0aW9uLnBsYWNlbWVudCkpe3Q9dGhpcy5jYXB0aW9uLnJlc2VydmU7dDw9MCYmKHQ9dGhpcy5jYXB0aW9uW3NzXShlKS5oKTtjb25zdCByPXRoaXMuaC10LWktcy5oO2cuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQ9bWVhc3VyZVRvU3RyaW5nKHIpfWVsc2UgZy5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnN0eWxlLmhlaWdodD0iMTAwJSJ9cCYmZy5jaGlsZHJlbi5wdXNoKHApO2lmKCF0KXtnLmF0dHJpYnV0ZXMuY2xhc3MmJmcuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFMZWZ0Iik7dGhpcy53PXI7dGhpcy5oPWE7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsdSksZil9aWYodGhpcy51aS5idXR0b24pe28ucGFkZGluZyYmZGVsZXRlIG8ucGFkZGluZzsiZGl2Ij09PXQubmFtZSYmKHQubmFtZT0ic3BhbiIpO2cuY2hpbGRyZW4ucHVzaCh0KTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHUsZil9dGhpcy51aS5jaGVja0J1dHRvbiYmKHQuYXR0cmlidXRlcy5jbGFzc1swXT0ieGZhQ2FwdGlvbkZvckNoZWNrQnV0dG9uIik7Zy5hdHRyaWJ1dGVzLmNsYXNzfHw9W107Zy5jaGlsZHJlbi5zcGxpY2UoMCwwLHQpO3N3aXRjaCh0aGlzLmNhcHRpb24ucGxhY2VtZW50KXtjYXNlImxlZnQiOmNhc2UiaW5saW5lIjpnLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhTGVmdCIpO2JyZWFrO2Nhc2UicmlnaHQiOmcuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFSaWdodCIpO2JyZWFrO2Nhc2UidG9wIjpnLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhVG9wIik7YnJlYWs7Y2FzZSJib3R0b20iOmcuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFCb3R0b20iKX10aGlzLnc9cjt0aGlzLmg9YTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcyx1KSxmKX19Y2xhc3MgRmlsbCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZmlsbCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5wcmVzZW5jZT1nZXRTdHJpbmdPcHRpb24oZS5wcmVzZW5jZSxbInZpc2libGUiLCJoaWRkZW4iLCJpbmFjdGl2ZSIsImludmlzaWJsZSJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jb2xvcj1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5saW5lYXI9bnVsbDt0aGlzLnBhdHRlcm49bnVsbDt0aGlzLnJhZGlhbD1udWxsO3RoaXMuc29saWQ9bnVsbDt0aGlzLnN0aXBwbGU9bnVsbH1bWXNdKCl7Y29uc3QgZT10aGlzW2RzXSgpLHQ9ZVtkc10oKVtkc10oKSxyPU9iamVjdC5jcmVhdGUobnVsbCk7bGV0IGE9ImNvbG9yIixuPWE7aWYoZSBpbnN0YW5jZW9mIEJvcmRlcil7YT0iYmFja2dyb3VuZC1jb2xvciI7bj0iYmFja2dyb3VuZCI7dCBpbnN0YW5jZW9mIFVpJiYoci5iYWNrZ3JvdW5kQ29sb3I9IndoaXRlIil9aWYoZSBpbnN0YW5jZW9mIFJlY3RhbmdsZXx8ZSBpbnN0YW5jZW9mIEFyYyl7YT1uPSJmaWxsIjtyLmZpbGw9IndoaXRlIn1mb3IoY29uc3QgZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSl7aWYoImV4dHJhcyI9PT1lfHwiY29sb3IiPT09ZSljb250aW51ZTtjb25zdCB0PXRoaXNbZV07aWYoISh0IGluc3RhbmNlb2YgWEZBT2JqZWN0KSljb250aW51ZTtjb25zdCBpPXRbWXNdKHRoaXMuY29sb3IpO2kmJihyW2kuc3RhcnRzV2l0aCgiIyIpP2E6bl09aSk7cmV0dXJuIHJ9aWYodGhpcy5jb2xvcj8udmFsdWUpe2NvbnN0IGU9dGhpcy5jb2xvcltZc10oKTtyW2Uuc3RhcnRzV2l0aCgiIyIpP2E6bl09ZX1yZXR1cm4gcn19Y2xhc3MgRmlsdGVyIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJmaWx0ZXIiLCEwKTt0aGlzLmFkZFJldm9jYXRpb25JbmZvPWdldFN0cmluZ09wdGlvbihlLmFkZFJldm9jYXRpb25JbmZvLFsiIiwicmVxdWlyZWQiLCJvcHRpb25hbCIsIm5vbmUiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy52ZXJzaW9uPWdldEludGVnZXIoe2RhdGE6dGhpcy52ZXJzaW9uLGRlZmF1bHRWYWx1ZTo1LHZhbGlkYXRlOmU9PmU+PTEmJmU8PTV9KTt0aGlzLmFwcGVhcmFuY2VGaWx0ZXI9bnVsbDt0aGlzLmNlcnRpZmljYXRlcz1udWxsO3RoaXMuZGlnZXN0TWV0aG9kcz1udWxsO3RoaXMuZW5jb2RpbmdzPW51bGw7dGhpcy5lbmNyeXB0aW9uTWV0aG9kcz1udWxsO3RoaXMuaGFuZGxlcj1udWxsO3RoaXMubG9ja0RvY3VtZW50PW51bGw7dGhpcy5tZHA9bnVsbDt0aGlzLnJlYXNvbnM9bnVsbDt0aGlzLnRpbWVTdGFtcD1udWxsfX1jbGFzcyBGbG9hdCBleHRlbmRzIENvbnRlbnRPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImZsb2F0Iik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9W1lpXSgpe2NvbnN0IGU9cGFyc2VGbG9hdCh0aGlzWyRpXS50cmltKCkpO3RoaXNbJGldPWlzTmFOKGUpP251bGw6ZX1bS3NdKGUpe3JldHVybiB2YWx1ZVRvSHRtbChudWxsIT09dGhpc1skaV0/dGhpc1skaV0udG9TdHJpbmcoKToiIil9fWNsYXNzIHRlbXBsYXRlX0ZvbnQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImZvbnQiLCEwKTt0aGlzLmJhc2VsaW5lU2hpZnQ9Z2V0TWVhc3VyZW1lbnQoZS5iYXNlbGluZVNoaWZ0KTt0aGlzLmZvbnRIb3Jpem9udGFsU2NhbGU9Z2V0RmxvYXQoe2RhdGE6ZS5mb250SG9yaXpvbnRhbFNjYWxlLGRlZmF1bHRWYWx1ZToxMDAsdmFsaWRhdGU6ZT0+ZT49MH0pO3RoaXMuZm9udFZlcnRpY2FsU2NhbGU9Z2V0RmxvYXQoe2RhdGE6ZS5mb250VmVydGljYWxTY2FsZSxkZWZhdWx0VmFsdWU6MTAwLHZhbGlkYXRlOmU9PmU+PTB9KTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMua2VybmluZ01vZGU9Z2V0U3RyaW5nT3B0aW9uKGUua2VybmluZ01vZGUsWyJub25lIiwicGFpciJdKTt0aGlzLmxldHRlclNwYWNpbmc9Z2V0TWVhc3VyZW1lbnQoZS5sZXR0ZXJTcGFjaW5nLCIwIik7dGhpcy5saW5lVGhyb3VnaD1nZXRJbnRlZ2VyKHtkYXRhOmUubGluZVRocm91Z2gsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV8fDI9PT1lfSk7dGhpcy5saW5lVGhyb3VnaFBlcmlvZD1nZXRTdHJpbmdPcHRpb24oZS5saW5lVGhyb3VnaFBlcmlvZCxbImFsbCIsIndvcmQiXSk7dGhpcy5vdmVybGluZT1nZXRJbnRlZ2VyKHtkYXRhOmUub3ZlcmxpbmUsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV8fDI9PT1lfSk7dGhpcy5vdmVybGluZVBlcmlvZD1nZXRTdHJpbmdPcHRpb24oZS5vdmVybGluZVBlcmlvZCxbImFsbCIsIndvcmQiXSk7dGhpcy5wb3N0dXJlPWdldFN0cmluZ09wdGlvbihlLnBvc3R1cmUsWyJub3JtYWwiLCJpdGFsaWMiXSk7dGhpcy5zaXplPWdldE1lYXN1cmVtZW50KGUuc2l6ZSwiMTBwdCIpO3RoaXMudHlwZWZhY2U9ZS50eXBlZmFjZXx8IkNvdXJpZXIiO3RoaXMudW5kZXJsaW5lPWdldEludGVnZXIoe2RhdGE6ZS51bmRlcmxpbmUsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV8fDI9PT1lfSk7dGhpcy51bmRlcmxpbmVQZXJpb2Q9Z2V0U3RyaW5nT3B0aW9uKGUudW5kZXJsaW5lUGVyaW9kLFsiYWxsIiwid29yZCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy53ZWlnaHQ9Z2V0U3RyaW5nT3B0aW9uKGUud2VpZ2h0LFsibm9ybWFsIiwiYm9sZCJdKTt0aGlzLmV4dHJhcz1udWxsO3RoaXMuZmlsbD1udWxsfVtYaV0oZSl7c3VwZXJbWGldKGUpO3RoaXNbZ3NdLnVzZWRUeXBlZmFjZXMuYWRkKHRoaXMudHlwZWZhY2UpfVtZc10oKXtjb25zdCBlPXRvU3R5bGUodGhpcywiZmlsbCIpLHQ9ZS5jb2xvcjtpZih0KWlmKCIjMDAwMDAwIj09PXQpZGVsZXRlIGUuY29sb3I7ZWxzZSBpZighdC5zdGFydHNXaXRoKCIjIikpe2UuYmFja2dyb3VuZD10O2UuYmFja2dyb3VuZENsaXA9InRleHQiO2UuY29sb3I9InRyYW5zcGFyZW50In10aGlzLmJhc2VsaW5lU2hpZnQmJihlLnZlcnRpY2FsQWxpZ249bWVhc3VyZVRvU3RyaW5nKHRoaXMuYmFzZWxpbmVTaGlmdCkpO2UuZm9udEtlcm5pbmc9Im5vbmUiPT09dGhpcy5rZXJuaW5nTW9kZT8ibm9uZSI6Im5vcm1hbCI7ZS5sZXR0ZXJTcGFjaW5nPW1lYXN1cmVUb1N0cmluZyh0aGlzLmxldHRlclNwYWNpbmcpO2lmKDAhPT10aGlzLmxpbmVUaHJvdWdoKXtlLnRleHREZWNvcmF0aW9uPSJsaW5lLXRocm91Z2giOzI9PT10aGlzLmxpbmVUaHJvdWdoJiYoZS50ZXh0RGVjb3JhdGlvblN0eWxlPSJkb3VibGUiKX1pZigwIT09dGhpcy5vdmVybGluZSl7ZS50ZXh0RGVjb3JhdGlvbj0ib3ZlcmxpbmUiOzI9PT10aGlzLm92ZXJsaW5lJiYoZS50ZXh0RGVjb3JhdGlvblN0eWxlPSJkb3VibGUiKX1lLmZvbnRTdHlsZT10aGlzLnBvc3R1cmU7ZS5mb250U2l6ZT1tZWFzdXJlVG9TdHJpbmcoLjk5KnRoaXMuc2l6ZSk7c2V0Rm9udEZhbWlseSh0aGlzLHRoaXMsdGhpc1tnc10uZm9udEZpbmRlcixlKTtpZigwIT09dGhpcy51bmRlcmxpbmUpe2UudGV4dERlY29yYXRpb249InVuZGVybGluZSI7Mj09PXRoaXMudW5kZXJsaW5lJiYoZS50ZXh0RGVjb3JhdGlvblN0eWxlPSJkb3VibGUiKX1lLmZvbnRXZWlnaHQ9dGhpcy53ZWlnaHQ7cmV0dXJuIGV9fWNsYXNzIEZvcm1hdCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiZm9ybWF0IiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5leHRyYXM9bnVsbDt0aGlzLnBpY3R1cmU9bnVsbH19Y2xhc3MgSGFuZGxlciBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiaGFuZGxlciIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy50eXBlPWdldFN0cmluZ09wdGlvbihlLnR5cGUsWyJvcHRpb25hbCIsInJlcXVpcmVkIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgSHlwaGVuYXRpb24gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImh5cGhlbmF0aW9uIik7dGhpcy5leGNsdWRlQWxsQ2Fwcz1nZXRJbnRlZ2VyKHtkYXRhOmUuZXhjbHVkZUFsbENhcHMsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLmV4Y2x1ZGVJbml0aWFsQ2FwPWdldEludGVnZXIoe2RhdGE6ZS5leGNsdWRlSW5pdGlhbENhcCxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMuaHlwaGVuYXRlPWdldEludGVnZXIoe2RhdGE6ZS5oeXBoZW5hdGUsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMucHVzaENoYXJhY3RlckNvdW50PWdldEludGVnZXIoe2RhdGE6ZS5wdXNoQ2hhcmFjdGVyQ291bnQsZGVmYXVsdFZhbHVlOjMsdmFsaWRhdGU6ZT0+ZT49MH0pO3RoaXMucmVtYWluQ2hhcmFjdGVyQ291bnQ9Z2V0SW50ZWdlcih7ZGF0YTplLnJlbWFpbkNoYXJhY3RlckNvdW50LGRlZmF1bHRWYWx1ZTozLHZhbGlkYXRlOmU9PmU+PTB9KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy53b3JkQ2hhcmFjdGVyQ291bnQ9Z2V0SW50ZWdlcih7ZGF0YTplLndvcmRDaGFyYWN0ZXJDb3VudCxkZWZhdWx0VmFsdWU6Nyx2YWxpZGF0ZTplPT5lPj0wfSl9fWNsYXNzIEltYWdlIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJpbWFnZSIpO3RoaXMuYXNwZWN0PWdldFN0cmluZ09wdGlvbihlLmFzcGVjdCxbImZpdCIsImFjdHVhbCIsImhlaWdodCIsIm5vbmUiLCJ3aWR0aCJdKTt0aGlzLmNvbnRlbnRUeXBlPWUuY29udGVudFR5cGV8fCIiO3RoaXMuaHJlZj1lLmhyZWZ8fCIiO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy50cmFuc2ZlckVuY29kaW5nPWdldFN0cmluZ09wdGlvbihlLnRyYW5zZmVyRW5jb2RpbmcsWyJiYXNlNjQiLCJub25lIiwicGFja2FnZSJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9W0tzXSgpe2lmKHRoaXMuY29udGVudFR5cGUmJiFfby5oYXModGhpcy5jb250ZW50VHlwZS50b0xvd2VyQ2FzZSgpKSlyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTtsZXQgZT10aGlzW2dzXS5pbWFnZXM/LmdldCh0aGlzLmhyZWYpO2lmKCFlJiYodGhpcy5ocmVmfHwhdGhpc1skaV0pKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO2V8fCJiYXNlNjQiIT09dGhpcy50cmFuc2ZlckVuY29kaW5nfHwoZT1mdW5jdGlvbiBmcm9tQmFzZTY0VXRpbChlKXtyZXR1cm4gVWludDhBcnJheS5mcm9tQmFzZTY0P1VpbnQ4QXJyYXkuZnJvbUJhc2U2NChlKTpzdHJpbmdUb0J5dGVzKGF0b2IoZSkpfSh0aGlzWyRpXSkpO2lmKCFlKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO2lmKCF0aGlzLmNvbnRlbnRUeXBlKXtmb3IoY29uc3RbdCxyXW9mIExvKWlmKGUubGVuZ3RoPnQubGVuZ3RoJiZ0LmV2ZXJ5KCh0LHIpPT50PT09ZVtyXSkpe3RoaXMuY29udGVudFR5cGU9cjticmVha31pZighdGhpcy5jb250ZW50VHlwZSlyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWX1jb25zdCB0PW5ldyBCbG9iKFtlXSx7dHlwZTp0aGlzLmNvbnRlbnRUeXBlfSk7bGV0IHI7c3dpdGNoKHRoaXMuYXNwZWN0KXtjYXNlImZpdCI6Y2FzZSJhY3R1YWwiOmJyZWFrO2Nhc2UiaGVpZ2h0IjpyPXtoZWlnaHQ6IjEwMCUiLG9iamVjdEZpdDoiZmlsbCJ9O2JyZWFrO2Nhc2Uibm9uZSI6cj17d2lkdGg6IjEwMCUiLGhlaWdodDoiMTAwJSIsb2JqZWN0Rml0OiJmaWxsIn07YnJlYWs7Y2FzZSJ3aWR0aCI6cj17d2lkdGg6IjEwMCUiLG9iamVjdEZpdDoiZmlsbCJ9fWNvbnN0IGE9dGhpc1tkc10oKTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJpbWciLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhSW1hZ2UiXSxzdHlsZTpyLHNyYzpVUkwuY3JlYXRlT2JqZWN0VVJMKHQpLGFsdDphP2FyaWFMYWJlbChhW2RzXSgpKTpudWxsfX0pfX1jbGFzcyBJbWFnZUVkaXQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sImltYWdlRWRpdCIsITApO3RoaXMuZGF0YT1nZXRTdHJpbmdPcHRpb24oZS5kYXRhLFsibGluayIsImVtYmVkIl0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuYm9yZGVyPW51bGw7dGhpcy5leHRyYXM9bnVsbDt0aGlzLm1hcmdpbj1udWxsfVtLc10oZSl7cmV0dXJuImVtYmVkIj09PXRoaXMuZGF0YT9IVE1MUmVzdWx0LnN1Y2Nlc3Moe25hbWU6ImRpdiIsY2hpbGRyZW46W10sYXR0cmlidXRlczp7fX0pOkhUTUxSZXN1bHQuRU1QVFl9fWNsYXNzIEludGVnZXIgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJpbnRlZ2VyIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9W1lpXSgpe2NvbnN0IGU9cGFyc2VJbnQodGhpc1skaV0udHJpbSgpLDEwKTt0aGlzWyRpXT1pc05hTihlKT9udWxsOmV9W0tzXShlKXtyZXR1cm4gdmFsdWVUb0h0bWwobnVsbCE9PXRoaXNbJGldP3RoaXNbJGldLnRvU3RyaW5nKCk6IiIpfX1jbGFzcyBJc3N1ZXJzIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJpc3N1ZXJzIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuY2VydGlmaWNhdGU9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBJdGVtcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywiaXRlbXMiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucHJlc2VuY2U9Z2V0U3RyaW5nT3B0aW9uKGUucHJlc2VuY2UsWyJ2aXNpYmxlIiwiaGlkZGVuIiwiaW5hY3RpdmUiLCJpbnZpc2libGUiXSk7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMuc2F2ZT1nZXRJbnRlZ2VyKHtkYXRhOmUuc2F2ZSxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmJvb2xlYW49bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5kYXRlVGltZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5kZWNpbWFsPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmV4RGF0YT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5mbG9hdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbWFnZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pbnRlZ2VyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRleHQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudGltZT1uZXcgWEZBT2JqZWN0QXJyYXl9W0tzXSgpe2NvbnN0IGU9W107Zm9yKGNvbnN0IHQgb2YgdGhpc1tjc10oKSllLnB1c2godFskc10oKSk7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhlKX19Y2xhc3MgS2VlcCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywia2VlcCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7Y29uc3QgdD1bIm5vbmUiLCJjb250ZW50QXJlYSIsInBhZ2VBcmVhIl07dGhpcy5pbnRhY3Q9Z2V0U3RyaW5nT3B0aW9uKGUuaW50YWN0LHQpO3RoaXMubmV4dD1nZXRTdHJpbmdPcHRpb24oZS5uZXh0LHQpO3RoaXMucHJldmlvdXM9Z2V0U3RyaW5nT3B0aW9uKGUucHJldmlvdXMsdCk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGx9fWNsYXNzIEtleVVzYWdlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJrZXlVc2FnZSIpO2NvbnN0IHQ9WyIiLCJ5ZXMiLCJubyJdO3RoaXMuY3JsU2lnbj1nZXRTdHJpbmdPcHRpb24oZS5jcmxTaWduLHQpO3RoaXMuZGF0YUVuY2lwaGVybWVudD1nZXRTdHJpbmdPcHRpb24oZS5kYXRhRW5jaXBoZXJtZW50LHQpO3RoaXMuZGVjaXBoZXJPbmx5PWdldFN0cmluZ09wdGlvbihlLmRlY2lwaGVyT25seSx0KTt0aGlzLmRpZ2l0YWxTaWduYXR1cmU9Z2V0U3RyaW5nT3B0aW9uKGUuZGlnaXRhbFNpZ25hdHVyZSx0KTt0aGlzLmVuY2lwaGVyT25seT1nZXRTdHJpbmdPcHRpb24oZS5lbmNpcGhlck9ubHksdCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmtleUFncmVlbWVudD1nZXRTdHJpbmdPcHRpb24oZS5rZXlBZ3JlZW1lbnQsdCk7dGhpcy5rZXlDZXJ0U2lnbj1nZXRTdHJpbmdPcHRpb24oZS5rZXlDZXJ0U2lnbix0KTt0aGlzLmtleUVuY2lwaGVybWVudD1nZXRTdHJpbmdPcHRpb24oZS5rZXlFbmNpcGhlcm1lbnQsdCk7dGhpcy5ub25SZXB1ZGlhdGlvbj1nZXRTdHJpbmdPcHRpb24oZS5ub25SZXB1ZGlhdGlvbix0KTt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBMaW5lIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJsaW5lIiwhMCk7dGhpcy5oYW5kPWdldFN0cmluZ09wdGlvbihlLmhhbmQsWyJldmVuIiwibGVmdCIsInJpZ2h0Il0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5zbG9wZT1nZXRTdHJpbmdPcHRpb24oZS5zbG9wZSxbIlxcIiwiLyJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5lZGdlPW51bGx9W0tzXSgpe2NvbnN0IGU9dGhpc1tkc10oKVtkc10oKSx0PXRoaXMuZWRnZXx8bmV3IEVkZ2Uoe30pLHI9dFtZc10oKSxhPU9iamVjdC5jcmVhdGUobnVsbCksbj0idmlzaWJsZSI9PT10LnByZXNlbmNlP3QudGhpY2tuZXNzOjA7YS5zdHJva2VXaWR0aD1tZWFzdXJlVG9TdHJpbmcobik7YS5zdHJva2U9ci5jb2xvcjtsZXQgaSxzLG8sYyxsPSIxMDAlIixoPSIxMDAlIjtpZihlLnc8PW4pe1tpLHMsbyxjXT1bIjUwJSIsMCwiNTAlIiwiMTAwJSJdO2w9YS5zdHJva2VXaWR0aH1lbHNlIGlmKGUuaDw9bil7W2kscyxvLGNdPVswLCI1MCUiLCIxMDAlIiwiNTAlIl07aD1hLnN0cm9rZVdpZHRofWVsc2UiXFwiPT09dGhpcy5zbG9wZT9baSxzLG8sY109WzAsMCwiMTAwJSIsIjEwMCUiXTpbaSxzLG8sY109WzAsIjEwMCUiLCIxMDAlIiwwXTtjb25zdCB1PXtuYW1lOiJzdmciLGNoaWxkcmVuOlt7bmFtZToibGluZSIsYXR0cmlidXRlczp7eG1sbnM6Tm8seDE6aSx5MTpzLHgyOm8seTI6YyxzdHlsZTphfX1dLGF0dHJpYnV0ZXM6e3htbG5zOk5vLHdpZHRoOmwsaGVpZ2h0Omgsc3R5bGU6e292ZXJmbG93OiJ2aXNpYmxlIn19fTtpZihoYXNNYXJnaW4oZSkpcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7bmFtZToiZGl2IixhdHRyaWJ1dGVzOntzdHlsZTp7ZGlzcGxheToiaW5saW5lIix3aWR0aDoiMTAwJSIsaGVpZ2h0OiIxMDAlIn19LGNoaWxkcmVuOlt1XX0pO3UuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbj0iYWJzb2x1dGUiO3JldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3ModSl9fWNsYXNzIExpbmVhciBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywibGluZWFyIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbInRvUmlnaHQiLCJ0b0JvdHRvbSIsInRvTGVmdCIsInRvVG9wIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmNvbG9yPW51bGw7dGhpcy5leHRyYXM9bnVsbH1bWXNdKGUpe2U9ZT9lW1lzXSgpOiIjRkZGRkZGIjtyZXR1cm5gbGluZWFyLWdyYWRpZW50KCR7dGhpcy50eXBlLnJlcGxhY2UoLyhbUkJMVF0pLywiICQxIikudG9Mb3dlckNhc2UoKX0sICR7ZX0sICR7dGhpcy5jb2xvcj90aGlzLmNvbG9yW1lzXSgpOiIjMDAwMDAwIn0pYH19Y2xhc3MgTG9ja0RvY3VtZW50IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywibG9ja0RvY3VtZW50Iik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifVtZaV0oKXt0aGlzWyRpXT1nZXRTdHJpbmdPcHRpb24odGhpc1skaV0sWyJhdXRvIiwiMCIsIjEiXSl9fWNsYXNzIE1hbmlmZXN0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJtYW5pZmVzdCIsITApO3RoaXMuYWN0aW9uPWdldFN0cmluZ09wdGlvbihlLmFjdGlvbixbImluY2x1ZGUiLCJhbGwiLCJleGNsdWRlIl0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5yZWY9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBNYXJnaW4gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sIm1hcmdpbiIsITApO3RoaXMuYm90dG9tSW5zZXQ9Z2V0TWVhc3VyZW1lbnQoZS5ib3R0b21JbnNldCwiMCIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5sZWZ0SW5zZXQ9Z2V0TWVhc3VyZW1lbnQoZS5sZWZ0SW5zZXQsIjAiKTt0aGlzLnJpZ2h0SW5zZXQ9Z2V0TWVhc3VyZW1lbnQoZS5yaWdodEluc2V0LCIwIik7dGhpcy50b3BJbnNldD1nZXRNZWFzdXJlbWVudChlLnRvcEluc2V0LCIwIik7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGx9W1lzXSgpe3JldHVybnttYXJnaW46bWVhc3VyZVRvU3RyaW5nKHRoaXMudG9wSW5zZXQpKyIgIittZWFzdXJlVG9TdHJpbmcodGhpcy5yaWdodEluc2V0KSsiICIrbWVhc3VyZVRvU3RyaW5nKHRoaXMuYm90dG9tSW5zZXQpKyIgIittZWFzdXJlVG9TdHJpbmcodGhpcy5sZWZ0SW5zZXQpfX19Y2xhc3MgTWRwIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJtZHAiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMucGVybWlzc2lvbnM9Z2V0SW50ZWdlcih7ZGF0YTplLnBlcm1pc3Npb25zLGRlZmF1bHRWYWx1ZToyLHZhbGlkYXRlOmU9PjE9PT1lfHwzPT09ZX0pO3RoaXMuc2lnbmF0dXJlVHlwZT1nZXRTdHJpbmdPcHRpb24oZS5zaWduYXR1cmVUeXBlLFsiZmlsbGVyIiwiYXV0aG9yIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgTWVkaXVtIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJtZWRpdW0iKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMuaW1hZ2luZ0JCb3g9ZnVuY3Rpb24gZ2V0QkJveChlKXtjb25zdCB0PS0xO2lmKCFlKXJldHVybnt4OnQseTp0LHdpZHRoOnQsaGVpZ2h0OnR9O2NvbnN0IHI9ZS5zcGxpdCgiLCIsNCkubWFwKGU9PmdldE1lYXN1cmVtZW50KGUudHJpbSgpLCItMSIpKTtpZihyLmxlbmd0aDw0fHxyWzJdPDB8fHJbM108MClyZXR1cm57eDp0LHk6dCx3aWR0aDp0LGhlaWdodDp0fTtjb25zdFthLG4saSxzXT1yO3JldHVybnt4OmEseTpuLHdpZHRoOmksaGVpZ2h0OnN9fShlLmltYWdpbmdCQm94KTt0aGlzLmxvbmc9Z2V0TWVhc3VyZW1lbnQoZS5sb25nKTt0aGlzLm9yaWVudGF0aW9uPWdldFN0cmluZ09wdGlvbihlLm9yaWVudGF0aW9uLFsicG9ydHJhaXQiLCJsYW5kc2NhcGUiXSk7dGhpcy5zaG9ydD1nZXRNZWFzdXJlbWVudChlLnNob3J0KTt0aGlzLnN0b2NrPWUuc3RvY2t8fCIiO3RoaXMudHJheUluPWdldFN0cmluZ09wdGlvbihlLnRyYXlJbixbImF1dG8iLCJkZWxlZ2F0ZSIsInBhZ2VGcm9udCJdKTt0aGlzLnRyYXlPdXQ9Z2V0U3RyaW5nT3B0aW9uKGUudHJheU91dCxbImF1dG8iLCJkZWxlZ2F0ZSJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIE1lc3NhZ2UgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sIm1lc3NhZ2UiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnRleHQ9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBOdW1lcmljRWRpdCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywibnVtZXJpY0VkaXQiLCEwKTt0aGlzLmhTY3JvbGxQb2xpY3k9Z2V0U3RyaW5nT3B0aW9uKGUuaFNjcm9sbFBvbGljeSxbImF1dG8iLCJvZmYiLCJvbiJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmJvcmRlcj1udWxsO3RoaXMuY29tYj1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5tYXJnaW49bnVsbH1bS3NdKGUpe2NvbnN0IHQ9dG9TdHlsZSh0aGlzLCJib3JkZXIiLCJmb250IiwibWFyZ2luIikscj10aGlzW2RzXSgpW2RzXSgpLGE9e25hbWU6ImlucHV0IixhdHRyaWJ1dGVzOnt0eXBlOiJ0ZXh0IixmaWVsZElkOnJbWnNdLGRhdGFJZDpyW1ZpXT8uW1pzXXx8cltac10sY2xhc3M6WyJ4ZmFUZXh0ZmllbGQiXSxzdHlsZTp0LCJhcmlhLWxhYmVsIjphcmlhTGFiZWwociksImFyaWEtcmVxdWlyZWQiOiExfX07aWYoaXNSZXF1aXJlZChyKSl7YS5hdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl09ITA7YS5hdHRyaWJ1dGVzLnJlcXVpcmVkPSEwfXJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moe25hbWU6ImxhYmVsIixhdHRyaWJ1dGVzOntjbGFzczpbInhmYUxhYmVsIl19LGNoaWxkcmVuOlthXX0pfX1jbGFzcyBPY2N1ciBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywib2NjdXIiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMuaW5pdGlhbD0iIiE9PWUuaW5pdGlhbD9nZXRJbnRlZ2VyKHtkYXRhOmUuaW5pdGlhbCxkZWZhdWx0VmFsdWU6IiIsdmFsaWRhdGU6ZT0+ITB9KToiIjt0aGlzLm1heD0iIiE9PWUubWF4P2dldEludGVnZXIoe2RhdGE6ZS5tYXgsZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ITB9KToiIjt0aGlzLm1pbj0iIiE9PWUubWluP2dldEludGVnZXIoe2RhdGE6ZS5taW4sZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ITB9KToiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5leHRyYXM9bnVsbH1bWGldKCl7Y29uc3QgZT10aGlzW2RzXSgpLHQ9dGhpcy5taW47IiI9PT10aGlzLm1pbiYmKHRoaXMubWluPWUgaW5zdGFuY2VvZiBQYWdlQXJlYXx8ZSBpbnN0YW5jZW9mIFBhZ2VTZXQ/MDoxKTsiIj09PXRoaXMubWF4JiYodGhpcy5tYXg9IiI9PT10P2UgaW5zdGFuY2VvZiBQYWdlQXJlYXx8ZSBpbnN0YW5jZW9mIFBhZ2VTZXQ/LTE6MTp0aGlzLm1pbik7LTEhPT10aGlzLm1heCYmdGhpcy5tYXg8dGhpcy5taW4mJih0aGlzLm1heD10aGlzLm1pbik7IiI9PT10aGlzLmluaXRpYWwmJih0aGlzLmluaXRpYWw9ZSBpbnN0YW5jZW9mIFRlbXBsYXRlPzE6dGhpcy5taW4pfX1jbGFzcyBPaWQgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sIm9pZCIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBPaWRzIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJvaWRzIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMub2lkPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgT3ZlcmZsb3cgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sIm92ZXJmbG93Iik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmxlYWRlcj1lLmxlYWRlcnx8IiI7dGhpcy50YXJnZXQ9ZS50YXJnZXR8fCIiO3RoaXMudHJhaWxlcj1lLnRyYWlsZXJ8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn1bc3NdKCl7aWYoIXRoaXNbSmldKXtjb25zdCBlPXRoaXNbZHNdKCksdD10aGlzW2ZzXSgpLHI9dFtYc10odGhpcy50YXJnZXQsZSksYT10W1hzXSh0aGlzLmxlYWRlcixlKSxuPXRbWHNdKHRoaXMudHJhaWxlcixlKTt0aGlzW0ppXT17dGFyZ2V0OnI/LlswXXx8bnVsbCxsZWFkZXI6YT8uWzBdfHxudWxsLHRyYWlsZXI6bj8uWzBdfHxudWxsLGFkZExlYWRlcjohMSxhZGRUcmFpbGVyOiExfX1yZXR1cm4gdGhpc1tKaV19fWNsYXNzIFBhZ2VBcmVhIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwYWdlQXJlYSIsITApO3RoaXMuYmxhbmtPck5vdEJsYW5rPWdldFN0cmluZ09wdGlvbihlLmJsYW5rT3JOb3RCbGFuayxbImFueSIsImJsYW5rIiwibm90QmxhbmsiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLmluaXRpYWxOdW1iZXI9Z2V0SW50ZWdlcih7ZGF0YTplLmluaXRpYWxOdW1iZXIsZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ITB9KTt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLm51bWJlcmVkPWdldEludGVnZXIoe2RhdGE6ZS5udW1iZXJlZCxkZWZhdWx0VmFsdWU6MSx2YWxpZGF0ZTplPT4hMH0pO3RoaXMub2RkT3JFdmVuPWdldFN0cmluZ09wdGlvbihlLm9kZE9yRXZlbixbImFueSIsImV2ZW4iLCJvZGQiXSk7dGhpcy5wYWdlUG9zaXRpb249Z2V0U3RyaW5nT3B0aW9uKGUucGFnZVBvc2l0aW9uLFsiYW55IiwiZmlyc3QiLCJsYXN0Iiwib25seSIsInJlc3QiXSk7dGhpcy5yZWxldmFudD1nZXRSZWxldmFudChlLnJlbGV2YW50KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5kZXNjPW51bGw7dGhpcy5leHRyYXM9bnVsbDt0aGlzLm1lZGl1bT1udWxsO3RoaXMub2NjdXI9bnVsbDt0aGlzLmFyZWE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY29udGVudEFyZWE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZHJhdz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leGNsR3JvdXA9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmllbGQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViZm9ybT1uZXcgWEZBT2JqZWN0QXJyYXl9W0lzXSgpe2lmKCF0aGlzW0ppXSl7dGhpc1tKaV09e251bWJlck9mVXNlOjB9O3JldHVybiEwfXJldHVybiF0aGlzLm9jY3VyfHwtMT09PXRoaXMub2NjdXIubWF4fHx0aGlzW0ppXS5udW1iZXJPZlVzZTx0aGlzLm9jY3VyLm1heH1bSGldKCl7ZGVsZXRlIHRoaXNbSmldfVtoc10oKXt0aGlzW0ppXXx8PXtudW1iZXJPZlVzZTowfTtjb25zdCBlPXRoaXNbZHNdKCk7aWYoIm9yZGVyZWRPY2N1cnJlbmNlIj09PWUucmVsYXRpb24mJnRoaXNbSXNdKCkpe3RoaXNbSmldLm51bWJlck9mVXNlKz0xO3JldHVybiB0aGlzfXJldHVybiBlW2hzXSgpfVt0c10oKXtyZXR1cm4gdGhpc1tKaV0uc3BhY2V8fHt3aWR0aDowLGhlaWdodDowfX1bS3NdKCl7dGhpc1tKaV18fD17bnVtYmVyT2ZVc2U6MX07Y29uc3QgZT1bXTt0aGlzW0ppXS5jaGlsZHJlbj1lO2NvbnN0IHQ9T2JqZWN0LmNyZWF0ZShudWxsKTtpZih0aGlzLm1lZGl1bSYmdGhpcy5tZWRpdW0uc2hvcnQmJnRoaXMubWVkaXVtLmxvbmcpe3Qud2lkdGg9bWVhc3VyZVRvU3RyaW5nKHRoaXMubWVkaXVtLnNob3J0KTt0LmhlaWdodD1tZWFzdXJlVG9TdHJpbmcodGhpcy5tZWRpdW0ubG9uZyk7dGhpc1tKaV0uc3BhY2U9e3dpZHRoOnRoaXMubWVkaXVtLnNob3J0LGhlaWdodDp0aGlzLm1lZGl1bS5sb25nfTtpZigibGFuZHNjYXBlIj09PXRoaXMubWVkaXVtLm9yaWVudGF0aW9uKXtjb25zdCBlPXQud2lkdGg7dC53aWR0aD10LmhlaWdodDt0LmhlaWdodD1lO3RoaXNbSmldLnNwYWNlPXt3aWR0aDp0aGlzLm1lZGl1bS5sb25nLGhlaWdodDp0aGlzLm1lZGl1bS5zaG9ydH19fWVsc2Ugd2FybigiWEZBIC0gTm8gbWVkaXVtIHNwZWNpZmllZCBpbiBwYWdlQXJlYTogcGxlYXNlIGZpbGUgYSBidWcuIik7dGhpc1txaV0oe2ZpbHRlcjpuZXcgU2V0KFsiYXJlYSIsImRyYXciLCJmaWVsZCIsInN1YmZvcm0iXSksaW5jbHVkZTohMH0pO3RoaXNbcWldKHtmaWx0ZXI6bmV3IFNldChbImNvbnRlbnRBcmVhIl0pLGluY2x1ZGU6ITB9KTtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGNoaWxkcmVuOmUsYXR0cmlidXRlczp7Y2xhc3M6WyJ4ZmFQYWdlIl0saWQ6dGhpc1tac10sc3R5bGU6dCx4ZmFOYW1lOnRoaXMubmFtZX19KX19Y2xhc3MgUGFnZVNldCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywicGFnZVNldCIsITApO3RoaXMuZHVwbGV4SW1wb3NpdGlvbj1nZXRTdHJpbmdPcHRpb24oZS5kdXBsZXhJbXBvc2l0aW9uLFsibG9uZ0VkZ2UiLCJzaG9ydEVkZ2UiXSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnJlbGF0aW9uPWdldFN0cmluZ09wdGlvbihlLnJlbGF0aW9uLFsib3JkZXJlZE9jY3VycmVuY2UiLCJkdXBsZXhQYWdpbmF0ZWQiLCJzaW1wbGV4UGFnaW5hdGVkIl0pO3RoaXMucmVsZXZhbnQ9Z2V0UmVsZXZhbnQoZS5yZWxldmFudCk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5vY2N1cj1udWxsO3RoaXMucGFnZUFyZWE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucGFnZVNldD1uZXcgWEZBT2JqZWN0QXJyYXl9W0hpXSgpe2Zvcihjb25zdCBlIG9mIHRoaXMucGFnZUFyZWEuY2hpbGRyZW4pZVtIaV0oKTtmb3IoY29uc3QgZSBvZiB0aGlzLnBhZ2VTZXQuY2hpbGRyZW4pZVtIaV0oKX1bSXNdKCl7cmV0dXJuIXRoaXMub2NjdXJ8fC0xPT09dGhpcy5vY2N1ci5tYXh8fHRoaXNbSmldLm51bWJlck9mVXNlPHRoaXMub2NjdXIubWF4fVtoc10oKXt0aGlzW0ppXXx8PXtudW1iZXJPZlVzZToxLHBhZ2VJbmRleDotMSxwYWdlU2V0SW5kZXg6LTF9O2lmKCJvcmRlcmVkT2NjdXJyZW5jZSI9PT10aGlzLnJlbGF0aW9uKXtpZih0aGlzW0ppXS5wYWdlSW5kZXgrMTx0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmxlbmd0aCl7dGhpc1tKaV0ucGFnZUluZGV4Kz0xO3JldHVybiB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuW3RoaXNbSmldLnBhZ2VJbmRleF1baHNdKCl9aWYodGhpc1tKaV0ucGFnZVNldEluZGV4KzE8dGhpcy5wYWdlU2V0LmNoaWxkcmVuLmxlbmd0aCl7dGhpc1tKaV0ucGFnZVNldEluZGV4Kz0xO3JldHVybiB0aGlzLnBhZ2VTZXQuY2hpbGRyZW5bdGhpc1tKaV0ucGFnZVNldEluZGV4XVtoc10oKX1pZih0aGlzW0lzXSgpKXt0aGlzW0ppXS5udW1iZXJPZlVzZSs9MTt0aGlzW0ppXS5wYWdlSW5kZXg9LTE7dGhpc1tKaV0ucGFnZVNldEluZGV4PS0xO3JldHVybiB0aGlzW2hzXSgpfWNvbnN0IGU9dGhpc1tkc10oKTtpZihlIGluc3RhbmNlb2YgUGFnZVNldClyZXR1cm4gZVtoc10oKTt0aGlzW0hpXSgpO3JldHVybiB0aGlzW2hzXSgpfWNvbnN0IGU9dGhpc1tmc10oKVtKaV0ucGFnZU51bWJlcix0PWUlMj09MD8iZXZlbiI6Im9kZCIscj0wPT09ZT8iZmlyc3QiOiJyZXN0IjtsZXQgYT10aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQoZT0+ZS5vZGRPckV2ZW49PT10JiZlLnBhZ2VQb3NpdGlvbj09PXIpO2lmKGEpcmV0dXJuIGE7YT10aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQoZT0+ImFueSI9PT1lLm9kZE9yRXZlbiYmZS5wYWdlUG9zaXRpb249PT1yKTtpZihhKXJldHVybiBhO2E9dGhpcy5wYWdlQXJlYS5jaGlsZHJlbi5maW5kKGU9PiJhbnkiPT09ZS5vZGRPckV2ZW4mJiJhbnkiPT09ZS5wYWdlUG9zaXRpb24pO3JldHVybiBhfHx0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuWzBdfX1jbGFzcyBQYXJhIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwYXJhIiwhMCk7dGhpcy5oQWxpZ249Z2V0U3RyaW5nT3B0aW9uKGUuaEFsaWduLFsibGVmdCIsImNlbnRlciIsImp1c3RpZnkiLCJqdXN0aWZ5QWxsIiwicmFkaXgiLCJyaWdodCJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubGluZUhlaWdodD1lLmxpbmVIZWlnaHQ/Z2V0TWVhc3VyZW1lbnQoZS5saW5lSGVpZ2h0LCIwcHQiKToiIjt0aGlzLm1hcmdpbkxlZnQ9ZS5tYXJnaW5MZWZ0P2dldE1lYXN1cmVtZW50KGUubWFyZ2luTGVmdCwiMHB0Iik6IiI7dGhpcy5tYXJnaW5SaWdodD1lLm1hcmdpblJpZ2h0P2dldE1lYXN1cmVtZW50KGUubWFyZ2luUmlnaHQsIjBwdCIpOiIiO3RoaXMub3JwaGFucz1nZXRJbnRlZ2VyKHtkYXRhOmUub3JwaGFucyxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT5lPj0wfSk7dGhpcy5wcmVzZXJ2ZT1lLnByZXNlcnZlfHwiIjt0aGlzLnJhZGl4T2Zmc2V0PWUucmFkaXhPZmZzZXQ/Z2V0TWVhc3VyZW1lbnQoZS5yYWRpeE9mZnNldCwiMHB0Iik6IiI7dGhpcy5zcGFjZUFib3ZlPWUuc3BhY2VBYm92ZT9nZXRNZWFzdXJlbWVudChlLnNwYWNlQWJvdmUsIjBwdCIpOiIiO3RoaXMuc3BhY2VCZWxvdz1lLnNwYWNlQmVsb3c/Z2V0TWVhc3VyZW1lbnQoZS5zcGFjZUJlbG93LCIwcHQiKToiIjt0aGlzLnRhYkRlZmF1bHQ9ZS50YWJEZWZhdWx0P2dldE1lYXN1cmVtZW50KHRoaXMudGFiRGVmYXVsdCk6IiI7dGhpcy50YWJTdG9wcz0oZS50YWJTdG9wc3x8IiIpLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKChlLHQpPT50JTI9PTE/Z2V0TWVhc3VyZW1lbnQoZSk6ZSk7dGhpcy50ZXh0SW5kZW50PWUudGV4dEluZGVudD9nZXRNZWFzdXJlbWVudChlLnRleHRJbmRlbnQsIjBwdCIpOiIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnZBbGlnbj1nZXRTdHJpbmdPcHRpb24oZS52QWxpZ24sWyJ0b3AiLCJib3R0b20iLCJtaWRkbGUiXSk7dGhpcy53aWRvd3M9Z2V0SW50ZWdlcih7ZGF0YTplLndpZG93cyxkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT5lPj0wfSk7dGhpcy5oeXBoZW5hdGlvbj1udWxsfVtZc10oKXtjb25zdCBlPXRvU3R5bGUodGhpcywiaEFsaWduIik7IiIhPT10aGlzLm1hcmdpbkxlZnQmJihlLnBhZGRpbmdMZWZ0PW1lYXN1cmVUb1N0cmluZyh0aGlzLm1hcmdpbkxlZnQpKTsiIiE9PXRoaXMubWFyZ2luUmlnaHQmJihlLnBhZGRpbmdSaWdodD1tZWFzdXJlVG9TdHJpbmcodGhpcy5tYXJnaW5SaWdodCkpOyIiIT09dGhpcy5zcGFjZUFib3ZlJiYoZS5wYWRkaW5nVG9wPW1lYXN1cmVUb1N0cmluZyh0aGlzLnNwYWNlQWJvdmUpKTsiIiE9PXRoaXMuc3BhY2VCZWxvdyYmKGUucGFkZGluZ0JvdHRvbT1tZWFzdXJlVG9TdHJpbmcodGhpcy5zcGFjZUJlbG93KSk7aWYoIiIhPT10aGlzLnRleHRJbmRlbnQpe2UudGV4dEluZGVudD1tZWFzdXJlVG9TdHJpbmcodGhpcy50ZXh0SW5kZW50KTtmaXhUZXh0SW5kZW50KGUpfXRoaXMubGluZUhlaWdodD4wJiYoZS5saW5lSGVpZ2h0PW1lYXN1cmVUb1N0cmluZyh0aGlzLmxpbmVIZWlnaHQpKTsiIiE9PXRoaXMudGFiRGVmYXVsdCYmKGUudGFiU2l6ZT1tZWFzdXJlVG9TdHJpbmcodGhpcy50YWJEZWZhdWx0KSk7dGhpcy50YWJTdG9wcy5sZW5ndGg7dGhpcy5oeXBoZW5hdGF0aW9uJiZPYmplY3QuYXNzaWduKGUsdGhpcy5oeXBoZW5hdGF0aW9uW1lzXSgpKTtyZXR1cm4gZX19Y2xhc3MgUGFzc3dvcmRFZGl0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwYXNzd29yZEVkaXQiLCEwKTt0aGlzLmhTY3JvbGxQb2xpY3k9Z2V0U3RyaW5nT3B0aW9uKGUuaFNjcm9sbFBvbGljeSxbImF1dG8iLCJvZmYiLCJvbiJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMucGFzc3dvcmRDaGFyPWUucGFzc3dvcmRDaGFyfHwiKiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuYm9yZGVyPW51bGw7dGhpcy5leHRyYXM9bnVsbDt0aGlzLm1hcmdpbj1udWxsfX1jbGFzcyB0ZW1wbGF0ZV9QYXR0ZXJuIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwYXR0ZXJuIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbImNyb3NzSGF0Y2giLCJjcm9zc0RpYWdvbmFsIiwiZGlhZ29uYWxMZWZ0IiwiZGlhZ29uYWxSaWdodCIsImhvcml6b250YWwiLCJ2ZXJ0aWNhbCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jb2xvcj1udWxsO3RoaXMuZXh0cmFzPW51bGx9W1lzXShlKXtlPWU/ZVtZc10oKToiI0ZGRkZGRiI7Y29uc3QgdD10aGlzLmNvbG9yP3RoaXMuY29sb3JbWXNdKCk6IiMwMDAwMDAiLHI9InJlcGVhdGluZy1saW5lYXItZ3JhZGllbnQiLGE9YCR7ZX0sJHtlfSA1cHgsJHt0fSA1cHgsJHt0fSAxMHB4YDtzd2l0Y2godGhpcy50eXBlKXtjYXNlImNyb3NzSGF0Y2giOnJldHVybmAke3J9KHRvIHRvcCwke2F9KSAke3J9KHRvIHJpZ2h0LCR7YX0pYDtjYXNlImNyb3NzRGlhZ29uYWwiOnJldHVybmAke3J9KDQ1ZGVnLCR7YX0pICR7cn0oLTQ1ZGVnLCR7YX0pYDtjYXNlImRpYWdvbmFsTGVmdCI6cmV0dXJuYCR7cn0oNDVkZWcsJHthfSlgO2Nhc2UiZGlhZ29uYWxSaWdodCI6cmV0dXJuYCR7cn0oLTQ1ZGVnLCR7YX0pYDtjYXNlImhvcml6b250YWwiOnJldHVybmAke3J9KHRvIHRvcCwke2F9KWA7Y2FzZSJ2ZXJ0aWNhbCI6cmV0dXJuYCR7cn0odG8gcmlnaHQsJHthfSlgfXJldHVybiIifX1jbGFzcyBQaWN0dXJlIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwaWN0dXJlIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIFByb3RvIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJwcm90byIsITApO3RoaXMuYXBwZWFyYW5jZUZpbHRlcj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5hcmM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuYXJlYT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5hc3Npc3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuYmFyY29kZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5iaW5kSXRlbXM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuYm9va2VuZD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5ib29sZWFuPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmJvcmRlcj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5icmVhaz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5icmVha0FmdGVyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmJyZWFrQmVmb3JlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmJ1dHRvbj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jYWxjdWxhdGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY2FwdGlvbj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jZXJ0aWZpY2F0ZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jZXJ0aWZpY2F0ZXM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY2hlY2tCdXR0b249bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY2hvaWNlTGlzdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jb2xvcj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5jb21iPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmNvbm5lY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY29udGVudEFyZWE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuY29ybmVyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRhdGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZVRpbWU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZVRpbWVFZGl0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRlY2ltYWw9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGVmYXVsdFVpPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRlc2M9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGlnZXN0TWV0aG9kPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRpZ2VzdE1ldGhvZHM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZHJhdz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5lZGdlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmVuY29kaW5nPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmVuY29kaW5ncz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5lbmNyeXB0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmVuY3J5cHREYXRhPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmVuY3J5cHRpb249bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZW5jcnlwdGlvbk1ldGhvZD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5lbmNyeXB0aW9uTWV0aG9kcz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5ldmVudD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leERhdGE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhPYmplY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXhjbEdyb3VwPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmV4ZWN1dGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZXh0cmFzPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmZpZWxkPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmZpbGw9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmlsdGVyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmZsb2F0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmZvbnQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZm9ybWF0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmhhbmRsZXI9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaHlwaGVuYXRpb249bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW1hZ2U9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW1hZ2VFZGl0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmludGVnZXI9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaXNzdWVycz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5pdGVtcz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5rZWVwPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmtleVVzYWdlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmxpbmU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMubGluZWFyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmxvY2tEb2N1bWVudD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5tYW5pZmVzdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5tYXJnaW49bmV3IFhGQU9iamVjdEFycmF5O3RoaXMubWRwPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLm1lZGl1bT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5tZXNzYWdlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLm51bWVyaWNFZGl0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLm9jY3VyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLm9pZD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5vaWRzPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLm92ZXJmbG93PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnBhZ2VBcmVhPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnBhZ2VTZXQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucGFyYT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5wYXNzd29yZEVkaXQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucGF0dGVybj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5waWN0dXJlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnJhZGlhbD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5yZWFzb249bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucmVhc29ucz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5yZWN0YW5nbGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucmVmPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnNjcmlwdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zZXRQcm9wZXJ0eT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zaWduRGF0YT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zaWduYXR1cmU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc2lnbmluZz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zb2xpZD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zcGVhaz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zdGlwcGxlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnN1YmZvcm09bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViZm9ybVNldD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zdWJqZWN0RE49bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViamVjdEROcz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zdWJtaXQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudGV4dD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50ZXh0RWRpdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50aW1lPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRpbWVTdGFtcD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50b29sVGlwPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRyYXZlcnNhbD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50cmF2ZXJzZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy51aT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy52YWxpZGF0ZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy52YWx1ZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy52YXJpYWJsZXM9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBSYWRpYWwgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInJhZGlhbCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy50eXBlPWdldFN0cmluZ09wdGlvbihlLnR5cGUsWyJ0b0VkZ2UiLCJ0b0NlbnRlciJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jb2xvcj1udWxsO3RoaXMuZXh0cmFzPW51bGx9W1lzXShlKXtlPWU/ZVtZc10oKToiI0ZGRkZGRiI7Y29uc3QgdD10aGlzLmNvbG9yP3RoaXMuY29sb3JbWXNdKCk6IiMwMDAwMDAiO3JldHVybmByYWRpYWwtZ3JhZGllbnQoY2lyY2xlIGF0IGNlbnRlciwgJHsidG9FZGdlIj09PXRoaXMudHlwZT9gJHtlfSwke3R9YDpgJHt0fSwke2V9YH0pYH19Y2xhc3MgUmVhc29uIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJyZWFzb24iKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgUmVhc29ucyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywicmVhc29ucyIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy50eXBlPWdldFN0cmluZ09wdGlvbihlLnR5cGUsWyJvcHRpb25hbCIsInJlcXVpcmVkIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnJlYXNvbj1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIFJlY3RhbmdsZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywicmVjdGFuZ2xlIiwhMCk7dGhpcy5oYW5kPWdldFN0cmluZ09wdGlvbihlLmhhbmQsWyJldmVuIiwibGVmdCIsInJpZ2h0Il0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuY29ybmVyPW5ldyBYRkFPYmplY3RBcnJheSg0KTt0aGlzLmVkZ2U9bmV3IFhGQU9iamVjdEFycmF5KDQpO3RoaXMuZmlsbD1udWxsfVtLc10oKXtjb25zdCBlPXRoaXMuZWRnZS5jaGlsZHJlbi5sZW5ndGg/dGhpcy5lZGdlLmNoaWxkcmVuWzBdOm5ldyBFZGdlKHt9KSx0PWVbWXNdKCkscj1PYmplY3QuY3JlYXRlKG51bGwpOyJ2aXNpYmxlIj09PXRoaXMuZmlsbD8ucHJlc2VuY2U/T2JqZWN0LmFzc2lnbihyLHRoaXMuZmlsbFtZc10oKSk6ci5maWxsPSJ0cmFuc3BhcmVudCI7ci5zdHJva2VXaWR0aD1tZWFzdXJlVG9TdHJpbmcoInZpc2libGUiPT09ZS5wcmVzZW5jZT9lLnRoaWNrbmVzczowKTtyLnN0cm9rZT10LmNvbG9yO2NvbnN0IGE9KHRoaXMuY29ybmVyLmNoaWxkcmVuLmxlbmd0aD90aGlzLmNvcm5lci5jaGlsZHJlblswXTpuZXcgQ29ybmVyKHt9KSlbWXNdKCksbj17bmFtZToic3ZnIixjaGlsZHJlbjpbe25hbWU6InJlY3QiLGF0dHJpYnV0ZXM6e3htbG5zOk5vLHdpZHRoOiIxMDAlIixoZWlnaHQ6IjEwMCUiLHg6MCx5OjAscng6YS5yYWRpdXMscnk6YS5yYWRpdXMsc3R5bGU6cn19XSxhdHRyaWJ1dGVzOnt4bWxuczpObyxzdHlsZTp7b3ZlcmZsb3c6InZpc2libGUifSx3aWR0aDoiMTAwJSIsaGVpZ2h0OiIxMDAlIn19O2lmKGhhc01hcmdpbih0aGlzW2RzXSgpW2RzXSgpKSlyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e3N0eWxlOntkaXNwbGF5OiJpbmxpbmUiLHdpZHRoOiIxMDAlIixoZWlnaHQ6IjEwMCUifX0sY2hpbGRyZW46W25dfSk7bi5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uPSJhYnNvbHV0ZSI7cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhuKX19Y2xhc3MgUmVmRWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywicmVmIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIFNjcmlwdCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywic2NyaXB0Iik7dGhpcy5iaW5kaW5nPWUuYmluZGluZ3x8IiI7dGhpcy5jb250ZW50VHlwZT1lLmNvbnRlbnRUeXBlfHwiIjt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucnVuQXQ9Z2V0U3RyaW5nT3B0aW9uKGUucnVuQXQsWyJjbGllbnQiLCJib3RoIiwic2VydmVyIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgU2V0UHJvcGVydHkgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInNldFByb3BlcnR5Iik7dGhpcy5jb25uZWN0aW9uPWUuY29ubmVjdGlvbnx8IiI7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIn19Y2xhc3MgU2lnbkRhdGEgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInNpZ25EYXRhIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm9wZXJhdGlvbj1nZXRTdHJpbmdPcHRpb24oZS5vcGVyYXRpb24sWyJzaWduIiwiY2xlYXIiLCJ2ZXJpZnkiXSk7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5maWx0ZXI9bnVsbDt0aGlzLm1hbmlmZXN0PW51bGx9fWNsYXNzIFNpZ25hdHVyZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywic2lnbmF0dXJlIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIlBERjEuMyIsIlBERjEuNiJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5ib3JkZXI9bnVsbDt0aGlzLmV4dHJhcz1udWxsO3RoaXMuZmlsdGVyPW51bGw7dGhpcy5tYW5pZmVzdD1udWxsO3RoaXMubWFyZ2luPW51bGx9fWNsYXNzIFNpZ25pbmcgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInNpZ25pbmciLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudHlwZT1nZXRTdHJpbmdPcHRpb24oZS50eXBlLFsib3B0aW9uYWwiLCJyZXF1aXJlZCJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5jZXJ0aWZpY2F0ZT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIFNvbGlkIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJzb2xpZCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuZXh0cmFzPW51bGx9W1lzXShlKXtyZXR1cm4gZT9lW1lzXSgpOiIjRkZGRkZGIn19Y2xhc3MgU3BlYWsgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInNwZWFrIik7dGhpcy5kaXNhYmxlPWdldEludGVnZXIoe2RhdGE6ZS5kaXNhYmxlLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PjE9PT1lfSk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnByaW9yaXR5PWdldFN0cmluZ09wdGlvbihlLnByaW9yaXR5LFsiY3VzdG9tIiwiY2FwdGlvbiIsIm5hbWUiLCJ0b29sVGlwIl0pO3RoaXMucmlkPWUucmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIFN0aXBwbGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInN0aXBwbGUiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMucmF0ZT1nZXRJbnRlZ2VyKHtkYXRhOmUucmF0ZSxkZWZhdWx0VmFsdWU6NTAsdmFsaWRhdGU6ZT0+ZT49MCYmZTw9MTAwfSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuY29sb3I9bnVsbDt0aGlzLmV4dHJhcz1udWxsfVtZc10oZSl7Y29uc3QgdD10aGlzLnJhdGUvMTAwO3JldHVybiBVdGlsLm1ha2VIZXhDb2xvcihNYXRoLnJvdW5kKGUudmFsdWUuciooMS10KSt0aGlzLnZhbHVlLnIqdCksTWF0aC5yb3VuZChlLnZhbHVlLmcqKDEtdCkrdGhpcy52YWx1ZS5nKnQpLE1hdGgucm91bmQoZS52YWx1ZS5iKigxLXQpK3RoaXMudmFsdWUuYip0KSl9fWNsYXNzIFN1YmZvcm0gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInN1YmZvcm0iLCEwKTt0aGlzLmFjY2Vzcz1nZXRTdHJpbmdPcHRpb24oZS5hY2Nlc3MsWyJvcGVuIiwibm9uSW50ZXJhY3RpdmUiLCJwcm90ZWN0ZWQiLCJyZWFkT25seSJdKTt0aGlzLmFsbG93TWFjcm89Z2V0SW50ZWdlcih7ZGF0YTplLmFsbG93TWFjcm8sZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLmFuY2hvclR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUuYW5jaG9yVHlwZSxbInRvcExlZnQiLCJib3R0b21DZW50ZXIiLCJib3R0b21MZWZ0IiwiYm90dG9tUmlnaHQiLCJtaWRkbGVDZW50ZXIiLCJtaWRkbGVMZWZ0IiwibWlkZGxlUmlnaHQiLCJ0b3BDZW50ZXIiLCJ0b3BSaWdodCJdKTt0aGlzLmNvbFNwYW49Z2V0SW50ZWdlcih7ZGF0YTplLmNvbFNwYW4sZGVmYXVsdFZhbHVlOjEsdmFsaWRhdGU6ZT0+ZT49MXx8LTE9PT1lfSk7dGhpcy5jb2x1bW5XaWR0aHM9KGUuY29sdW1uV2lkdGhzfHwiIikudHJpbSgpLnNwbGl0KC9ccysvKS5tYXAoZT0+Ii0xIj09PWU/LTE6Z2V0TWVhc3VyZW1lbnQoZSkpO3RoaXMuaD1lLmg/Z2V0TWVhc3VyZW1lbnQoZS5oKToiIjt0aGlzLmhBbGlnbj1nZXRTdHJpbmdPcHRpb24oZS5oQWxpZ24sWyJsZWZ0IiwiY2VudGVyIiwianVzdGlmeSIsImp1c3RpZnlBbGwiLCJyYWRpeCIsInJpZ2h0Il0pO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5sYXlvdXQ9Z2V0U3RyaW5nT3B0aW9uKGUubGF5b3V0LFsicG9zaXRpb24iLCJsci10YiIsInJsLXJvdyIsInJsLXRiIiwicm93IiwidGFibGUiLCJ0YiJdKTt0aGlzLmxvY2FsZT1lLmxvY2FsZXx8IiI7dGhpcy5tYXhIPWdldE1lYXN1cmVtZW50KGUubWF4SCwiMHB0Iik7dGhpcy5tYXhXPWdldE1lYXN1cmVtZW50KGUubWF4VywiMHB0Iik7dGhpcy5tZXJnZU1vZGU9Z2V0U3RyaW5nT3B0aW9uKGUubWVyZ2VNb2RlLFsiY29uc3VtZURhdGEiLCJtYXRjaFRlbXBsYXRlIl0pO3RoaXMubWluSD1nZXRNZWFzdXJlbWVudChlLm1pbkgsIjBwdCIpO3RoaXMubWluVz1nZXRNZWFzdXJlbWVudChlLm1pblcsIjBwdCIpO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucHJlc2VuY2U9Z2V0U3RyaW5nT3B0aW9uKGUucHJlc2VuY2UsWyJ2aXNpYmxlIiwiaGlkZGVuIiwiaW5hY3RpdmUiLCJpbnZpc2libGUiXSk7dGhpcy5yZWxldmFudD1nZXRSZWxldmFudChlLnJlbGV2YW50KTt0aGlzLnJlc3RvcmVTdGF0ZT1nZXRTdHJpbmdPcHRpb24oZS5yZXN0b3JlU3RhdGUsWyJtYW51YWwiLCJhdXRvIl0pO3RoaXMuc2NvcGU9Z2V0U3RyaW5nT3B0aW9uKGUuc2NvcGUsWyJuYW1lIiwibm9uZSJdKTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy53PWUudz9nZXRNZWFzdXJlbWVudChlLncpOiIiO3RoaXMueD1nZXRNZWFzdXJlbWVudChlLngsIjBwdCIpO3RoaXMueT1nZXRNZWFzdXJlbWVudChlLnksIjBwdCIpO3RoaXMuYXNzaXN0PW51bGw7dGhpcy5iaW5kPW51bGw7dGhpcy5ib29rZW5kPW51bGw7dGhpcy5ib3JkZXI9bnVsbDt0aGlzLmJyZWFrPW51bGw7dGhpcy5jYWxjdWxhdGU9bnVsbDt0aGlzLmRlc2M9bnVsbDt0aGlzLmV4dHJhcz1udWxsO3RoaXMua2VlcD1udWxsO3RoaXMubWFyZ2luPW51bGw7dGhpcy5vY2N1cj1udWxsO3RoaXMub3ZlcmZsb3c9bnVsbDt0aGlzLnBhZ2VTZXQ9bnVsbDt0aGlzLnBhcmE9bnVsbDt0aGlzLnRyYXZlcnNhbD1udWxsO3RoaXMudmFsaWRhdGU9bnVsbDt0aGlzLnZhcmlhYmxlcz1udWxsO3RoaXMuYXJlYT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5icmVha0FmdGVyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmJyZWFrQmVmb3JlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmNvbm5lY3Q9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZHJhdz1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5ldmVudD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leE9iamVjdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leGNsR3JvdXA9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmllbGQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucHJvdG89bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc2V0UHJvcGVydHk9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViZm9ybT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zdWJmb3JtU2V0PW5ldyBYRkFPYmplY3RBcnJheX1bdXNdKCl7Y29uc3QgZT10aGlzW2RzXSgpO3JldHVybiBlIGluc3RhbmNlb2YgU3ViZm9ybVNldD9lW3VzXSgpOmV9W3hzXSgpe3JldHVybiEwfVt2c10oKXtyZXR1cm4gdGhpcy5sYXlvdXQuZW5kc1dpdGgoIi10YiIpJiYwPT09dGhpc1tKaV0uYXR0ZW1wdCYmdGhpc1tKaV0ubnVtYmVySW5MaW5lPjB8fHRoaXNbZHNdKClbdnNdKCl9Kltsc10oKXt5aWVsZCpnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKX1bWmldKCl7cmV0dXJuIGZsdXNoSFRNTCh0aGlzKX1bX2ldKGUsdCl7YWRkSFRNTCh0aGlzLGUsdCl9W3RzXSgpe3JldHVybiBnZXRBdmFpbGFibGVTcGFjZSh0aGlzKX1bQ3NdKCl7Y29uc3QgZT10aGlzW3VzXSgpO2lmKCFlW0NzXSgpKXJldHVybiExO2lmKHZvaWQgMCE9PXRoaXNbSmldLl9pc1NwbGl0dGFibGUpcmV0dXJuIHRoaXNbSmldLl9pc1NwbGl0dGFibGU7aWYoInBvc2l0aW9uIj09PXRoaXMubGF5b3V0fHx0aGlzLmxheW91dC5pbmNsdWRlcygicm93Iikpe3RoaXNbSmldLl9pc1NwbGl0dGFibGU9ITE7cmV0dXJuITF9aWYodGhpcy5rZWVwJiYibm9uZSIhPT10aGlzLmtlZXAuaW50YWN0KXt0aGlzW0ppXS5faXNTcGxpdHRhYmxlPSExO3JldHVybiExfWlmKGUubGF5b3V0Py5lbmRzV2l0aCgiLXRiIikmJjAhPT1lW0ppXS5udW1iZXJJbkxpbmUpcmV0dXJuITE7dGhpc1tKaV0uX2lzU3BsaXR0YWJsZT0hMDtyZXR1cm4hMH1bS3NdKGUpe3NldFRhYkluZGV4KHRoaXMpO2lmKHRoaXMuYnJlYWspe2lmKCJhdXRvIiE9PXRoaXMuYnJlYWsuYWZ0ZXJ8fCIiIT09dGhpcy5icmVhay5hZnRlclRhcmdldCl7Y29uc3QgZT1uZXcgQnJlYWtBZnRlcih7dGFyZ2V0VHlwZTp0aGlzLmJyZWFrLmFmdGVyLHRhcmdldDp0aGlzLmJyZWFrLmFmdGVyVGFyZ2V0LHN0YXJ0TmV3OnRoaXMuYnJlYWsuc3RhcnROZXcudG9TdHJpbmcoKX0pO2VbZ3NdPXRoaXNbZ3NdO3RoaXNbamldKGUpO3RoaXMuYnJlYWtBZnRlci5wdXNoKGUpfWlmKCJhdXRvIiE9PXRoaXMuYnJlYWsuYmVmb3JlfHwiIiE9PXRoaXMuYnJlYWsuYmVmb3JlVGFyZ2V0KXtjb25zdCBlPW5ldyBCcmVha0JlZm9yZSh7dGFyZ2V0VHlwZTp0aGlzLmJyZWFrLmJlZm9yZSx0YXJnZXQ6dGhpcy5icmVhay5iZWZvcmVUYXJnZXQsc3RhcnROZXc6dGhpcy5icmVhay5zdGFydE5ldy50b1N0cmluZygpfSk7ZVtnc109dGhpc1tnc107dGhpc1tqaV0oZSk7dGhpcy5icmVha0JlZm9yZS5wdXNoKGUpfWlmKCIiIT09dGhpcy5icmVhay5vdmVyZmxvd1RhcmdldCl7Y29uc3QgZT1uZXcgT3ZlcmZsb3coe3RhcmdldDp0aGlzLmJyZWFrLm92ZXJmbG93VGFyZ2V0LGxlYWRlcjp0aGlzLmJyZWFrLm92ZXJmbG93TGVhZGVyLHRyYWlsZXI6dGhpcy5icmVhay5vdmVyZmxvd1RyYWlsZXJ9KTtlW2dzXT10aGlzW2dzXTt0aGlzW2ppXShlKTt0aGlzLm92ZXJmbG93LnB1c2goZSl9dGhpc1tqc10odGhpcy5icmVhayk7dGhpcy5icmVhaz1udWxsfWlmKCJoaWRkZW4iPT09dGhpcy5wcmVzZW5jZXx8ImluYWN0aXZlIj09PXRoaXMucHJlc2VuY2UpcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7KHRoaXMuYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoPjF8fHRoaXMuYnJlYWtBZnRlci5jaGlsZHJlbi5sZW5ndGg+MSkmJndhcm4oIlhGQSAtIFNldmVyYWwgYnJlYWtCZWZvcmUgb3IgYnJlYWtBZnRlciBpbiBzdWJmb3JtczogcGxlYXNlIGZpbGUgYSBidWcuIik7aWYodGhpcy5icmVha0JlZm9yZS5jaGlsZHJlbi5sZW5ndGg+PTEpe2NvbnN0IGU9dGhpcy5icmVha0JlZm9yZS5jaGlsZHJlblswXTtpZihoYW5kbGVCcmVhayhlKSlyZXR1cm4gSFRNTFJlc3VsdC5icmVha05vZGUoZSl9aWYodGhpc1tKaV0/LmFmdGVyQnJlYWtBZnRlcilyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTtmaXhEaW1lbnNpb25zKHRoaXMpO2NvbnN0IHQ9W10scj17aWQ6dGhpc1tac10sY2xhc3M6W119O3NldEFjY2Vzcyh0aGlzLHIuY2xhc3MpO3RoaXNbSmldfHw9T2JqZWN0LmNyZWF0ZShudWxsKTtPYmplY3QuYXNzaWduKHRoaXNbSmldLHtjaGlsZHJlbjp0LGxpbmU6bnVsbCxhdHRyaWJ1dGVzOnIsYXR0ZW1wdDowLG51bWJlckluTGluZTowLGF2YWlsYWJsZVNwYWNlOnt3aWR0aDpNYXRoLm1pbih0aGlzLnd8fDEvMCxlLndpZHRoKSxoZWlnaHQ6TWF0aC5taW4odGhpcy5ofHwxLzAsZS5oZWlnaHQpfSx3aWR0aDowLGhlaWdodDowLHByZXZIZWlnaHQ6MCxjdXJyZW50V2lkdGg6MH0pO2NvbnN0IGE9dGhpc1tmc10oKSxuPWFbSmldLm5vTGF5b3V0RmFpbHVyZSxpPXRoaXNbQ3NdKCk7aXx8c2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7aWYoIWNoZWNrRGltZW5zaW9ucyh0aGlzLGUpKXJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7Y29uc3Qgcz1uZXcgU2V0KFsiYXJlYSIsImRyYXciLCJleGNsR3JvdXAiLCJmaWVsZCIsInN1YmZvcm0iLCJzdWJmb3JtU2V0Il0pO2lmKHRoaXMubGF5b3V0LmluY2x1ZGVzKCJyb3ciKSl7Y29uc3QgZT10aGlzW3VzXSgpLmNvbHVtbldpZHRocztpZihBcnJheS5pc0FycmF5KGUpJiZlLmxlbmd0aD4wKXt0aGlzW0ppXS5jb2x1bW5XaWR0aHM9ZTt0aGlzW0ppXS5jdXJyZW50Q29sdW1uPTB9fWNvbnN0IG89dG9TdHlsZSh0aGlzLCJhbmNob3JUeXBlIiwiZGltZW5zaW9ucyIsInBvc2l0aW9uIiwicHJlc2VuY2UiLCJib3JkZXIiLCJtYXJnaW4iLCJoQWxpZ24iKSxjPVsieGZhU3ViZm9ybSJdLGw9bGF5b3V0Q2xhc3ModGhpcyk7bCYmYy5wdXNoKGwpO3Iuc3R5bGU9bztyLmNsYXNzPWM7dGhpcy5uYW1lJiYoci54ZmFOYW1lPXRoaXMubmFtZSk7aWYodGhpcy5vdmVyZmxvdyl7Y29uc3QgdD10aGlzLm92ZXJmbG93W3NzXSgpO2lmKHQuYWRkTGVhZGVyKXt0LmFkZExlYWRlcj0hMTtoYW5kbGVPdmVyZmxvdyh0aGlzLHQubGVhZGVyLGUpfX10aGlzW0xzXSgpO2NvbnN0IGg9ImxyLXRiIj09PXRoaXMubGF5b3V0fHwicmwtdGIiPT09dGhpcy5sYXlvdXQsdT1oPzI6MTtmb3IoO3RoaXNbSmldLmF0dGVtcHQ8dTt0aGlzW0ppXS5hdHRlbXB0Kyspe2gmJjE9PT10aGlzW0ppXS5hdHRlbXB0JiYodGhpc1tKaV0ubnVtYmVySW5MaW5lPTApO2NvbnN0IGU9dGhpc1txaV0oe2ZpbHRlcjpzLGluY2x1ZGU6ITB9KTtpZihlLnN1Y2Nlc3MpYnJlYWs7aWYoZS5pc0JyZWFrKCkpe3RoaXNbX3NdKCk7cmV0dXJuIGV9aWYoaCYmMD09PXRoaXNbSmldLmF0dGVtcHQmJjA9PT10aGlzW0ppXS5udW1iZXJJbkxpbmUmJiFhW0ppXS5ub0xheW91dEZhaWx1cmUpe3RoaXNbSmldLmF0dGVtcHQ9dTticmVha319dGhpc1tfc10oKTtpfHx1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpO2FbSmldLm5vTGF5b3V0RmFpbHVyZT1uO2lmKHRoaXNbSmldLmF0dGVtcHQ9PT11KXt0aGlzLm92ZXJmbG93JiYodGhpc1tmc10oKVtKaV0ub3ZlcmZsb3dOb2RlPXRoaXMub3ZlcmZsb3cpO2l8fGRlbGV0ZSB0aGlzW0ppXTtyZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFfWlmKHRoaXMub3ZlcmZsb3cpe2NvbnN0IHQ9dGhpcy5vdmVyZmxvd1tzc10oKTtpZih0LmFkZFRyYWlsZXIpe3QuYWRkVHJhaWxlcj0hMTtoYW5kbGVPdmVyZmxvdyh0aGlzLHQudHJhaWxlcixlKX19bGV0IGQ9MCxmPTA7aWYodGhpcy5tYXJnaW4pe2Q9dGhpcy5tYXJnaW4ubGVmdEluc2V0K3RoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7Zj10aGlzLm1hcmdpbi50b3BJbnNldCt0aGlzLm1hcmdpbi5ib3R0b21JbnNldH1jb25zdCBnPU1hdGgubWF4KHRoaXNbSmldLndpZHRoK2QsdGhpcy53fHwwKSxwPU1hdGgubWF4KHRoaXNbSmldLmhlaWdodCtmLHRoaXMuaHx8MCksbT1bdGhpcy54LHRoaXMueSxnLHBdOyIiPT09dGhpcy53JiYoby53aWR0aD1tZWFzdXJlVG9TdHJpbmcoZykpOyIiPT09dGhpcy5oJiYoby5oZWlnaHQ9bWVhc3VyZVRvU3RyaW5nKHApKTtpZigoIjBweCI9PT1vLndpZHRofHwiMHB4Ij09PW8uaGVpZ2h0KSYmMD09PXQubGVuZ3RoKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO2NvbnN0IGI9e25hbWU6ImRpdiIsYXR0cmlidXRlczpyLGNoaWxkcmVuOnR9O2FwcGx5QXNzaXN0KHRoaXMscik7Y29uc3QgeT1IVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLGIpLG0pO2lmKHRoaXMuYnJlYWtBZnRlci5jaGlsZHJlbi5sZW5ndGg+PTEpe2NvbnN0IGU9dGhpcy5icmVha0FmdGVyLmNoaWxkcmVuWzBdO2lmKGhhbmRsZUJyZWFrKGUpKXt0aGlzW0ppXS5hZnRlckJyZWFrQWZ0ZXI9eTtyZXR1cm4gSFRNTFJlc3VsdC5icmVha05vZGUoZSl9fWRlbGV0ZSB0aGlzW0ppXTtyZXR1cm4geX19Y2xhc3MgU3ViZm9ybVNldCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywic3ViZm9ybVNldCIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy5yZWxhdGlvbj1nZXRTdHJpbmdPcHRpb24oZS5yZWxhdGlvbixbIm9yZGVyZWQiLCJjaG9pY2UiLCJ1bm9yZGVyZWQiXSk7dGhpcy5yZWxldmFudD1nZXRSZWxldmFudChlLnJlbGV2YW50KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5ib29rZW5kPW51bGw7dGhpcy5icmVhaz1udWxsO3RoaXMuZGVzYz1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5vY2N1cj1udWxsO3RoaXMub3ZlcmZsb3c9bnVsbDt0aGlzLmJyZWFrQWZ0ZXI9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuYnJlYWtCZWZvcmU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3ViZm9ybT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zdWJmb3JtU2V0PW5ldyBYRkFPYmplY3RBcnJheX0qW2xzXSgpe3lpZWxkKmdldENvbnRhaW5lZENoaWxkcmVuKHRoaXMpfVt1c10oKXtsZXQgZT10aGlzW2RzXSgpO2Zvcig7IShlIGluc3RhbmNlb2YgU3ViZm9ybSk7KWU9ZVtkc10oKTtyZXR1cm4gZX1beHNdKCl7cmV0dXJuITB9fWNsYXNzIFN1YmplY3RETiBleHRlbmRzIENvbnRlbnRPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInN1YmplY3RETiIpO3RoaXMuZGVsaW1pdGVyPWUuZGVsaW1pdGVyfHwiLCI7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9W1lpXSgpe3RoaXNbJGldPW5ldyBNYXAodGhpc1skaV0uc3BsaXQodGhpcy5kZWxpbWl0ZXIpLm1hcChlPT57KGU9ZS5zcGxpdCgiPSIsMikpWzBdPWVbMF0udHJpbSgpO3JldHVybiBlfSkpfX1jbGFzcyBTdWJqZWN0RE5zIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJzdWJqZWN0RE5zIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnR5cGU9Z2V0U3RyaW5nT3B0aW9uKGUudHlwZSxbIm9wdGlvbmFsIiwicmVxdWlyZWQiXSk7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIiO3RoaXMuc3ViamVjdEROPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgU3VibWl0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJzdWJtaXQiLCEwKTt0aGlzLmVtYmVkUERGPWdldEludGVnZXIoe2RhdGE6ZS5lbWJlZFBERixkZWZhdWx0VmFsdWU6MCx2YWxpZGF0ZTplPT4xPT09ZX0pO3RoaXMuZm9ybWF0PWdldFN0cmluZ09wdGlvbihlLmZvcm1hdCxbInhkcCIsImZvcm1kYXRhIiwicGRmIiwidXJsZW5jb2RlZCIsInhmZCIsInhtbCJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudGFyZ2V0PWUudGFyZ2V0fHwiIjt0aGlzLnRleHRFbmNvZGluZz1nZXRLZXl3b3JkKHtkYXRhOmUudGV4dEVuY29kaW5nP2UudGV4dEVuY29kaW5nLnRvTG93ZXJDYXNlKCk6IiIsZGVmYXVsdFZhbHVlOiIiLHZhbGlkYXRlOmU9PlsidXRmLTgiLCJiaWctZml2ZSIsImZvbnRzcGVjaWZpYyIsImdiayIsImdiLTE4MDMwIiwiZ2ItMjMxMiIsImtzYy01NjAxIiwibm9uZSIsInNoaWZ0LWppcyIsInVjcy0yIiwidXRmLTE2Il0uaW5jbHVkZXMoZSl8fGUubWF0Y2goL2lzby04ODU5LVxkezJ9Lyl9KTt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy54ZHBDb250ZW50PWUueGRwQ29udGVudHx8IiI7dGhpcy5lbmNyeXB0PW51bGw7dGhpcy5lbmNyeXB0RGF0YT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zaWduRGF0YT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIFRlbXBsYXRlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJ0ZW1wbGF0ZSIsITApO3RoaXMuYmFzZVByb2ZpbGU9Z2V0U3RyaW5nT3B0aW9uKGUuYmFzZVByb2ZpbGUsWyJmdWxsIiwiaW50ZXJhY3RpdmVGb3JtcyJdKTt0aGlzLmV4dHJhcz1udWxsO3RoaXMuc3ViZm9ybT1uZXcgWEZBT2JqZWN0QXJyYXl9W1lpXSgpezA9PT10aGlzLnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoJiZ3YXJuKCJYRkEgLSBObyBzdWJmb3JtcyBpbiB0ZW1wbGF0ZSBub2RlLiIpO3RoaXMuc3ViZm9ybS5jaGlsZHJlbi5sZW5ndGg+PTImJndhcm4oIlhGQSAtIFNldmVyYWwgc3ViZm9ybXMgaW4gdGVtcGxhdGUgbm9kZTogcGxlYXNlIGZpbGUgYSBidWcuIik7dGhpc1tHc109NWUzfVtDc10oKXtyZXR1cm4hMH1bWHNdKGUsdCl7cmV0dXJuIGUuc3RhcnRzV2l0aCgiIyIpP1t0aGlzW21zXS5nZXQoZS5zbGljZSgxKSldOnNlYXJjaE5vZGUodGhpcyx0LGUsITAsITApfSpbVnNdKCl7aWYoIXRoaXMuc3ViZm9ybS5jaGlsZHJlbi5sZW5ndGgpcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7bmFtZToiZGl2IixjaGlsZHJlbjpbXX0pO3RoaXNbSmldPXtvdmVyZmxvd05vZGU6bnVsbCxmaXJzdFVuc3BsaXR0YWJsZTpudWxsLGN1cnJlbnRDb250ZW50QXJlYTpudWxsLGN1cnJlbnRQYWdlQXJlYTpudWxsLG5vTGF5b3V0RmFpbHVyZTohMSxwYWdlTnVtYmVyOjEscGFnZVBvc2l0aW9uOiJmaXJzdCIsb2RkT3JFdmVuOiJvZGQiLGJsYW5rT3JOb3RCbGFuazoibm9uQmxhbmsiLHBhcmFTdGFjazpbXX07Y29uc3QgZT10aGlzLnN1YmZvcm0uY2hpbGRyZW5bMF07ZS5wYWdlU2V0W0hpXSgpO2NvbnN0IHQ9ZS5wYWdlU2V0LnBhZ2VBcmVhLmNoaWxkcmVuLHI9e25hbWU6ImRpdiIsY2hpbGRyZW46W119O2xldCBhPW51bGwsbj1udWxsLGk9bnVsbDtpZihlLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aD49MSl7bj1lLmJyZWFrQmVmb3JlLmNoaWxkcmVuWzBdO2k9bi50YXJnZXR9ZWxzZSBpZihlLnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoPj0xJiZlLnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoPj0xKXtuPWUuc3ViZm9ybS5jaGlsZHJlblswXS5icmVha0JlZm9yZS5jaGlsZHJlblswXTtpPW4udGFyZ2V0fWVsc2UgaWYoZS5icmVhaz8uYmVmb3JlVGFyZ2V0KXtuPWUuYnJlYWs7aT1uLmJlZm9yZVRhcmdldH1lbHNlIGlmKGUuc3ViZm9ybS5jaGlsZHJlbi5sZW5ndGg+PTEmJmUuc3ViZm9ybS5jaGlsZHJlblswXS5icmVhaz8uYmVmb3JlVGFyZ2V0KXtuPWUuc3ViZm9ybS5jaGlsZHJlblswXS5icmVhaztpPW4uYmVmb3JlVGFyZ2V0fWlmKG4pe2NvbnN0IGU9dGhpc1tYc10oaSxuW2RzXSgpKTtpZihlIGluc3RhbmNlb2YgUGFnZUFyZWEpe2E9ZTtuW0ppXT17fX19YXx8PXRbMF07YVtKaV09e251bWJlck9mVXNlOjF9O2NvbnN0IHM9YVtkc10oKTtzW0ppXT17bnVtYmVyT2ZVc2U6MSxwYWdlSW5kZXg6cy5wYWdlQXJlYS5jaGlsZHJlbi5pbmRleE9mKGEpLHBhZ2VTZXRJbmRleDowfTtsZXQgbyxjPW51bGwsbD1udWxsLGg9ITAsdT0wLGQ9MDtmb3IoOzspe2lmKGgpdT0wO2Vsc2V7ci5jaGlsZHJlbi5wb3AoKTtpZigzPT09Kyt1KXt3YXJuKCJYRkEgLSBTb21ldGhpbmcgZ29lcyB3cm9uZzogcGxlYXNlIGZpbGUgYSBidWcuIik7cmV0dXJuIHJ9fW89bnVsbDt0aGlzW0ppXS5jdXJyZW50UGFnZUFyZWE9YTtjb25zdCB0PWFbS3NdKCkuaHRtbDtyLmNoaWxkcmVuLnB1c2godCk7aWYoYyl7dGhpc1tKaV0ubm9MYXlvdXRGYWlsdXJlPSEwO3QuY2hpbGRyZW4ucHVzaChjW0tzXShhW0ppXS5zcGFjZSkuaHRtbCk7Yz1udWxsfWlmKGwpe3RoaXNbSmldLm5vTGF5b3V0RmFpbHVyZT0hMDt0LmNoaWxkcmVuLnB1c2gobFtLc10oYVtKaV0uc3BhY2UpLmh0bWwpO2w9bnVsbH1jb25zdCBuPWEuY29udGVudEFyZWEuY2hpbGRyZW4saT10LmNoaWxkcmVuLmZpbHRlcihlPT5lLmF0dHJpYnV0ZXMuY2xhc3MuaW5jbHVkZXMoInhmYUNvbnRlbnRhcmVhIikpO2g9ITE7dGhpc1tKaV0uZmlyc3RVbnNwbGl0dGFibGU9bnVsbDt0aGlzW0ppXS5ub0xheW91dEZhaWx1cmU9ITE7Y29uc3QgZmx1c2g9dD0+e2NvbnN0IHI9ZVtaaV0oKTtpZihyKXtofHw9ci5jaGlsZHJlbj8ubGVuZ3RoPjA7aVt0XS5jaGlsZHJlbi5wdXNoKHIpfX07Zm9yKGxldCB0PWQsYT1uLmxlbmd0aDt0PGE7dCsrKXtjb25zdCBhPXRoaXNbSmldLmN1cnJlbnRDb250ZW50QXJlYT1uW3RdLHM9e3dpZHRoOmEudyxoZWlnaHQ6YS5ofTtkPTA7aWYoYyl7aVt0XS5jaGlsZHJlbi5wdXNoKGNbS3NdKHMpLmh0bWwpO2M9bnVsbH1pZihsKXtpW3RdLmNoaWxkcmVuLnB1c2gobFtLc10ocykuaHRtbCk7bD1udWxsfWNvbnN0IHU9ZVtLc10ocyk7aWYodS5zdWNjZXNzKXtpZih1Lmh0bWwpe2h8fD11Lmh0bWwuY2hpbGRyZW4/Lmxlbmd0aD4wO2lbdF0uY2hpbGRyZW4ucHVzaCh1Lmh0bWwpfWVsc2UhaCYmci5jaGlsZHJlbi5sZW5ndGg+MSYmci5jaGlsZHJlbi5wb3AoKTtyZXR1cm4gcn1pZih1LmlzQnJlYWsoKSl7Y29uc3QgZT11LmJyZWFrTm9kZTtmbHVzaCh0KTtpZigiYXV0byI9PT1lLnRhcmdldFR5cGUpY29udGludWU7aWYoZS5sZWFkZXIpe2M9dGhpc1tYc10oZS5sZWFkZXIsZVtkc10oKSk7Yz1jP2NbMF06bnVsbH1pZihlLnRyYWlsZXIpe2w9dGhpc1tYc10oZS50cmFpbGVyLGVbZHNdKCkpO2w9bD9sWzBdOm51bGx9aWYoInBhZ2VBcmVhIj09PWUudGFyZ2V0VHlwZSl7bz1lW0ppXS50YXJnZXQ7dD0xLzB9ZWxzZSBpZihlW0ppXS50YXJnZXQpe289ZVtKaV0udGFyZ2V0O2Q9ZVtKaV0uaW5kZXgrMTt0PTEvMH1lbHNlIHQ9ZVtKaV0uaW5kZXg7Y29udGludWV9aWYodGhpc1tKaV0ub3ZlcmZsb3dOb2RlKXtjb25zdCBlPXRoaXNbSmldLm92ZXJmbG93Tm9kZTt0aGlzW0ppXS5vdmVyZmxvd05vZGU9bnVsbDtjb25zdCByPWVbc3NdKCksYT1yLnRhcmdldDtyLmFkZExlYWRlcj1udWxsIT09ci5sZWFkZXI7ci5hZGRUcmFpbGVyPW51bGwhPT1yLnRyYWlsZXI7Zmx1c2godCk7Y29uc3QgaT10O3Q9MS8wO2lmKGEgaW5zdGFuY2VvZiBQYWdlQXJlYSlvPWE7ZWxzZSBpZihhIGluc3RhbmNlb2YgQ29udGVudEFyZWEpe2NvbnN0IGU9bi5pbmRleE9mKGEpO2lmKC0xIT09ZSllPmk/dD1lLTE6ZD1lO2Vsc2V7bz1hW2RzXSgpO2Q9by5jb250ZW50QXJlYS5jaGlsZHJlbi5pbmRleE9mKGEpfX1jb250aW51ZX1mbHVzaCh0KX10aGlzW0ppXS5wYWdlTnVtYmVyKz0xO28mJihvW0lzXSgpP29bSmldLm51bWJlck9mVXNlKz0xOm89bnVsbCk7YT1vfHxhW2hzXSgpO3lpZWxkIG51bGx9fX1jbGFzcyBUZXh0IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidGV4dCIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5tYXhDaGFycz1nZXRJbnRlZ2VyKHtkYXRhOmUubWF4Q2hhcnMsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+ZT49MH0pO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMucmlkPWUucmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9W1BpXSgpe3JldHVybiEwfVtCc10oZSl7aWYoZVtPc109PT1lby54aHRtbC5pZCl7dGhpc1skaV09ZTtyZXR1cm4hMH13YXJuKGBYRkEgLSBJbnZhbGlkIGNvbnRlbnQgaW4gVGV4dDogJHtlW01zXX0uYCk7cmV0dXJuITF9W0VzXShlKXt0aGlzWyRpXWluc3RhbmNlb2YgWEZBT2JqZWN0fHxzdXBlcltFc10oZSl9W1lpXSgpeyJzdHJpbmciPT10eXBlb2YgdGhpc1skaV0mJih0aGlzWyRpXT10aGlzWyRpXS5yZXBsYWNlQWxsKCJcclxuIiwiXG4iKSl9W3NzXSgpe3JldHVybiJzdHJpbmciPT10eXBlb2YgdGhpc1skaV0/dGhpc1skaV0uc3BsaXQoL1tcdTIwMjlcdTIwMjhcbl0vKS5maWx0ZXIoZT0+ISFlKS5qb2luKCJcbiIpOnRoaXNbJGldWyRzXSgpfVtLc10oZSl7aWYoInN0cmluZyI9PXR5cGVvZiB0aGlzWyRpXSl7Y29uc3QgZT12YWx1ZVRvSHRtbCh0aGlzWyRpXSkuaHRtbDtpZih0aGlzWyRpXS5pbmNsdWRlcygiXHUyMDI5Iikpe2UubmFtZT0iZGl2IjtlLmNoaWxkcmVuPVtdO3RoaXNbJGldLnNwbGl0KCJcdTIwMjkiKS5tYXAoZT0+ZS5zcGxpdCgvW1x1MjAyOFxuXS8pLmZsYXRNYXAoZT0+W3tuYW1lOiJzcGFuIix2YWx1ZTplfSx7bmFtZToiYnIifV0pKS5mb3JFYWNoKHQ9PntlLmNoaWxkcmVuLnB1c2goe25hbWU6InAiLGNoaWxkcmVuOnR9KX0pfWVsc2UgaWYoL1tcdTIwMjhcbl0vLnRlc3QodGhpc1skaV0pKXtlLm5hbWU9ImRpdiI7ZS5jaGlsZHJlbj1bXTt0aGlzWyRpXS5zcGxpdCgvW1x1MjAyOFxuXS8pLmZvckVhY2godD0+e2UuY2hpbGRyZW4ucHVzaCh7bmFtZToic3BhbiIsdmFsdWU6dH0se25hbWU6ImJyIn0pfSl9cmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhlKX1yZXR1cm4gdGhpc1skaV1bS3NdKGUpfX1jbGFzcyBUZXh0RWRpdCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidGV4dEVkaXQiLCEwKTt0aGlzLmFsbG93UmljaFRleHQ9Z2V0SW50ZWdlcih7ZGF0YTplLmFsbG93UmljaFRleHQsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLmhTY3JvbGxQb2xpY3k9Z2V0U3RyaW5nT3B0aW9uKGUuaFNjcm9sbFBvbGljeSxbImF1dG8iLCJvZmYiLCJvbiJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubXVsdGlMaW5lPWdldEludGVnZXIoe2RhdGE6ZS5tdWx0aUxpbmUsZGVmYXVsdFZhbHVlOiIiLHZhbGlkYXRlOmU9PjA9PT1lfHwxPT09ZX0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLnZTY3JvbGxQb2xpY3k9Z2V0U3RyaW5nT3B0aW9uKGUudlNjcm9sbFBvbGljeSxbImF1dG8iLCJvZmYiLCJvbiJdKTt0aGlzLmJvcmRlcj1udWxsO3RoaXMuY29tYj1udWxsO3RoaXMuZXh0cmFzPW51bGw7dGhpcy5tYXJnaW49bnVsbH1bS3NdKGUpe2NvbnN0IHQ9dG9TdHlsZSh0aGlzLCJib3JkZXIiLCJmb250IiwibWFyZ2luIik7bGV0IHI7Y29uc3QgYT10aGlzW2RzXSgpW2RzXSgpOyIiPT09dGhpcy5tdWx0aUxpbmUmJih0aGlzLm11bHRpTGluZT1hIGluc3RhbmNlb2YgRHJhdz8xOjApO3I9MT09PXRoaXMubXVsdGlMaW5lP3tuYW1lOiJ0ZXh0YXJlYSIsYXR0cmlidXRlczp7ZGF0YUlkOmFbVmldPy5bWnNdfHxhW1pzXSxmaWVsZElkOmFbWnNdLGNsYXNzOlsieGZhVGV4dGZpZWxkIl0sc3R5bGU6dCwiYXJpYS1sYWJlbCI6YXJpYUxhYmVsKGEpLCJhcmlhLXJlcXVpcmVkIjohMX19OntuYW1lOiJpbnB1dCIsYXR0cmlidXRlczp7dHlwZToidGV4dCIsZGF0YUlkOmFbVmldPy5bWnNdfHxhW1pzXSxmaWVsZElkOmFbWnNdLGNsYXNzOlsieGZhVGV4dGZpZWxkIl0sc3R5bGU6dCwiYXJpYS1sYWJlbCI6YXJpYUxhYmVsKGEpLCJhcmlhLXJlcXVpcmVkIjohMX19O2lmKGlzUmVxdWlyZWQoYSkpe3IuYXR0cmlidXRlc1siYXJpYS1yZXF1aXJlZCJdPSEwO3IuYXR0cmlidXRlcy5yZXF1aXJlZD0hMH1yZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJsYWJlbCIsYXR0cmlidXRlczp7Y2xhc3M6WyJ4ZmFMYWJlbCJdfSxjaGlsZHJlbjpbcl19KX19Y2xhc3MgVGltZSBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidGltZSIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifVtZaV0oKXtjb25zdCBlPXRoaXNbJGldLnRyaW0oKTt0aGlzWyRpXT1lP25ldyBEYXRlKGUpOm51bGx9W0tzXShlKXtyZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skaV0/dGhpc1skaV0udG9TdHJpbmcoKToiIil9fWNsYXNzIFRpbWVTdGFtcCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidGltZVN0YW1wIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnNlcnZlcj1lLnNlcnZlcnx8IiI7dGhpcy50eXBlPWdldFN0cmluZ09wdGlvbihlLnR5cGUsWyJvcHRpb25hbCIsInJlcXVpcmVkIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgVG9vbFRpcCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidG9vbFRpcCIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5yaWQ9ZS5yaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgVHJhdmVyc2FsIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJ0cmF2ZXJzYWwiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsO3RoaXMudHJhdmVyc2U9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBUcmF2ZXJzZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidHJhdmVyc2UiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMub3BlcmF0aW9uPWdldFN0cmluZ09wdGlvbihlLm9wZXJhdGlvbixbIm5leHQiLCJiYWNrIiwiZG93biIsImZpcnN0IiwibGVmdCIsInJpZ2h0IiwidXAiXSk7dGhpcy5yZWY9ZS5yZWZ8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsO3RoaXMuc2NyaXB0PW51bGx9Z2V0IG5hbWUoKXtyZXR1cm4gdGhpcy5vcGVyYXRpb259W0ZzXSgpe3JldHVybiExfX1jbGFzcyBVaSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidWkiLCEwKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsO3RoaXMucGljdHVyZT1udWxsO3RoaXMuYmFyY29kZT1udWxsO3RoaXMuYnV0dG9uPW51bGw7dGhpcy5jaGVja0J1dHRvbj1udWxsO3RoaXMuY2hvaWNlTGlzdD1udWxsO3RoaXMuZGF0ZVRpbWVFZGl0PW51bGw7dGhpcy5kZWZhdWx0VWk9bnVsbDt0aGlzLmltYWdlRWRpdD1udWxsO3RoaXMubnVtZXJpY0VkaXQ9bnVsbDt0aGlzLnBhc3N3b3JkRWRpdD1udWxsO3RoaXMuc2lnbmF0dXJlPW51bGw7dGhpcy50ZXh0RWRpdD1udWxsfVtzc10oKXtpZih2b2lkIDA9PT10aGlzW0ppXSl7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpe2lmKCJleHRyYXMiPT09ZXx8InBpY3R1cmUiPT09ZSljb250aW51ZTtjb25zdCB0PXRoaXNbZV07aWYodCBpbnN0YW5jZW9mIFhGQU9iamVjdCl7dGhpc1tKaV09dDtyZXR1cm4gdH19dGhpc1tKaV09bnVsbH1yZXR1cm4gdGhpc1tKaV19W0tzXShlKXtjb25zdCB0PXRoaXNbc3NdKCk7cmV0dXJuIHQ/dFtLc10oZSk6SFRNTFJlc3VsdC5FTVBUWX19Y2xhc3MgVmFsaWRhdGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoRW8sInZhbGlkYXRlIiwhMCk7dGhpcy5mb3JtYXRUZXN0PWdldFN0cmluZ09wdGlvbihlLmZvcm1hdFRlc3QsWyJ3YXJuaW5nIiwiZGlzYWJsZWQiLCJlcnJvciJdKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubnVsbFRlc3Q9Z2V0U3RyaW5nT3B0aW9uKGUubnVsbFRlc3QsWyJkaXNhYmxlZCIsImVycm9yIiwid2FybmluZyJdKTt0aGlzLnNjcmlwdFRlc3Q9Z2V0U3RyaW5nT3B0aW9uKGUuc2NyaXB0VGVzdCxbImVycm9yIiwiZGlzYWJsZWQiLCJ3YXJuaW5nIl0pO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmV4dHJhcz1udWxsO3RoaXMubWVzc2FnZT1udWxsO3RoaXMucGljdHVyZT1udWxsO3RoaXMuc2NyaXB0PW51bGx9fWNsYXNzIFZhbHVlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEVvLCJ2YWx1ZSIsITApO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5vdmVycmlkZT1nZXRJbnRlZ2VyKHtkYXRhOmUub3ZlcnJpZGUsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLnJlbGV2YW50PWdldFJlbGV2YW50KGUucmVsZXZhbnQpO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIjt0aGlzLmFyYz1udWxsO3RoaXMuYm9vbGVhbj1udWxsO3RoaXMuZGF0ZT1udWxsO3RoaXMuZGF0ZVRpbWU9bnVsbDt0aGlzLmRlY2ltYWw9bnVsbDt0aGlzLmV4RGF0YT1udWxsO3RoaXMuZmxvYXQ9bnVsbDt0aGlzLmltYWdlPW51bGw7dGhpcy5pbnRlZ2VyPW51bGw7dGhpcy5saW5lPW51bGw7dGhpcy5yZWN0YW5nbGU9bnVsbDt0aGlzLnRleHQ9bnVsbDt0aGlzLnRpbWU9bnVsbH1benNdKGUpe2NvbnN0IHQ9dGhpc1tkc10oKTtpZih0IGluc3RhbmNlb2YgRmllbGQmJnQudWk/LmltYWdlRWRpdCl7aWYoIXRoaXMuaW1hZ2Upe3RoaXMuaW1hZ2U9bmV3IEltYWdlKHt9KTt0aGlzW2ppXSh0aGlzLmltYWdlKX10aGlzLmltYWdlWyRpXT1lWyRpXTtyZXR1cm59Y29uc3Qgcj1lW01zXTtpZihudWxsPT09dGhpc1tyXSl7Zm9yKGNvbnN0IGUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpe2NvbnN0IHQ9dGhpc1tlXTtpZih0IGluc3RhbmNlb2YgWEZBT2JqZWN0KXt0aGlzW2VdPW51bGw7dGhpc1tqc10odCl9fXRoaXNbZVtNc11dPWU7dGhpc1tqaV0oZSl9ZWxzZSB0aGlzW3JdWyRpXT1lWyRpXX1bJHNdKCl7aWYodGhpcy5leERhdGEpcmV0dXJuInN0cmluZyI9PXR5cGVvZiB0aGlzLmV4RGF0YVskaV0/dGhpcy5leERhdGFbJGldLnRyaW0oKTp0aGlzLmV4RGF0YVskaV1bJHNdKCkudHJpbSgpO2Zvcihjb25zdCBlIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKXtpZigiaW1hZ2UiPT09ZSljb250aW51ZTtjb25zdCB0PXRoaXNbZV07aWYodCBpbnN0YW5jZW9mIFhGQU9iamVjdClyZXR1cm4odFskaV18fCIiKS50b1N0cmluZygpLnRyaW0oKX1yZXR1cm4gbnVsbH1bS3NdKGUpe2Zvcihjb25zdCB0IG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKXtjb25zdCByPXRoaXNbdF07aWYociBpbnN0YW5jZW9mIFhGQU9iamVjdClyZXR1cm4gcltLc10oZSl9cmV0dXJuIEhUTUxSZXN1bHQuRU1QVFl9fWNsYXNzIFZhcmlhYmxlcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihFbywidmFyaWFibGVzIiwhMCk7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiI7dGhpcy5ib29sZWFuPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRhdGU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGF0ZVRpbWU9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZGVjaW1hbD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5leERhdGE9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuZmxvYXQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW1hZ2U9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuaW50ZWdlcj1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5tYW5pZmVzdD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5zY3JpcHQ9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudGV4dD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy50aW1lPW5ldyBYRkFPYmplY3RBcnJheX1bRnNdKCl7cmV0dXJuITB9fWNsYXNzIFRlbXBsYXRlTmFtZXNwYWNle3N0YXRpY1tRc10oZSx0KXtpZihUZW1wbGF0ZU5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShlKSl7Y29uc3Qgcj1UZW1wbGF0ZU5hbWVzcGFjZVtlXSh0KTtyW1dzXSh0KTtyZXR1cm4gcn19c3RhdGljIGFwcGVhcmFuY2VGaWx0ZXIoZSl7cmV0dXJuIG5ldyBBcHBlYXJhbmNlRmlsdGVyKGUpfXN0YXRpYyBhcmMoZSl7cmV0dXJuIG5ldyBBcmMoZSl9c3RhdGljIGFyZWEoZSl7cmV0dXJuIG5ldyBBcmVhKGUpfXN0YXRpYyBhc3Npc3QoZSl7cmV0dXJuIG5ldyBBc3Npc3QoZSl9c3RhdGljIGJhcmNvZGUoZSl7cmV0dXJuIG5ldyBCYXJjb2RlKGUpfXN0YXRpYyBiaW5kKGUpe3JldHVybiBuZXcgQmluZChlKX1zdGF0aWMgYmluZEl0ZW1zKGUpe3JldHVybiBuZXcgQmluZEl0ZW1zKGUpfXN0YXRpYyBib29rZW5kKGUpe3JldHVybiBuZXcgQm9va2VuZChlKX1zdGF0aWMgYm9vbGVhbihlKXtyZXR1cm4gbmV3IEJvb2xlYW5FbGVtZW50KGUpfXN0YXRpYyBib3JkZXIoZSl7cmV0dXJuIG5ldyBCb3JkZXIoZSl9c3RhdGljIGJyZWFrKGUpe3JldHVybiBuZXcgQnJlYWsoZSl9c3RhdGljIGJyZWFrQWZ0ZXIoZSl7cmV0dXJuIG5ldyBCcmVha0FmdGVyKGUpfXN0YXRpYyBicmVha0JlZm9yZShlKXtyZXR1cm4gbmV3IEJyZWFrQmVmb3JlKGUpfXN0YXRpYyBidXR0b24oZSl7cmV0dXJuIG5ldyBCdXR0b24oZSl9c3RhdGljIGNhbGN1bGF0ZShlKXtyZXR1cm4gbmV3IENhbGN1bGF0ZShlKX1zdGF0aWMgY2FwdGlvbihlKXtyZXR1cm4gbmV3IENhcHRpb24oZSl9c3RhdGljIGNlcnRpZmljYXRlKGUpe3JldHVybiBuZXcgQ2VydGlmaWNhdGUoZSl9c3RhdGljIGNlcnRpZmljYXRlcyhlKXtyZXR1cm4gbmV3IENlcnRpZmljYXRlcyhlKX1zdGF0aWMgY2hlY2tCdXR0b24oZSl7cmV0dXJuIG5ldyBDaGVja0J1dHRvbihlKX1zdGF0aWMgY2hvaWNlTGlzdChlKXtyZXR1cm4gbmV3IENob2ljZUxpc3QoZSl9c3RhdGljIGNvbG9yKGUpe3JldHVybiBuZXcgQ29sb3IoZSl9c3RhdGljIGNvbWIoZSl7cmV0dXJuIG5ldyBDb21iKGUpfXN0YXRpYyBjb25uZWN0KGUpe3JldHVybiBuZXcgQ29ubmVjdChlKX1zdGF0aWMgY29udGVudEFyZWEoZSl7cmV0dXJuIG5ldyBDb250ZW50QXJlYShlKX1zdGF0aWMgY29ybmVyKGUpe3JldHVybiBuZXcgQ29ybmVyKGUpfXN0YXRpYyBkYXRlKGUpe3JldHVybiBuZXcgRGF0ZUVsZW1lbnQoZSl9c3RhdGljIGRhdGVUaW1lKGUpe3JldHVybiBuZXcgRGF0ZVRpbWUoZSl9c3RhdGljIGRhdGVUaW1lRWRpdChlKXtyZXR1cm4gbmV3IERhdGVUaW1lRWRpdChlKX1zdGF0aWMgZGVjaW1hbChlKXtyZXR1cm4gbmV3IERlY2ltYWwoZSl9c3RhdGljIGRlZmF1bHRVaShlKXtyZXR1cm4gbmV3IERlZmF1bHRVaShlKX1zdGF0aWMgZGVzYyhlKXtyZXR1cm4gbmV3IERlc2MoZSl9c3RhdGljIGRpZ2VzdE1ldGhvZChlKXtyZXR1cm4gbmV3IERpZ2VzdE1ldGhvZChlKX1zdGF0aWMgZGlnZXN0TWV0aG9kcyhlKXtyZXR1cm4gbmV3IERpZ2VzdE1ldGhvZHMoZSl9c3RhdGljIGRyYXcoZSl7cmV0dXJuIG5ldyBEcmF3KGUpfXN0YXRpYyBlZGdlKGUpe3JldHVybiBuZXcgRWRnZShlKX1zdGF0aWMgZW5jb2RpbmcoZSl7cmV0dXJuIG5ldyBFbmNvZGluZyhlKX1zdGF0aWMgZW5jb2RpbmdzKGUpe3JldHVybiBuZXcgRW5jb2RpbmdzKGUpfXN0YXRpYyBlbmNyeXB0KGUpe3JldHVybiBuZXcgRW5jcnlwdChlKX1zdGF0aWMgZW5jcnlwdERhdGEoZSl7cmV0dXJuIG5ldyBFbmNyeXB0RGF0YShlKX1zdGF0aWMgZW5jcnlwdGlvbihlKXtyZXR1cm4gbmV3IEVuY3J5cHRpb24oZSl9c3RhdGljIGVuY3J5cHRpb25NZXRob2QoZSl7cmV0dXJuIG5ldyBFbmNyeXB0aW9uTWV0aG9kKGUpfXN0YXRpYyBlbmNyeXB0aW9uTWV0aG9kcyhlKXtyZXR1cm4gbmV3IEVuY3J5cHRpb25NZXRob2RzKGUpfXN0YXRpYyBldmVudChlKXtyZXR1cm4gbmV3IEV2ZW50KGUpfXN0YXRpYyBleERhdGEoZSl7cmV0dXJuIG5ldyBFeERhdGEoZSl9c3RhdGljIGV4T2JqZWN0KGUpe3JldHVybiBuZXcgRXhPYmplY3QoZSl9c3RhdGljIGV4Y2xHcm91cChlKXtyZXR1cm4gbmV3IEV4Y2xHcm91cChlKX1zdGF0aWMgZXhlY3V0ZShlKXtyZXR1cm4gbmV3IEV4ZWN1dGUoZSl9c3RhdGljIGV4dHJhcyhlKXtyZXR1cm4gbmV3IEV4dHJhcyhlKX1zdGF0aWMgZmllbGQoZSl7cmV0dXJuIG5ldyBGaWVsZChlKX1zdGF0aWMgZmlsbChlKXtyZXR1cm4gbmV3IEZpbGwoZSl9c3RhdGljIGZpbHRlcihlKXtyZXR1cm4gbmV3IEZpbHRlcihlKX1zdGF0aWMgZmxvYXQoZSl7cmV0dXJuIG5ldyBGbG9hdChlKX1zdGF0aWMgZm9udChlKXtyZXR1cm4gbmV3IHRlbXBsYXRlX0ZvbnQoZSl9c3RhdGljIGZvcm1hdChlKXtyZXR1cm4gbmV3IEZvcm1hdChlKX1zdGF0aWMgaGFuZGxlcihlKXtyZXR1cm4gbmV3IEhhbmRsZXIoZSl9c3RhdGljIGh5cGhlbmF0aW9uKGUpe3JldHVybiBuZXcgSHlwaGVuYXRpb24oZSl9c3RhdGljIGltYWdlKGUpe3JldHVybiBuZXcgSW1hZ2UoZSl9c3RhdGljIGltYWdlRWRpdChlKXtyZXR1cm4gbmV3IEltYWdlRWRpdChlKX1zdGF0aWMgaW50ZWdlcihlKXtyZXR1cm4gbmV3IEludGVnZXIoZSl9c3RhdGljIGlzc3VlcnMoZSl7cmV0dXJuIG5ldyBJc3N1ZXJzKGUpfXN0YXRpYyBpdGVtcyhlKXtyZXR1cm4gbmV3IEl0ZW1zKGUpfXN0YXRpYyBrZWVwKGUpe3JldHVybiBuZXcgS2VlcChlKX1zdGF0aWMga2V5VXNhZ2UoZSl7cmV0dXJuIG5ldyBLZXlVc2FnZShlKX1zdGF0aWMgbGluZShlKXtyZXR1cm4gbmV3IExpbmUoZSl9c3RhdGljIGxpbmVhcihlKXtyZXR1cm4gbmV3IExpbmVhcihlKX1zdGF0aWMgbG9ja0RvY3VtZW50KGUpe3JldHVybiBuZXcgTG9ja0RvY3VtZW50KGUpfXN0YXRpYyBtYW5pZmVzdChlKXtyZXR1cm4gbmV3IE1hbmlmZXN0KGUpfXN0YXRpYyBtYXJnaW4oZSl7cmV0dXJuIG5ldyBNYXJnaW4oZSl9c3RhdGljIG1kcChlKXtyZXR1cm4gbmV3IE1kcChlKX1zdGF0aWMgbWVkaXVtKGUpe3JldHVybiBuZXcgTWVkaXVtKGUpfXN0YXRpYyBtZXNzYWdlKGUpe3JldHVybiBuZXcgTWVzc2FnZShlKX1zdGF0aWMgbnVtZXJpY0VkaXQoZSl7cmV0dXJuIG5ldyBOdW1lcmljRWRpdChlKX1zdGF0aWMgb2NjdXIoZSl7cmV0dXJuIG5ldyBPY2N1cihlKX1zdGF0aWMgb2lkKGUpe3JldHVybiBuZXcgT2lkKGUpfXN0YXRpYyBvaWRzKGUpe3JldHVybiBuZXcgT2lkcyhlKX1zdGF0aWMgb3ZlcmZsb3coZSl7cmV0dXJuIG5ldyBPdmVyZmxvdyhlKX1zdGF0aWMgcGFnZUFyZWEoZSl7cmV0dXJuIG5ldyBQYWdlQXJlYShlKX1zdGF0aWMgcGFnZVNldChlKXtyZXR1cm4gbmV3IFBhZ2VTZXQoZSl9c3RhdGljIHBhcmEoZSl7cmV0dXJuIG5ldyBQYXJhKGUpfXN0YXRpYyBwYXNzd29yZEVkaXQoZSl7cmV0dXJuIG5ldyBQYXNzd29yZEVkaXQoZSl9c3RhdGljIHBhdHRlcm4oZSl7cmV0dXJuIG5ldyB0ZW1wbGF0ZV9QYXR0ZXJuKGUpfXN0YXRpYyBwaWN0dXJlKGUpe3JldHVybiBuZXcgUGljdHVyZShlKX1zdGF0aWMgcHJvdG8oZSl7cmV0dXJuIG5ldyBQcm90byhlKX1zdGF0aWMgcmFkaWFsKGUpe3JldHVybiBuZXcgUmFkaWFsKGUpfXN0YXRpYyByZWFzb24oZSl7cmV0dXJuIG5ldyBSZWFzb24oZSl9c3RhdGljIHJlYXNvbnMoZSl7cmV0dXJuIG5ldyBSZWFzb25zKGUpfXN0YXRpYyByZWN0YW5nbGUoZSl7cmV0dXJuIG5ldyBSZWN0YW5nbGUoZSl9c3RhdGljIHJlZihlKXtyZXR1cm4gbmV3IFJlZkVsZW1lbnQoZSl9c3RhdGljIHNjcmlwdChlKXtyZXR1cm4gbmV3IFNjcmlwdChlKX1zdGF0aWMgc2V0UHJvcGVydHkoZSl7cmV0dXJuIG5ldyBTZXRQcm9wZXJ0eShlKX1zdGF0aWMgc2lnbkRhdGEoZSl7cmV0dXJuIG5ldyBTaWduRGF0YShlKX1zdGF0aWMgc2lnbmF0dXJlKGUpe3JldHVybiBuZXcgU2lnbmF0dXJlKGUpfXN0YXRpYyBzaWduaW5nKGUpe3JldHVybiBuZXcgU2lnbmluZyhlKX1zdGF0aWMgc29saWQoZSl7cmV0dXJuIG5ldyBTb2xpZChlKX1zdGF0aWMgc3BlYWsoZSl7cmV0dXJuIG5ldyBTcGVhayhlKX1zdGF0aWMgc3RpcHBsZShlKXtyZXR1cm4gbmV3IFN0aXBwbGUoZSl9c3RhdGljIHN1YmZvcm0oZSl7cmV0dXJuIG5ldyBTdWJmb3JtKGUpfXN0YXRpYyBzdWJmb3JtU2V0KGUpe3JldHVybiBuZXcgU3ViZm9ybVNldChlKX1zdGF0aWMgc3ViamVjdEROKGUpe3JldHVybiBuZXcgU3ViamVjdEROKGUpfXN0YXRpYyBzdWJqZWN0RE5zKGUpe3JldHVybiBuZXcgU3ViamVjdEROcyhlKX1zdGF0aWMgc3VibWl0KGUpe3JldHVybiBuZXcgU3VibWl0KGUpfXN0YXRpYyB0ZW1wbGF0ZShlKXtyZXR1cm4gbmV3IFRlbXBsYXRlKGUpfXN0YXRpYyB0ZXh0KGUpe3JldHVybiBuZXcgVGV4dChlKX1zdGF0aWMgdGV4dEVkaXQoZSl7cmV0dXJuIG5ldyBUZXh0RWRpdChlKX1zdGF0aWMgdGltZShlKXtyZXR1cm4gbmV3IFRpbWUoZSl9c3RhdGljIHRpbWVTdGFtcChlKXtyZXR1cm4gbmV3IFRpbWVTdGFtcChlKX1zdGF0aWMgdG9vbFRpcChlKXtyZXR1cm4gbmV3IFRvb2xUaXAoZSl9c3RhdGljIHRyYXZlcnNhbChlKXtyZXR1cm4gbmV3IFRyYXZlcnNhbChlKX1zdGF0aWMgdHJhdmVyc2UoZSl7cmV0dXJuIG5ldyBUcmF2ZXJzZShlKX1zdGF0aWMgdWkoZSl7cmV0dXJuIG5ldyBVaShlKX1zdGF0aWMgdmFsaWRhdGUoZSl7cmV0dXJuIG5ldyBWYWxpZGF0ZShlKX1zdGF0aWMgdmFsdWUoZSl7cmV0dXJuIG5ldyBWYWx1ZShlKX1zdGF0aWMgdmFyaWFibGVzKGUpe3JldHVybiBuZXcgVmFyaWFibGVzKGUpfX1jb25zdCBqbz1lby5kYXRhc2V0cy5pZDtmdW5jdGlvbiBjcmVhdGVUZXh0KGUpe2NvbnN0IHQ9bmV3IFRleHQoe30pO3RbJGldPWU7cmV0dXJuIHR9Y2xhc3MgQmluZGVye2NvbnN0cnVjdG9yKGUpe3RoaXMucm9vdD1lO3RoaXMuZGF0YXNldHM9ZS5kYXRhc2V0czt0aGlzLmRhdGE9ZS5kYXRhc2V0cz8uZGF0YXx8bmV3IFhtbE9iamVjdChlby5kYXRhc2V0cy5pZCwiZGF0YSIpO3RoaXMuZW1wdHlNZXJnZT0wPT09dGhpcy5kYXRhW2NzXSgpLmxlbmd0aDt0aGlzLnJvb3QuZm9ybT10aGlzLmZvcm09ZS50ZW1wbGF0ZVt6aV0oKX1faXNDb25zdW1lRGF0YSgpe3JldHVybiF0aGlzLmVtcHR5TWVyZ2UmJnRoaXMuX21lcmdlTW9kZX1faXNNYXRjaFRlbXBsYXRlKCl7cmV0dXJuIXRoaXMuX2lzQ29uc3VtZURhdGEoKX1iaW5kKCl7dGhpcy5fYmluZEVsZW1lbnQodGhpcy5mb3JtLHRoaXMuZGF0YSk7cmV0dXJuIHRoaXMuZm9ybX1nZXREYXRhKCl7cmV0dXJuIHRoaXMuZGF0YX1fYmluZFZhbHVlKGUsdCxyKXtlW1ZpXT10O2lmKGVbcHNdKCkpaWYodFtTc10oKSl7Y29uc3Qgcj10W2lzXSgpO2VbenNdKGNyZWF0ZVRleHQocikpfWVsc2UgaWYoZSBpbnN0YW5jZW9mIEZpZWxkJiYibXVsdGlTZWxlY3QiPT09ZS51aT8uY2hvaWNlTGlzdD8ub3Blbil7Y29uc3Qgcj10W2NzXSgpLm1hcChlPT5lWyRpXS50cmltKCkpLmpvaW4oIlxuIik7ZVt6c10oY3JlYXRlVGV4dChyKSl9ZWxzZSB0aGlzLl9pc0NvbnN1bWVEYXRhKCkmJndhcm4oIlhGQSAtIE5vZGVzIGhhdmVuJ3QgdGhlIHNhbWUgdHlwZS4iKTtlbHNlIXRbU3NdKCl8fHRoaXMuX2lzTWF0Y2hUZW1wbGF0ZSgpP3RoaXMuX2JpbmRFbGVtZW50KGUsdCk6d2FybigiWEZBIC0gTm9kZXMgaGF2ZW4ndCB0aGUgc2FtZSB0eXBlLiIpfV9maW5kRGF0YUJ5TmFtZVRvQ29uc3VtZShlLHQscixhKXtpZighZSlyZXR1cm4gbnVsbDtsZXQgbixpO2ZvcihsZXQgYT0wO2E8MzthKyspe249cltvc10oZSwhMSwhMCk7Zm9yKDs7KXtpPW4ubmV4dCgpLnZhbHVlO2lmKCFpKWJyZWFrO2lmKHQ9PT1pW1NzXSgpKXJldHVybiBpfWlmKHJbT3NdPT09ZW8uZGF0YXNldHMuaWQmJiJkYXRhIj09PXJbTXNdKWJyZWFrO3I9cltkc10oKX1pZighYSlyZXR1cm4gbnVsbDtuPXRoaXMuZGF0YVtvc10oZSwhMCwhMSk7aT1uLm5leHQoKS52YWx1ZTtpZihpKXJldHVybiBpO249dGhpcy5kYXRhW1FpXShlLCEwKTtpPW4ubmV4dCgpLnZhbHVlO3JldHVybiBpPy5bU3NdKCk/aTpudWxsfV9zZXRQcm9wZXJ0aWVzKGUsdCl7aWYoZS5oYXNPd25Qcm9wZXJ0eSgic2V0UHJvcGVydHkiKSlmb3IoY29uc3R7cmVmOnIsdGFyZ2V0OmEsY29ubmVjdGlvbjpufW9mIGUuc2V0UHJvcGVydHkuY2hpbGRyZW4pe2lmKG4pY29udGludWU7aWYoIXIpY29udGludWU7Y29uc3QgaT1zZWFyY2hOb2RlKHRoaXMucm9vdCx0LHIsITEsITEpO2lmKCFpKXt3YXJuKGBYRkEgLSBJbnZhbGlkIHJlZmVyZW5jZTogJHtyfS5gKTtjb250aW51ZX1jb25zdFtzXT1pO2lmKCFzW0FzXSh0aGlzLmRhdGEpKXt3YXJuKCJYRkEgLSBJbnZhbGlkIG5vZGU6IG11c3QgYmUgYSBkYXRhIG5vZGUuIik7Y29udGludWV9Y29uc3Qgbz1zZWFyY2hOb2RlKHRoaXMucm9vdCxlLGEsITEsITEpO2lmKCFvKXt3YXJuKGBYRkEgLSBJbnZhbGlkIHRhcmdldDogJHthfS5gKTtjb250aW51ZX1jb25zdFtjXT1vO2lmKCFjW0FzXShlKSl7d2FybigiWEZBIC0gSW52YWxpZCB0YXJnZXQ6IG11c3QgYmUgYSBwcm9wZXJ0eSBvciBzdWJwcm9wZXJ0eS4iKTtjb250aW51ZX1jb25zdCBsPWNbZHNdKCk7aWYoYyBpbnN0YW5jZW9mIFNldFByb3BlcnR5fHxsIGluc3RhbmNlb2YgU2V0UHJvcGVydHkpe3dhcm4oIlhGQSAtIEludmFsaWQgdGFyZ2V0OiBjYW5ub3QgYmUgYSBzZXRQcm9wZXJ0eSBvciBvbmUgb2YgaXRzIHByb3BlcnRpZXMuIik7Y29udGludWV9aWYoYyBpbnN0YW5jZW9mIEJpbmRJdGVtc3x8bCBpbnN0YW5jZW9mIEJpbmRJdGVtcyl7d2FybigiWEZBIC0gSW52YWxpZCB0YXJnZXQ6IGNhbm5vdCBiZSBhIGJpbmRJdGVtcyBvciBvbmUgb2YgaXRzIHByb3BlcnRpZXMuIik7Y29udGludWV9Y29uc3QgaD1zWyRzXSgpLHU9Y1tNc107aWYoYyBpbnN0YW5jZW9mIFhGQUF0dHJpYnV0ZSl7Y29uc3QgZT1PYmplY3QuY3JlYXRlKG51bGwpO2VbdV09aDtjb25zdCB0PVJlZmxlY3QuY29uc3RydWN0KE9iamVjdC5nZXRQcm90b3R5cGVPZihsKS5jb25zdHJ1Y3RvcixbZV0pO2xbdV09dFt1XTtjb250aW51ZX1pZihjLmhhc093blByb3BlcnR5KCRpKSl7Y1tWaV09cztjWyRpXT1oO2NbWWldKCl9ZWxzZSB3YXJuKCJYRkEgLSBJbnZhbGlkIG5vZGUgdG8gdXNlIGluIHNldFByb3BlcnR5Iil9fV9iaW5kSXRlbXMoZSx0KXtpZighZS5oYXNPd25Qcm9wZXJ0eSgiaXRlbXMiKXx8IWUuaGFzT3duUHJvcGVydHkoImJpbmRJdGVtcyIpfHxlLmJpbmRJdGVtcy5pc0VtcHR5KCkpcmV0dXJuO2Zvcihjb25zdCB0IG9mIGUuaXRlbXMuY2hpbGRyZW4pZVtqc10odCk7ZS5pdGVtcy5jbGVhcigpO2NvbnN0IHI9bmV3IEl0ZW1zKHt9KSxhPW5ldyBJdGVtcyh7fSk7ZVtqaV0ocik7ZS5pdGVtcy5wdXNoKHIpO2VbamldKGEpO2UuaXRlbXMucHVzaChhKTtmb3IoY29uc3R7cmVmOm4sbGFiZWxSZWY6aSx2YWx1ZVJlZjpzLGNvbm5lY3Rpb246b31vZiBlLmJpbmRJdGVtcy5jaGlsZHJlbil7aWYobyljb250aW51ZTtpZighbiljb250aW51ZTtjb25zdCBlPXNlYXJjaE5vZGUodGhpcy5yb290LHQsbiwhMSwhMSk7aWYoZSlmb3IoY29uc3QgdCBvZiBlKXtpZighdFtBc10odGhpcy5kYXRhc2V0cykpe3dhcm4oYFhGQSAtIEludmFsaWQgcmVmICgke259KTogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLmApO2NvbnRpbnVlfWNvbnN0IGU9c2VhcmNoTm9kZSh0aGlzLnJvb3QsdCxpLCEwLCExKTtpZighZSl7d2FybihgWEZBIC0gSW52YWxpZCBsYWJlbDogJHtpfS5gKTtjb250aW51ZX1jb25zdFtvXT1lO2lmKCFvW0FzXSh0aGlzLmRhdGFzZXRzKSl7d2FybigiWEZBIC0gSW52YWxpZCBsYWJlbDogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLiIpO2NvbnRpbnVlfWNvbnN0IGM9c2VhcmNoTm9kZSh0aGlzLnJvb3QsdCxzLCEwLCExKTtpZighYyl7d2FybihgWEZBIC0gSW52YWxpZCB2YWx1ZTogJHtzfS5gKTtjb250aW51ZX1jb25zdFtsXT1jO2lmKCFsW0FzXSh0aGlzLmRhdGFzZXRzKSl7d2FybigiWEZBIC0gSW52YWxpZCB2YWx1ZTogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLiIpO2NvbnRpbnVlfWNvbnN0IGg9Y3JlYXRlVGV4dChvWyRzXSgpKSx1PWNyZWF0ZVRleHQobFskc10oKSk7cltqaV0oaCk7ci50ZXh0LnB1c2goaCk7YVtqaV0odSk7YS50ZXh0LnB1c2godSl9ZWxzZSB3YXJuKGBYRkEgLSBJbnZhbGlkIHJlZmVyZW5jZTogJHtufS5gKX19X2JpbmRPY2N1cnJlbmNlcyhlLHQscil7bGV0IGE7aWYodC5sZW5ndGg+MSl7YT1lW3ppXSgpO2FbanNdKGEub2NjdXIpO2Eub2NjdXI9bnVsbH10aGlzLl9iaW5kVmFsdWUoZSx0WzBdLHIpO3RoaXMuX3NldFByb3BlcnRpZXMoZSx0WzBdKTt0aGlzLl9iaW5kSXRlbXMoZSx0WzBdKTtpZigxPT09dC5sZW5ndGgpcmV0dXJuO2NvbnN0IG49ZVtkc10oKSxpPWVbTXNdLHM9bltic10oZSk7Zm9yKGxldCBlPTEsbz10Lmxlbmd0aDtlPG87ZSsrKXtjb25zdCBvPXRbZV0sYz1hW3ppXSgpO25baV0ucHVzaChjKTtuW3lzXShzK2UsYyk7dGhpcy5fYmluZFZhbHVlKGMsbyxyKTt0aGlzLl9zZXRQcm9wZXJ0aWVzKGMsbyk7dGhpcy5fYmluZEl0ZW1zKGMsbyl9fV9jcmVhdGVPY2N1cnJlbmNlcyhlKXtpZighdGhpcy5lbXB0eU1lcmdlKXJldHVybjtjb25zdHtvY2N1cjp0fT1lO2lmKCF0fHx0LmluaXRpYWw8PTEpcmV0dXJuO2NvbnN0IHI9ZVtkc10oKSxhPWVbTXNdO2lmKCEoclthXWluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkpKXJldHVybjtsZXQgbjtuPWUubmFtZT9yW2FdLmNoaWxkcmVuLmZpbHRlcih0PT50Lm5hbWU9PT1lLm5hbWUpLmxlbmd0aDpyW2FdLmNoaWxkcmVuLmxlbmd0aDtjb25zdCBpPXJbYnNdKGUpKzEscz10LmluaXRpYWwtbjtpZihzKXtjb25zdCB0PWVbemldKCk7dFtqc10odC5vY2N1cik7dC5vY2N1cj1udWxsO3JbYV0ucHVzaCh0KTtyW3lzXShpLHQpO2ZvcihsZXQgZT0xO2U8cztlKyspe2NvbnN0IG49dFt6aV0oKTtyW2FdLnB1c2gobik7clt5c10oaStlLG4pfX19X2dldE9jY3VySW5mbyhlKXtjb25zdHtuYW1lOnQsb2NjdXI6cn09ZTtpZighcnx8IXQpcmV0dXJuWzEsMV07Y29uc3QgYT0tMT09PXIubWF4PzEvMDpyLm1heDtyZXR1cm5bci5taW4sYV19X3NldEFuZEJpbmQoZSx0KXt0aGlzLl9zZXRQcm9wZXJ0aWVzKGUsdCk7dGhpcy5fYmluZEl0ZW1zKGUsdCk7dGhpcy5fYmluZEVsZW1lbnQoZSx0KX1fYmluZEVsZW1lbnQoZSx0KXtjb25zdCByPVtdO3RoaXMuX2NyZWF0ZU9jY3VycmVuY2VzKGUpO2Zvcihjb25zdCBhIG9mIGVbY3NdKCkpe2lmKGFbVmldKWNvbnRpbnVlO2lmKHZvaWQgMD09PXRoaXMuX21lcmdlTW9kZSYmInN1YmZvcm0iPT09YVtNc10pe3RoaXMuX21lcmdlTW9kZT0iY29uc3VtZURhdGEiPT09YS5tZXJnZU1vZGU7Y29uc3QgZT10W2NzXSgpO2lmKGUubGVuZ3RoPjApdGhpcy5fYmluZE9jY3VycmVuY2VzKGEsW2VbMF1dLG51bGwpO2Vsc2UgaWYodGhpcy5lbXB0eU1lcmdlKXtjb25zdCBlPXRbT3NdPT09am8/LTE6dFtPc10scj1hW1ZpXT1uZXcgWG1sT2JqZWN0KGUsYS5uYW1lfHwicm9vdCIpO3RbamldKHIpO3RoaXMuX2JpbmRFbGVtZW50KGEscil9Y29udGludWV9aWYoIWFbeHNdKCkpY29udGludWU7bGV0IGU9ITEsbj1udWxsLGk9bnVsbCxzPW51bGw7aWYoYS5iaW5kKXtzd2l0Y2goYS5iaW5kLm1hdGNoKXtjYXNlIm5vbmUiOnRoaXMuX3NldEFuZEJpbmQoYSx0KTtjb250aW51ZTtjYXNlImdsb2JhbCI6ZT0hMDticmVhaztjYXNlImRhdGFSZWYiOmlmKCFhLmJpbmQucmVmKXt3YXJuKGBYRkEgLSByZWYgaXMgZW1wdHkgaW4gbm9kZSAke2FbTXNdfS5gKTt0aGlzLl9zZXRBbmRCaW5kKGEsdCk7Y29udGludWV9aT1hLmJpbmQucmVmfWEuYmluZC5waWN0dXJlJiYobj1hLmJpbmQucGljdHVyZVskaV0pfWNvbnN0W28sY109dGhpcy5fZ2V0T2NjdXJJbmZvKGEpO2lmKGkpe3M9c2VhcmNoTm9kZSh0aGlzLnJvb3QsdCxpLCEwLCExKTtpZihudWxsPT09cyl7cz1jcmVhdGVEYXRhTm9kZSh0aGlzLmRhdGEsdCxpKTtpZighcyljb250aW51ZTt0aGlzLl9pc0NvbnN1bWVEYXRhKCkmJihzW0dpXT0hMCk7dGhpcy5fc2V0QW5kQmluZChhLHMpO2NvbnRpbnVlfXRoaXMuX2lzQ29uc3VtZURhdGEoKSYmKHM9cy5maWx0ZXIoZT0+IWVbR2ldKSk7cy5sZW5ndGg+Yz9zPXMuc2xpY2UoMCxjKTowPT09cy5sZW5ndGgmJihzPW51bGwpO3MmJnRoaXMuX2lzQ29uc3VtZURhdGEoKSYmcy5mb3JFYWNoKGU9PntlW0dpXT0hMH0pfWVsc2V7aWYoIWEubmFtZSl7dGhpcy5fc2V0QW5kQmluZChhLHQpO2NvbnRpbnVlfWlmKHRoaXMuX2lzQ29uc3VtZURhdGEoKSl7Y29uc3Qgcj1bXTtmb3IoO3IubGVuZ3RoPGM7KXtjb25zdCBuPXRoaXMuX2ZpbmREYXRhQnlOYW1lVG9Db25zdW1lKGEubmFtZSxhW3BzXSgpLHQsZSk7aWYoIW4pYnJlYWs7bltHaV09ITA7ci5wdXNoKG4pfXM9ci5sZW5ndGg+MD9yOm51bGx9ZWxzZXtzPXRbb3NdKGEubmFtZSwhMSx0aGlzLmVtcHR5TWVyZ2UpLm5leHQoKS52YWx1ZTtpZighcyl7aWYoMD09PW8pe3IucHVzaChhKTtjb250aW51ZX1jb25zdCBlPXRbT3NdPT09am8/LTE6dFtPc107cz1hW1ZpXT1uZXcgWG1sT2JqZWN0KGUsYS5uYW1lKTt0aGlzLmVtcHR5TWVyZ2UmJihzW0dpXT0hMCk7dFtqaV0ocyk7dGhpcy5fc2V0QW5kQmluZChhLHMpO2NvbnRpbnVlfXRoaXMuZW1wdHlNZXJnZSYmKHNbR2ldPSEwKTtzPVtzXX19cz90aGlzLl9iaW5kT2NjdXJyZW5jZXMoYSxzLG4pOm8+MD90aGlzLl9zZXRBbmRCaW5kKGEsdCk6ci5wdXNoKGEpfXIuZm9yRWFjaChlPT5lW2RzXSgpW2pzXShlKSl9fWNsYXNzIERhdGFIYW5kbGVye2NvbnN0cnVjdG9yKGUsdCl7dGhpcy5kYXRhPXQ7dGhpcy5kYXRhc2V0PWUuZGF0YXNldHN8fG51bGx9c2VyaWFsaXplKGUpe2NvbnN0IHQ9W1stMSx0aGlzLmRhdGFbY3NdKCldXTtmb3IoO3QubGVuZ3RoPjA7KXtjb25zdCByPXQuYXQoLTEpLFthLG5dPXI7aWYoYSsxPT09bi5sZW5ndGgpe3QucG9wKCk7Y29udGludWV9Y29uc3QgaT1uWysrclswXV0scz1lLmdldChpW1pzXSk7aWYocylpW3pzXShzKTtlbHNle2NvbnN0IHQ9aVtlc10oKTtmb3IoY29uc3QgciBvZiB0LnZhbHVlcygpKXtjb25zdCB0PWUuZ2V0KHJbWnNdKTtpZih0KXtyW3pzXSh0KTticmVha319fWNvbnN0IG89aVtjc10oKTtvLmxlbmd0aD4wJiZ0LnB1c2goWy0xLG9dKX1jb25zdCByPVsnPHhmYTpkYXRhc2V0cyB4bWxuczp4ZmE9Imh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWRhdGEvMS4wLyI+J107aWYodGhpcy5kYXRhc2V0KWZvcihjb25zdCBlIG9mIHRoaXMuZGF0YXNldFtjc10oKSkiZGF0YSIhPT1lW01zXSYmZVtKc10ocik7dGhpcy5kYXRhW0pzXShyKTtyLnB1c2goIjwveGZhOmRhdGFzZXRzPiIpO3JldHVybiByLmpvaW4oIiIpfX1jb25zdCBVbz1lby5jb25maWcuaWQ7Y2xhc3MgQWNyb2JhdCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYWNyb2JhdCIsITApO3RoaXMuYWNyb2JhdDc9bnVsbDt0aGlzLmF1dG9TYXZlPW51bGw7dGhpcy5jb21tb249bnVsbDt0aGlzLnZhbGlkYXRlPW51bGw7dGhpcy52YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcz1udWxsO3RoaXMuc3VibWl0VXJsPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgQWNyb2JhdDcgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImFjcm9iYXQ3IiwhMCk7dGhpcy5keW5hbWljUmVuZGVyPW51bGx9fWNsYXNzIEFEQkVfSlNDb25zb2xlIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJBREJFX0pTQ29uc29sZSIsWyJkZWxlZ2F0ZSIsIkVuYWJsZSIsIkRpc2FibGUiXSl9fWNsYXNzIEFEQkVfSlNEZWJ1Z2dlciBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiQURCRV9KU0RlYnVnZ2VyIixbImRlbGVnYXRlIiwiRW5hYmxlIiwiRGlzYWJsZSJdKX19Y2xhc3MgQWRkU2lsZW50UHJpbnQgZXh0ZW5kcyBPcHRpb24wMXtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYWRkU2lsZW50UHJpbnQiKX19Y2xhc3MgQWRkVmlld2VyUHJlZmVyZW5jZXMgZXh0ZW5kcyBPcHRpb24wMXtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYWRkVmlld2VyUHJlZmVyZW5jZXMiKX19Y2xhc3MgQWRqdXN0RGF0YSBleHRlbmRzIE9wdGlvbjEwe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJhZGp1c3REYXRhIil9fWNsYXNzIEFkb2JlRXh0ZW5zaW9uTGV2ZWwgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJhZG9iZUV4dGVuc2lvbkxldmVsIiwwLGU9PmU+PTEmJmU8PTgpfX1jbGFzcyBBZ2VudCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYWdlbnQiLCEwKTt0aGlzLm5hbWU9ZS5uYW1lP2UubmFtZS50cmltKCk6IiI7dGhpcy5jb21tb249bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBBbHdheXNFbWJlZCBleHRlbmRzIENvbnRlbnRPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImFsd2F5c0VtYmVkIil9fWNsYXNzIEFtZCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYW1kIil9fWNsYXNzIGNvbmZpZ19BcmVhIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJhcmVhIik7dGhpcy5sZXZlbD1nZXRJbnRlZ2VyKHtkYXRhOmUubGV2ZWwsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+ZT49MSYmZTw9M30pO3RoaXMubmFtZT1nZXRTdHJpbmdPcHRpb24oZS5uYW1lLFsiIiwiYmFyY29kZSIsImNvcmVpbml0IiwiZGV2aWNlRHJpdmVyIiwiZm9udCIsImdlbmVyYWwiLCJsYXlvdXQiLCJtZXJnZSIsInNjcmlwdCIsInNpZ25hdHVyZSIsInNvdXJjZVNldCIsInRlbXBsYXRlQ2FjaGUiXSl9fWNsYXNzIEF0dHJpYnV0ZXMgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImF0dHJpYnV0ZXMiLFsicHJlc2VydmUiLCJkZWxlZ2F0ZSIsImlnbm9yZSJdKX19Y2xhc3MgQXV0b1NhdmUgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImF1dG9TYXZlIixbImRpc2FibGVkIiwiZW5hYmxlZCJdKX19Y2xhc3MgQmFzZSBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYmFzZSIpfX1jbGFzcyBCYXRjaE91dHB1dCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiYmF0Y2hPdXRwdXQiKTt0aGlzLmZvcm1hdD1nZXRTdHJpbmdPcHRpb24oZS5mb3JtYXQsWyJub25lIiwiY29uY2F0IiwiemlwIiwiemlwQ29tcHJlc3MiXSl9fWNsYXNzIEJlaGF2aW9yT3ZlcnJpZGUgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJiZWhhdmlvck92ZXJyaWRlIil9W1lpXSgpe3RoaXNbJGldPW5ldyBNYXAodGhpc1skaV0udHJpbSgpLnNwbGl0KC9ccysvKS5maWx0ZXIoZT0+ZS5pbmNsdWRlcygiOiIpKS5tYXAoZT0+ZS5zcGxpdCgiOiIsMikpKX19Y2xhc3MgQ2FjaGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImNhY2hlIiwhMCk7dGhpcy50ZW1wbGF0ZUNhY2hlPW51bGx9fWNsYXNzIENoYW5nZSBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJjaGFuZ2UiKX19Y2xhc3MgQ29tbW9uIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJjb21tb24iLCEwKTt0aGlzLmRhdGE9bnVsbDt0aGlzLmxvY2FsZT1udWxsO3RoaXMubG9jYWxlU2V0PW51bGw7dGhpcy5tZXNzYWdpbmc9bnVsbDt0aGlzLnN1cHByZXNzQmFubmVyPW51bGw7dGhpcy50ZW1wbGF0ZT1udWxsO3RoaXMudmFsaWRhdGlvbk1lc3NhZ2luZz1udWxsO3RoaXMudmVyc2lvbkNvbnRyb2w9bnVsbDt0aGlzLmxvZz1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIENvbXByZXNzIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJjb21wcmVzcyIpO3RoaXMuc2NvcGU9Z2V0U3RyaW5nT3B0aW9uKGUuc2NvcGUsWyJpbWFnZU9ubHkiLCJkb2N1bWVudCJdKX19Y2xhc3MgQ29tcHJlc3NMb2dpY2FsU3RydWN0dXJlIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImNvbXByZXNzTG9naWNhbFN0cnVjdHVyZSIpfX1jbGFzcyBDb21wcmVzc09iamVjdFN0cmVhbSBleHRlbmRzIE9wdGlvbjEwe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJjb21wcmVzc09iamVjdFN0cmVhbSIpfX1jbGFzcyBDb21wcmVzc2lvbiBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiY29tcHJlc3Npb24iLCEwKTt0aGlzLmNvbXByZXNzTG9naWNhbFN0cnVjdHVyZT1udWxsO3RoaXMuY29tcHJlc3NPYmplY3RTdHJlYW09bnVsbDt0aGlzLmxldmVsPW51bGw7dGhpcy50eXBlPW51bGx9fWNsYXNzIENvbmZpZyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiY29uZmlnIiwhMCk7dGhpcy5hY3JvYmF0PW51bGw7dGhpcy5wcmVzZW50PW51bGw7dGhpcy50cmFjZT1udWxsO3RoaXMuYWdlbnQ9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBDb25mb3JtYW5jZSBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiY29uZm9ybWFuY2UiLFsiQSIsIkIiXSl9fWNsYXNzIENvbnRlbnRDb3B5IGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImNvbnRlbnRDb3B5Iil9fWNsYXNzIENvcGllcyBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImNvcGllcyIsMSxlPT5lPj0xKX19Y2xhc3MgQ3JlYXRvciBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiY3JlYXRvciIpfX1jbGFzcyBDdXJyZW50UGFnZSBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImN1cnJlbnRQYWdlIiwwLGU9PmU+PTApfX1jbGFzcyBEYXRhIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJkYXRhIiwhMCk7dGhpcy5hZGp1c3REYXRhPW51bGw7dGhpcy5hdHRyaWJ1dGVzPW51bGw7dGhpcy5pbmNyZW1lbnRhbExvYWQ9bnVsbDt0aGlzLm91dHB1dFhTTD1udWxsO3RoaXMucmFuZ2U9bnVsbDt0aGlzLnJlY29yZD1udWxsO3RoaXMuc3RhcnROb2RlPW51bGw7dGhpcy51cmk9bnVsbDt0aGlzLndpbmRvdz1udWxsO3RoaXMueHNsPW51bGw7dGhpcy5leGNsdWRlTlM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMudHJhbnNmb3JtPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgRGVidWcgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImRlYnVnIiwhMCk7dGhpcy51cmk9bnVsbH19Y2xhc3MgRGVmYXVsdFR5cGVmYWNlIGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZGVmYXVsdFR5cGVmYWNlIik7dGhpcy53cml0aW5nU2NyaXB0PWdldFN0cmluZ09wdGlvbihlLndyaXRpbmdTY3JpcHQsWyIqIiwiQXJhYmljIiwiQ3lyaWxsaWMiLCJFYXN0RXVyb3BlYW5Sb21hbiIsIkdyZWVrIiwiSGVicmV3IiwiSmFwYW5lc2UiLCJLb3JlYW4iLCJSb21hbiIsIlNpbXBsaWZpZWRDaGluZXNlIiwiVGhhaSIsIlRyYWRpdGlvbmFsQ2hpbmVzZSIsIlZpZXRuYW1lc2UiXSl9fWNsYXNzIERlc3RpbmF0aW9uIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJkZXN0aW5hdGlvbiIsWyJwZGYiLCJwY2wiLCJwcyIsIndlYkNsaWVudCIsInpwbCJdKX19Y2xhc3MgRG9jdW1lbnRBc3NlbWJseSBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJkb2N1bWVudEFzc2VtYmx5Iil9fWNsYXNzIERyaXZlciBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZHJpdmVyIiwhMCk7dGhpcy5uYW1lPWUubmFtZT9lLm5hbWUudHJpbSgpOiIiO3RoaXMuZm9udEluZm89bnVsbDt0aGlzLnhkYz1udWxsfX1jbGFzcyBEdXBsZXhPcHRpb24gZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImR1cGxleE9wdGlvbiIsWyJzaW1wbGV4IiwiZHVwbGV4RmxpcExvbmdFZGdlIiwiZHVwbGV4RmxpcFNob3J0RWRnZSJdKX19Y2xhc3MgRHluYW1pY1JlbmRlciBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZHluYW1pY1JlbmRlciIsWyJmb3JiaWRkZW4iLCJyZXF1aXJlZCJdKX19Y2xhc3MgRW1iZWQgZXh0ZW5kcyBPcHRpb24wMXtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZW1iZWQiKX19Y2xhc3MgY29uZmlnX0VuY3J5cHQgZXh0ZW5kcyBPcHRpb24wMXtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZW5jcnlwdCIpfX1jbGFzcyBjb25maWdfRW5jcnlwdGlvbiBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZW5jcnlwdGlvbiIsITApO3RoaXMuZW5jcnlwdD1udWxsO3RoaXMuZW5jcnlwdGlvbkxldmVsPW51bGw7dGhpcy5wZXJtaXNzaW9ucz1udWxsfX1jbGFzcyBFbmNyeXB0aW9uTGV2ZWwgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImVuY3J5cHRpb25MZXZlbCIsWyI0MGJpdCIsIjEyOGJpdCJdKX19Y2xhc3MgRW5mb3JjZSBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiZW5mb3JjZSIpfX1jbGFzcyBFcXVhdGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImVxdWF0ZSIpO3RoaXMuZm9yY2U9Z2V0SW50ZWdlcih7ZGF0YTplLmZvcmNlLGRlZmF1bHRWYWx1ZToxLHZhbGlkYXRlOmU9PjA9PT1lfSk7dGhpcy5mcm9tPWUuZnJvbXx8IiI7dGhpcy50bz1lLnRvfHwiIn19Y2xhc3MgRXF1YXRlUmFuZ2UgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImVxdWF0ZVJhbmdlIik7dGhpcy5mcm9tPWUuZnJvbXx8IiI7dGhpcy50bz1lLnRvfHwiIjt0aGlzLl91bmljb2RlUmFuZ2U9ZS51bmljb2RlUmFuZ2V8fCIifWdldCB1bmljb2RlUmFuZ2UoKXtjb25zdCBlPVtdLHQ9L1VcKyhbMC05YS1mQS1GXSspLyxyPXRoaXMuX3VuaWNvZGVSYW5nZTtmb3IobGV0IGEgb2Ygci5zcGxpdCgiLCIpLm1hcChlPT5lLnRyaW0oKSkuZmlsdGVyKGU9PiEhZSkpe2E9YS5zcGxpdCgiLSIsMikubWFwKGU9Pntjb25zdCByPWUubWF0Y2godCk7cmV0dXJuIHI/cGFyc2VJbnQoclsxXSwxNik6MH0pOzE9PT1hLmxlbmd0aCYmYS5wdXNoKGFbMF0pO2UucHVzaChhKX1yZXR1cm4gc2hhZG93KHRoaXMsInVuaWNvZGVSYW5nZSIsZSl9fWNsYXNzIEV4Y2x1ZGUgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJleGNsdWRlIil9W1lpXSgpe3RoaXNbJGldPXRoaXNbJGldLnRyaW0oKS5zcGxpdCgvXHMrLykuZmlsdGVyKGU9PmUmJlsiY2FsY3VsYXRlIiwiY2xvc2UiLCJlbnRlciIsImV4aXQiLCJpbml0aWFsaXplIiwicmVhZHkiLCJ2YWxpZGF0ZSJdLmluY2x1ZGVzKGUpKX19Y2xhc3MgRXhjbHVkZU5TIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJleGNsdWRlTlMiKX19Y2xhc3MgRmxpcExhYmVsIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJmbGlwTGFiZWwiLFsidXNlUHJpbnRlclNldHRpbmciLCJvbiIsIm9mZiJdKX19Y2xhc3MgY29uZmlnX0ZvbnRJbmZvIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJmb250SW5mbyIsITApO3RoaXMuZW1iZWQ9bnVsbDt0aGlzLm1hcD1udWxsO3RoaXMuc3Vic2V0QmVsb3c9bnVsbDt0aGlzLmFsd2F5c0VtYmVkPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmRlZmF1bHRUeXBlZmFjZT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5uZXZlckVtYmVkPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgRm9ybUZpZWxkRmlsbGluZyBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJmb3JtRmllbGRGaWxsaW5nIil9fWNsYXNzIEdyb3VwUGFyZW50IGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJncm91cFBhcmVudCIpfX1jbGFzcyBJZkVtcHR5IGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJpZkVtcHR5IixbImRhdGFWYWx1ZSIsImRhdGFHcm91cCIsImlnbm9yZSIsInJlbW92ZSJdKX19Y2xhc3MgSW5jbHVkZVhEUENvbnRlbnQgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImluY2x1ZGVYRFBDb250ZW50Iil9fWNsYXNzIEluY3JlbWVudGFsTG9hZCBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiaW5jcmVtZW50YWxMb2FkIixbIm5vbmUiLCJmb3J3YXJkT25seSJdKX19Y2xhc3MgSW5jcmVtZW50YWxNZXJnZSBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJpbmNyZW1lbnRhbE1lcmdlIil9fWNsYXNzIEludGVyYWN0aXZlIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImludGVyYWN0aXZlIil9fWNsYXNzIEpvZyBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiam9nIixbInVzZVByaW50ZXJTZXR0aW5nIiwibm9uZSIsInBhZ2VTZXQiXSl9fWNsYXNzIExhYmVsUHJpbnRlciBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywibGFiZWxQcmludGVyIiwhMCk7dGhpcy5uYW1lPWdldFN0cmluZ09wdGlvbihlLm5hbWUsWyJ6cGwiLCJkcGwiLCJpcGwiLCJ0Y3BsIl0pO3RoaXMuYmF0Y2hPdXRwdXQ9bnVsbDt0aGlzLmZsaXBMYWJlbD1udWxsO3RoaXMuZm9udEluZm89bnVsbDt0aGlzLnhkYz1udWxsfX1jbGFzcyBMYXlvdXQgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImxheW91dCIsWyJwYWdpbmF0ZSIsInBhbmVsIl0pfX1jbGFzcyBMZXZlbCBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImxldmVsIiwwLGU9PmU+MCl9fWNsYXNzIExpbmVhcml6ZWQgZXh0ZW5kcyBPcHRpb24wMXtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywibGluZWFyaXplZCIpfX1jbGFzcyBMb2NhbGUgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImxvY2FsZSIpfX1jbGFzcyBMb2NhbGVTZXQgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImxvY2FsZVNldCIpfX1jbGFzcyBMb2cgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sImxvZyIsITApO3RoaXMubW9kZT1udWxsO3RoaXMudGhyZXNob2xkPW51bGw7dGhpcy50bz1udWxsO3RoaXMudXJpPW51bGx9fWNsYXNzIE1hcEVsZW1lbnQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIm1hcCIsITApO3RoaXMuZXF1YXRlPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLmVxdWF0ZVJhbmdlPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgTWVkaXVtSW5mbyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywibWVkaXVtSW5mbyIsITApO3RoaXMubWFwPW51bGx9fWNsYXNzIGNvbmZpZ19NZXNzYWdlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJtZXNzYWdlIiwhMCk7dGhpcy5tc2dJZD1udWxsO3RoaXMuc2V2ZXJpdHk9bnVsbH19Y2xhc3MgTWVzc2FnaW5nIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJtZXNzYWdpbmciLCEwKTt0aGlzLm1lc3NhZ2U9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBNb2RlIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJtb2RlIixbImFwcGVuZCIsIm92ZXJ3cml0ZSJdKX19Y2xhc3MgTW9kaWZ5QW5ub3RzIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIm1vZGlmeUFubm90cyIpfX1jbGFzcyBNc2dJZCBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIm1zZ0lkIiwxLGU9PmU+PTEpfX1jbGFzcyBOYW1lQXR0ciBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywibmFtZUF0dHIiKX19Y2xhc3MgTmV2ZXJFbWJlZCBleHRlbmRzIENvbnRlbnRPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIm5ldmVyRW1iZWQiKX19Y2xhc3MgTnVtYmVyT2ZDb3BpZXMgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJudW1iZXJPZkNvcGllcyIsbnVsbCxlPT5lPj0yJiZlPD01KX19Y2xhc3MgT3BlbkFjdGlvbiBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywib3BlbkFjdGlvbiIsITApO3RoaXMuZGVzdGluYXRpb249bnVsbH19Y2xhc3MgT3V0cHV0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJvdXRwdXQiLCEwKTt0aGlzLnRvPW51bGw7dGhpcy50eXBlPW51bGw7dGhpcy51cmk9bnVsbH19Y2xhc3MgT3V0cHV0QmluIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJvdXRwdXRCaW4iKX19Y2xhc3MgT3V0cHV0WFNMIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJvdXRwdXRYU0wiLCEwKTt0aGlzLnVyaT1udWxsfX1jbGFzcyBPdmVycHJpbnQgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIm92ZXJwcmludCIsWyJub25lIiwiYm90aCIsImRyYXciLCJmaWVsZCJdKX19Y2xhc3MgUGFja2V0cyBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicGFja2V0cyIpfVtZaV0oKXsiKiIhPT10aGlzWyRpXSYmKHRoaXNbJGldPXRoaXNbJGldLnRyaW0oKS5zcGxpdCgvXHMrLykuZmlsdGVyKGU9PlsiY29uZmlnIiwiZGF0YXNldHMiLCJ0ZW1wbGF0ZSIsInhmZGYiLCJ4c2x0Il0uaW5jbHVkZXMoZSkpKX19Y2xhc3MgUGFnZU9mZnNldCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicGFnZU9mZnNldCIpO3RoaXMueD1nZXRJbnRlZ2VyKHtkYXRhOmUueCxkZWZhdWx0VmFsdWU6InVzZVhEQ1NldHRpbmciLHZhbGlkYXRlOmU9PiEwfSk7dGhpcy55PWdldEludGVnZXIoe2RhdGE6ZS55LGRlZmF1bHRWYWx1ZToidXNlWERDU2V0dGluZyIsdmFsaWRhdGU6ZT0+ITB9KX19Y2xhc3MgUGFnZVJhbmdlIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwYWdlUmFuZ2UiKX1bWWldKCl7Y29uc3QgZT10aGlzWyRpXS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcChlPT5wYXJzZUludChlLDEwKSksdD1bXTtmb3IobGV0IHI9MCxhPWUubGVuZ3RoO3I8YTtyKz0yKXQucHVzaChlLnNsaWNlKHIscisyKSk7dGhpc1skaV09dH19Y2xhc3MgUGFnaW5hdGlvbiBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicGFnaW5hdGlvbiIsWyJzaW1wbGV4IiwiZHVwbGV4U2hvcnRFZGdlIiwiZHVwbGV4TG9uZ0VkZ2UiXSl9fWNsYXNzIFBhZ2luYXRpb25PdmVycmlkZSBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicGFnaW5hdGlvbk92ZXJyaWRlIixbIm5vbmUiLCJmb3JjZUR1cGxleCIsImZvcmNlRHVwbGV4TG9uZ0VkZ2UiLCJmb3JjZUR1cGxleFNob3J0RWRnZSIsImZvcmNlU2ltcGxleCJdKX19Y2xhc3MgUGFydCBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInBhcnQiLDEsZT0+ITEpfX1jbGFzcyBQY2wgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInBjbCIsITApO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMuYmF0Y2hPdXRwdXQ9bnVsbDt0aGlzLmZvbnRJbmZvPW51bGw7dGhpcy5qb2c9bnVsbDt0aGlzLm1lZGl1bUluZm89bnVsbDt0aGlzLm91dHB1dEJpbj1udWxsO3RoaXMucGFnZU9mZnNldD1udWxsO3RoaXMuc3RhcGxlPW51bGw7dGhpcy54ZGM9bnVsbH19Y2xhc3MgUGRmIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwZGYiLCEwKTt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLmFkb2JlRXh0ZW5zaW9uTGV2ZWw9bnVsbDt0aGlzLmJhdGNoT3V0cHV0PW51bGw7dGhpcy5jb21wcmVzc2lvbj1udWxsO3RoaXMuY3JlYXRvcj1udWxsO3RoaXMuZW5jcnlwdGlvbj1udWxsO3RoaXMuZm9udEluZm89bnVsbDt0aGlzLmludGVyYWN0aXZlPW51bGw7dGhpcy5saW5lYXJpemVkPW51bGw7dGhpcy5vcGVuQWN0aW9uPW51bGw7dGhpcy5wZGZhPW51bGw7dGhpcy5wcm9kdWNlcj1udWxsO3RoaXMucmVuZGVyUG9saWN5PW51bGw7dGhpcy5zY3JpcHRNb2RlbD1udWxsO3RoaXMuc2lsZW50UHJpbnQ9bnVsbDt0aGlzLnN1Ym1pdEZvcm1hdD1udWxsO3RoaXMudGFnZ2VkPW51bGw7dGhpcy52ZXJzaW9uPW51bGw7dGhpcy52aWV3ZXJQcmVmZXJlbmNlcz1udWxsO3RoaXMueGRjPW51bGx9fWNsYXNzIFBkZmEgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInBkZmEiLCEwKTt0aGlzLmFtZD1udWxsO3RoaXMuY29uZm9ybWFuY2U9bnVsbDt0aGlzLmluY2x1ZGVYRFBDb250ZW50PW51bGw7dGhpcy5wYXJ0PW51bGx9fWNsYXNzIFBlcm1pc3Npb25zIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwZXJtaXNzaW9ucyIsITApO3RoaXMuYWNjZXNzaWJsZUNvbnRlbnQ9bnVsbDt0aGlzLmNoYW5nZT1udWxsO3RoaXMuY29udGVudENvcHk9bnVsbDt0aGlzLmRvY3VtZW50QXNzZW1ibHk9bnVsbDt0aGlzLmZvcm1GaWVsZEZpbGxpbmc9bnVsbDt0aGlzLm1vZGlmeUFubm90cz1udWxsO3RoaXMucGxhaW50ZXh0TWV0YWRhdGE9bnVsbDt0aGlzLnByaW50PW51bGw7dGhpcy5wcmludEhpZ2hRdWFsaXR5PW51bGx9fWNsYXNzIFBpY2tUcmF5QnlQREZTaXplIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInBpY2tUcmF5QnlQREZTaXplIil9fWNsYXNzIGNvbmZpZ19QaWN0dXJlIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwaWN0dXJlIil9fWNsYXNzIFBsYWludGV4dE1ldGFkYXRhIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInBsYWludGV4dE1ldGFkYXRhIil9fWNsYXNzIFByZXNlbmNlIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwcmVzZW5jZSIsWyJwcmVzZXJ2ZSIsImRpc3NvbHZlIiwiZGlzc29sdmVTdHJ1Y3R1cmUiLCJpZ25vcmUiLCJyZW1vdmUiXSl9fWNsYXNzIFByZXNlbnQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInByZXNlbnQiLCEwKTt0aGlzLmJlaGF2aW9yT3ZlcnJpZGU9bnVsbDt0aGlzLmNhY2hlPW51bGw7dGhpcy5jb21tb249bnVsbDt0aGlzLmNvcGllcz1udWxsO3RoaXMuZGVzdGluYXRpb249bnVsbDt0aGlzLmluY3JlbWVudGFsTWVyZ2U9bnVsbDt0aGlzLmxheW91dD1udWxsO3RoaXMub3V0cHV0PW51bGw7dGhpcy5vdmVycHJpbnQ9bnVsbDt0aGlzLnBhZ2luYXRpb249bnVsbDt0aGlzLnBhZ2luYXRpb25PdmVycmlkZT1udWxsO3RoaXMuc2NyaXB0PW51bGw7dGhpcy52YWxpZGF0ZT1udWxsO3RoaXMueGRwPW51bGw7dGhpcy5kcml2ZXI9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMubGFiZWxQcmludGVyPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnBjbD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy5wZGY9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMucHM9bmV3IFhGQU9iamVjdEFycmF5O3RoaXMuc3VibWl0VXJsPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLndlYkNsaWVudD1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy56cGw9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBQcmludCBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwcmludCIpfX1jbGFzcyBQcmludEhpZ2hRdWFsaXR5IGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInByaW50SGlnaFF1YWxpdHkiKX19Y2xhc3MgUHJpbnRTY2FsaW5nIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwcmludFNjYWxpbmciLFsiYXBwZGVmYXVsdCIsIm5vU2NhbGluZyJdKX19Y2xhc3MgUHJpbnRlck5hbWUgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInByaW50ZXJOYW1lIil9fWNsYXNzIFByb2R1Y2VyIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJwcm9kdWNlciIpfX1jbGFzcyBQcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicHMiLCEwKTt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLmJhdGNoT3V0cHV0PW51bGw7dGhpcy5mb250SW5mbz1udWxsO3RoaXMuam9nPW51bGw7dGhpcy5tZWRpdW1JbmZvPW51bGw7dGhpcy5vdXRwdXRCaW49bnVsbDt0aGlzLnN0YXBsZT1udWxsO3RoaXMueGRjPW51bGx9fWNsYXNzIFJhbmdlIGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicmFuZ2UiKX1bWWldKCl7dGhpc1skaV09dGhpc1skaV0uc3BsaXQoIiwiLDIpLm1hcChlPT5lLnNwbGl0KCItIikubWFwKGU9PnBhcnNlSW50KGUudHJpbSgpLDEwKSkpLmZpbHRlcihlPT5lLmV2ZXJ5KGU9PiFpc05hTihlKSkpLm1hcChlPT57MT09PWUubGVuZ3RoJiZlLnB1c2goZVswXSk7cmV0dXJuIGV9KX19Y2xhc3MgUmVjb3JkIGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywicmVjb3JkIil9W1lpXSgpe3RoaXNbJGldPXRoaXNbJGldLnRyaW0oKTtjb25zdCBlPXBhcnNlSW50KHRoaXNbJGldLDEwKTshaXNOYU4oZSkmJmU+PTAmJih0aGlzWyRpXT1lKX19Y2xhc3MgUmVsZXZhbnQgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJyZWxldmFudCIpfVtZaV0oKXt0aGlzWyRpXT10aGlzWyRpXS50cmltKCkuc3BsaXQoL1xzKy8pfX1jbGFzcyBSZW5hbWUgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJyZW5hbWUiKX1bWWldKCl7dGhpc1skaV09dGhpc1skaV0udHJpbSgpOyh0aGlzWyRpXS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoInhtbCIpfHxuZXcgUmVnRXhwKCJbXFxwe0x9X11bXFxwe0x9XFxkLl9cXHB7TX0tXSoiLCJ1IikudGVzdCh0aGlzWyRpXSkpJiZ3YXJuKCJYRkEgLSBSZW5hbWU6IGludmFsaWQgWEZBIG5hbWUiKX19Y2xhc3MgUmVuZGVyUG9saWN5IGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJyZW5kZXJQb2xpY3kiLFsic2VydmVyIiwiY2xpZW50Il0pfX1jbGFzcyBSdW5TY3JpcHRzIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJydW5TY3JpcHRzIixbImJvdGgiLCJjbGllbnQiLCJub25lIiwic2VydmVyIl0pfX1jbGFzcyBjb25maWdfU2NyaXB0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJzY3JpcHQiLCEwKTt0aGlzLmN1cnJlbnRQYWdlPW51bGw7dGhpcy5leGNsdWRlPW51bGw7dGhpcy5ydW5TY3JpcHRzPW51bGx9fWNsYXNzIFNjcmlwdE1vZGVsIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJzY3JpcHRNb2RlbCIsWyJYRkEiLCJub25lIl0pfX1jbGFzcyBTZXZlcml0eSBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywic2V2ZXJpdHkiLFsiaWdub3JlIiwiZXJyb3IiLCJpbmZvcm1hdGlvbiIsInRyYWNlIiwid2FybmluZyJdKX19Y2xhc3MgU2lsZW50UHJpbnQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInNpbGVudFByaW50IiwhMCk7dGhpcy5hZGRTaWxlbnRQcmludD1udWxsO3RoaXMucHJpbnRlck5hbWU9bnVsbH19Y2xhc3MgU3RhcGxlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJzdGFwbGUiKTt0aGlzLm1vZGU9Z2V0U3RyaW5nT3B0aW9uKGUubW9kZSxbInVzZVByaW50ZXJTZXR0aW5nIiwib24iLCJvZmYiXSl9fWNsYXNzIFN0YXJ0Tm9kZSBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywic3RhcnROb2RlIil9fWNsYXNzIFN0YXJ0UGFnZSBleHRlbmRzIEludGVnZXJPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInN0YXJ0UGFnZSIsMCxlPT4hMCl9fWNsYXNzIFN1Ym1pdEZvcm1hdCBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywic3VibWl0Rm9ybWF0IixbImh0bWwiLCJkZWxlZ2F0ZSIsImZkZiIsInhtbCIsInBkZiJdKX19Y2xhc3MgU3VibWl0VXJsIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJzdWJtaXRVcmwiKX19Y2xhc3MgU3Vic2V0QmVsb3cgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJzdWJzZXRCZWxvdyIsMTAwLGU9PmU+PTAmJmU8PTEwMCl9fWNsYXNzIFN1cHByZXNzQmFubmVyIGV4dGVuZHMgT3B0aW9uMDF7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInN1cHByZXNzQmFubmVyIil9fWNsYXNzIFRhZ2dlZCBleHRlbmRzIE9wdGlvbjAxe2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ0YWdnZWQiKX19Y2xhc3MgY29uZmlnX1RlbXBsYXRlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ0ZW1wbGF0ZSIsITApO3RoaXMuYmFzZT1udWxsO3RoaXMucmVsZXZhbnQ9bnVsbDt0aGlzLnN0YXJ0UGFnZT1udWxsO3RoaXMudXJpPW51bGw7dGhpcy54c2w9bnVsbH19Y2xhc3MgVGhyZXNob2xkIGV4dGVuZHMgT3B0aW9uT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ0aHJlc2hvbGQiLFsidHJhY2UiLCJlcnJvciIsImluZm9ybWF0aW9uIiwid2FybmluZyJdKX19Y2xhc3MgVG8gZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInRvIixbIm51bGwiLCJtZW1vcnkiLCJzdGRlcnIiLCJzdGRvdXQiLCJzeXN0ZW0iLCJ1cmkiXSl9fWNsYXNzIFRlbXBsYXRlQ2FjaGUgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInRlbXBsYXRlQ2FjaGUiKTt0aGlzLm1heEVudHJpZXM9Z2V0SW50ZWdlcih7ZGF0YTplLm1heEVudHJpZXMsZGVmYXVsdFZhbHVlOjUsdmFsaWRhdGU6ZT0+ZT49MH0pfX1jbGFzcyBUcmFjZSBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywidHJhY2UiLCEwKTt0aGlzLmFyZWE9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBUcmFuc2Zvcm0gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInRyYW5zZm9ybSIsITApO3RoaXMuZ3JvdXBQYXJlbnQ9bnVsbDt0aGlzLmlmRW1wdHk9bnVsbDt0aGlzLm5hbWVBdHRyPW51bGw7dGhpcy5waWN0dXJlPW51bGw7dGhpcy5wcmVzZW5jZT1udWxsO3RoaXMucmVuYW1lPW51bGw7dGhpcy53aGl0ZXNwYWNlPW51bGx9fWNsYXNzIFR5cGUgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInR5cGUiLFsibm9uZSIsImFzY2lpODUiLCJhc2NpaUhleCIsImNjaXR0ZmF4IiwiZmxhdGUiLCJsenciLCJydW5MZW5ndGgiLCJuYXRpdmUiLCJ4ZHAiLCJtZXJnZWRYRFAiXSl9fWNsYXNzIFVyaSBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywidXJpIil9fWNsYXNzIGNvbmZpZ19WYWxpZGF0ZSBleHRlbmRzIE9wdGlvbk9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywidmFsaWRhdGUiLFsicHJlU3VibWl0IiwicHJlUHJpbnQiLCJwcmVFeGVjdXRlIiwicHJlU2F2ZSJdKX19Y2xhc3MgVmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyIpfVtZaV0oKXt0aGlzWyRpXT10aGlzWyRpXS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcihlPT5bImRvY1JlYWR5IiwicG9zdFNpZ24iXS5pbmNsdWRlcyhlKSl9fWNsYXNzIFZhbGlkYXRpb25NZXNzYWdpbmcgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInZhbGlkYXRpb25NZXNzYWdpbmciLFsiYWxsTWVzc2FnZXNJbmRpdmlkdWFsbHkiLCJhbGxNZXNzYWdlc1RvZ2V0aGVyIiwiZmlyc3RNZXNzYWdlT25seSIsIm5vTWVzc2FnZXMiXSl9fWNsYXNzIFZlcnNpb24gZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInZlcnNpb24iLFsiMS43IiwiMS42IiwiMS41IiwiMS40IiwiMS4zIiwiMS4yIl0pfX1jbGFzcyBWZXJzaW9uQ29udHJvbCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywiVmVyc2lvbkNvbnRyb2wiKTt0aGlzLm91dHB1dEJlbG93PWdldFN0cmluZ09wdGlvbihlLm91dHB1dEJlbG93LFsid2FybiIsImVycm9yIiwidXBkYXRlIl0pO3RoaXMuc291cmNlQWJvdmU9Z2V0U3RyaW5nT3B0aW9uKGUuc291cmNlQWJvdmUsWyJ3YXJuIiwiZXJyb3IiXSk7dGhpcy5zb3VyY2VCZWxvdz1nZXRTdHJpbmdPcHRpb24oZS5zb3VyY2VCZWxvdyxbInVwZGF0ZSIsIm1haW50YWluIl0pfX1jbGFzcyBWaWV3ZXJQcmVmZXJlbmNlcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywidmlld2VyUHJlZmVyZW5jZXMiLCEwKTt0aGlzLkFEQkVfSlNDb25zb2xlPW51bGw7dGhpcy5BREJFX0pTRGVidWdnZXI9bnVsbDt0aGlzLmFkZFZpZXdlclByZWZlcmVuY2VzPW51bGw7dGhpcy5kdXBsZXhPcHRpb249bnVsbDt0aGlzLmVuZm9yY2U9bnVsbDt0aGlzLm51bWJlck9mQ29waWVzPW51bGw7dGhpcy5wYWdlUmFuZ2U9bnVsbDt0aGlzLnBpY2tUcmF5QnlQREZTaXplPW51bGw7dGhpcy5wcmludFNjYWxpbmc9bnVsbH19Y2xhc3MgV2ViQ2xpZW50IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ3ZWJDbGllbnQiLCEwKTt0aGlzLm5hbWU9ZS5uYW1lP2UubmFtZS50cmltKCk6IiI7dGhpcy5mb250SW5mbz1udWxsO3RoaXMueGRjPW51bGx9fWNsYXNzIFdoaXRlc3BhY2UgZXh0ZW5kcyBPcHRpb25PYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sIndoaXRlc3BhY2UiLFsicHJlc2VydmUiLCJsdHJpbSIsIm5vcm1hbGl6ZSIsInJ0cmltIiwidHJpbSJdKX19Y2xhc3MgV2luZG93IGV4dGVuZHMgQ29udGVudE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihVbywid2luZG93Iil9W1lpXSgpe2NvbnN0IGU9dGhpc1skaV0uc3BsaXQoIiwiLDIpLm1hcChlPT5wYXJzZUludChlLnRyaW0oKSwxMCkpO2lmKGUuc29tZShlPT5pc05hTihlKSkpdGhpc1skaV09WzAsMF07ZWxzZXsxPT09ZS5sZW5ndGgmJmUucHVzaChlWzBdKTt0aGlzWyRpXT1lfX19Y2xhc3MgWGRjIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFVvLCJ4ZGMiLCEwKTt0aGlzLnVyaT1uZXcgWEZBT2JqZWN0QXJyYXk7dGhpcy54c2w9bmV3IFhGQU9iamVjdEFycmF5fX1jbGFzcyBYZHAgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInhkcCIsITApO3RoaXMucGFja2V0cz1udWxsfX1jbGFzcyBYc2wgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInhzbCIsITApO3RoaXMuZGVidWc9bnVsbDt0aGlzLnVyaT1udWxsfX1jbGFzcyBacGwgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoVW8sInpwbCIsITApO3RoaXMubmFtZT1lLm5hbWU/ZS5uYW1lLnRyaW0oKToiIjt0aGlzLmJhdGNoT3V0cHV0PW51bGw7dGhpcy5mbGlwTGFiZWw9bnVsbDt0aGlzLmZvbnRJbmZvPW51bGw7dGhpcy54ZGM9bnVsbH19Y2xhc3MgQ29uZmlnTmFtZXNwYWNle3N0YXRpY1tRc10oZSx0KXtpZihDb25maWdOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkoZSkpcmV0dXJuIENvbmZpZ05hbWVzcGFjZVtlXSh0KX1zdGF0aWMgYWNyb2JhdChlKXtyZXR1cm4gbmV3IEFjcm9iYXQoZSl9c3RhdGljIGFjcm9iYXQ3KGUpe3JldHVybiBuZXcgQWNyb2JhdDcoZSl9c3RhdGljIEFEQkVfSlNDb25zb2xlKGUpe3JldHVybiBuZXcgQURCRV9KU0NvbnNvbGUoZSl9c3RhdGljIEFEQkVfSlNEZWJ1Z2dlcihlKXtyZXR1cm4gbmV3IEFEQkVfSlNEZWJ1Z2dlcihlKX1zdGF0aWMgYWRkU2lsZW50UHJpbnQoZSl7cmV0dXJuIG5ldyBBZGRTaWxlbnRQcmludChlKX1zdGF0aWMgYWRkVmlld2VyUHJlZmVyZW5jZXMoZSl7cmV0dXJuIG5ldyBBZGRWaWV3ZXJQcmVmZXJlbmNlcyhlKX1zdGF0aWMgYWRqdXN0RGF0YShlKXtyZXR1cm4gbmV3IEFkanVzdERhdGEoZSl9c3RhdGljIGFkb2JlRXh0ZW5zaW9uTGV2ZWwoZSl7cmV0dXJuIG5ldyBBZG9iZUV4dGVuc2lvbkxldmVsKGUpfXN0YXRpYyBhZ2VudChlKXtyZXR1cm4gbmV3IEFnZW50KGUpfXN0YXRpYyBhbHdheXNFbWJlZChlKXtyZXR1cm4gbmV3IEFsd2F5c0VtYmVkKGUpfXN0YXRpYyBhbWQoZSl7cmV0dXJuIG5ldyBBbWQoZSl9c3RhdGljIGFyZWEoZSl7cmV0dXJuIG5ldyBjb25maWdfQXJlYShlKX1zdGF0aWMgYXR0cmlidXRlcyhlKXtyZXR1cm4gbmV3IEF0dHJpYnV0ZXMoZSl9c3RhdGljIGF1dG9TYXZlKGUpe3JldHVybiBuZXcgQXV0b1NhdmUoZSl9c3RhdGljIGJhc2UoZSl7cmV0dXJuIG5ldyBCYXNlKGUpfXN0YXRpYyBiYXRjaE91dHB1dChlKXtyZXR1cm4gbmV3IEJhdGNoT3V0cHV0KGUpfXN0YXRpYyBiZWhhdmlvck92ZXJyaWRlKGUpe3JldHVybiBuZXcgQmVoYXZpb3JPdmVycmlkZShlKX1zdGF0aWMgY2FjaGUoZSl7cmV0dXJuIG5ldyBDYWNoZShlKX1zdGF0aWMgY2hhbmdlKGUpe3JldHVybiBuZXcgQ2hhbmdlKGUpfXN0YXRpYyBjb21tb24oZSl7cmV0dXJuIG5ldyBDb21tb24oZSl9c3RhdGljIGNvbXByZXNzKGUpe3JldHVybiBuZXcgQ29tcHJlc3MoZSl9c3RhdGljIGNvbXByZXNzTG9naWNhbFN0cnVjdHVyZShlKXtyZXR1cm4gbmV3IENvbXByZXNzTG9naWNhbFN0cnVjdHVyZShlKX1zdGF0aWMgY29tcHJlc3NPYmplY3RTdHJlYW0oZSl7cmV0dXJuIG5ldyBDb21wcmVzc09iamVjdFN0cmVhbShlKX1zdGF0aWMgY29tcHJlc3Npb24oZSl7cmV0dXJuIG5ldyBDb21wcmVzc2lvbihlKX1zdGF0aWMgY29uZmlnKGUpe3JldHVybiBuZXcgQ29uZmlnKGUpfXN0YXRpYyBjb25mb3JtYW5jZShlKXtyZXR1cm4gbmV3IENvbmZvcm1hbmNlKGUpfXN0YXRpYyBjb250ZW50Q29weShlKXtyZXR1cm4gbmV3IENvbnRlbnRDb3B5KGUpfXN0YXRpYyBjb3BpZXMoZSl7cmV0dXJuIG5ldyBDb3BpZXMoZSl9c3RhdGljIGNyZWF0b3IoZSl7cmV0dXJuIG5ldyBDcmVhdG9yKGUpfXN0YXRpYyBjdXJyZW50UGFnZShlKXtyZXR1cm4gbmV3IEN1cnJlbnRQYWdlKGUpfXN0YXRpYyBkYXRhKGUpe3JldHVybiBuZXcgRGF0YShlKX1zdGF0aWMgZGVidWcoZSl7cmV0dXJuIG5ldyBEZWJ1ZyhlKX1zdGF0aWMgZGVmYXVsdFR5cGVmYWNlKGUpe3JldHVybiBuZXcgRGVmYXVsdFR5cGVmYWNlKGUpfXN0YXRpYyBkZXN0aW5hdGlvbihlKXtyZXR1cm4gbmV3IERlc3RpbmF0aW9uKGUpfXN0YXRpYyBkb2N1bWVudEFzc2VtYmx5KGUpe3JldHVybiBuZXcgRG9jdW1lbnRBc3NlbWJseShlKX1zdGF0aWMgZHJpdmVyKGUpe3JldHVybiBuZXcgRHJpdmVyKGUpfXN0YXRpYyBkdXBsZXhPcHRpb24oZSl7cmV0dXJuIG5ldyBEdXBsZXhPcHRpb24oZSl9c3RhdGljIGR5bmFtaWNSZW5kZXIoZSl7cmV0dXJuIG5ldyBEeW5hbWljUmVuZGVyKGUpfXN0YXRpYyBlbWJlZChlKXtyZXR1cm4gbmV3IEVtYmVkKGUpfXN0YXRpYyBlbmNyeXB0KGUpe3JldHVybiBuZXcgY29uZmlnX0VuY3J5cHQoZSl9c3RhdGljIGVuY3J5cHRpb24oZSl7cmV0dXJuIG5ldyBjb25maWdfRW5jcnlwdGlvbihlKX1zdGF0aWMgZW5jcnlwdGlvbkxldmVsKGUpe3JldHVybiBuZXcgRW5jcnlwdGlvbkxldmVsKGUpfXN0YXRpYyBlbmZvcmNlKGUpe3JldHVybiBuZXcgRW5mb3JjZShlKX1zdGF0aWMgZXF1YXRlKGUpe3JldHVybiBuZXcgRXF1YXRlKGUpfXN0YXRpYyBlcXVhdGVSYW5nZShlKXtyZXR1cm4gbmV3IEVxdWF0ZVJhbmdlKGUpfXN0YXRpYyBleGNsdWRlKGUpe3JldHVybiBuZXcgRXhjbHVkZShlKX1zdGF0aWMgZXhjbHVkZU5TKGUpe3JldHVybiBuZXcgRXhjbHVkZU5TKGUpfXN0YXRpYyBmbGlwTGFiZWwoZSl7cmV0dXJuIG5ldyBGbGlwTGFiZWwoZSl9c3RhdGljIGZvbnRJbmZvKGUpe3JldHVybiBuZXcgY29uZmlnX0ZvbnRJbmZvKGUpfXN0YXRpYyBmb3JtRmllbGRGaWxsaW5nKGUpe3JldHVybiBuZXcgRm9ybUZpZWxkRmlsbGluZyhlKX1zdGF0aWMgZ3JvdXBQYXJlbnQoZSl7cmV0dXJuIG5ldyBHcm91cFBhcmVudChlKX1zdGF0aWMgaWZFbXB0eShlKXtyZXR1cm4gbmV3IElmRW1wdHkoZSl9c3RhdGljIGluY2x1ZGVYRFBDb250ZW50KGUpe3JldHVybiBuZXcgSW5jbHVkZVhEUENvbnRlbnQoZSl9c3RhdGljIGluY3JlbWVudGFsTG9hZChlKXtyZXR1cm4gbmV3IEluY3JlbWVudGFsTG9hZChlKX1zdGF0aWMgaW5jcmVtZW50YWxNZXJnZShlKXtyZXR1cm4gbmV3IEluY3JlbWVudGFsTWVyZ2UoZSl9c3RhdGljIGludGVyYWN0aXZlKGUpe3JldHVybiBuZXcgSW50ZXJhY3RpdmUoZSl9c3RhdGljIGpvZyhlKXtyZXR1cm4gbmV3IEpvZyhlKX1zdGF0aWMgbGFiZWxQcmludGVyKGUpe3JldHVybiBuZXcgTGFiZWxQcmludGVyKGUpfXN0YXRpYyBsYXlvdXQoZSl7cmV0dXJuIG5ldyBMYXlvdXQoZSl9c3RhdGljIGxldmVsKGUpe3JldHVybiBuZXcgTGV2ZWwoZSl9c3RhdGljIGxpbmVhcml6ZWQoZSl7cmV0dXJuIG5ldyBMaW5lYXJpemVkKGUpfXN0YXRpYyBsb2NhbGUoZSl7cmV0dXJuIG5ldyBMb2NhbGUoZSl9c3RhdGljIGxvY2FsZVNldChlKXtyZXR1cm4gbmV3IExvY2FsZVNldChlKX1zdGF0aWMgbG9nKGUpe3JldHVybiBuZXcgTG9nKGUpfXN0YXRpYyBtYXAoZSl7cmV0dXJuIG5ldyBNYXBFbGVtZW50KGUpfXN0YXRpYyBtZWRpdW1JbmZvKGUpe3JldHVybiBuZXcgTWVkaXVtSW5mbyhlKX1zdGF0aWMgbWVzc2FnZShlKXtyZXR1cm4gbmV3IGNvbmZpZ19NZXNzYWdlKGUpfXN0YXRpYyBtZXNzYWdpbmcoZSl7cmV0dXJuIG5ldyBNZXNzYWdpbmcoZSl9c3RhdGljIG1vZGUoZSl7cmV0dXJuIG5ldyBNb2RlKGUpfXN0YXRpYyBtb2RpZnlBbm5vdHMoZSl7cmV0dXJuIG5ldyBNb2RpZnlBbm5vdHMoZSl9c3RhdGljIG1zZ0lkKGUpe3JldHVybiBuZXcgTXNnSWQoZSl9c3RhdGljIG5hbWVBdHRyKGUpe3JldHVybiBuZXcgTmFtZUF0dHIoZSl9c3RhdGljIG5ldmVyRW1iZWQoZSl7cmV0dXJuIG5ldyBOZXZlckVtYmVkKGUpfXN0YXRpYyBudW1iZXJPZkNvcGllcyhlKXtyZXR1cm4gbmV3IE51bWJlck9mQ29waWVzKGUpfXN0YXRpYyBvcGVuQWN0aW9uKGUpe3JldHVybiBuZXcgT3BlbkFjdGlvbihlKX1zdGF0aWMgb3V0cHV0KGUpe3JldHVybiBuZXcgT3V0cHV0KGUpfXN0YXRpYyBvdXRwdXRCaW4oZSl7cmV0dXJuIG5ldyBPdXRwdXRCaW4oZSl9c3RhdGljIG91dHB1dFhTTChlKXtyZXR1cm4gbmV3IE91dHB1dFhTTChlKX1zdGF0aWMgb3ZlcnByaW50KGUpe3JldHVybiBuZXcgT3ZlcnByaW50KGUpfXN0YXRpYyBwYWNrZXRzKGUpe3JldHVybiBuZXcgUGFja2V0cyhlKX1zdGF0aWMgcGFnZU9mZnNldChlKXtyZXR1cm4gbmV3IFBhZ2VPZmZzZXQoZSl9c3RhdGljIHBhZ2VSYW5nZShlKXtyZXR1cm4gbmV3IFBhZ2VSYW5nZShlKX1zdGF0aWMgcGFnaW5hdGlvbihlKXtyZXR1cm4gbmV3IFBhZ2luYXRpb24oZSl9c3RhdGljIHBhZ2luYXRpb25PdmVycmlkZShlKXtyZXR1cm4gbmV3IFBhZ2luYXRpb25PdmVycmlkZShlKX1zdGF0aWMgcGFydChlKXtyZXR1cm4gbmV3IFBhcnQoZSl9c3RhdGljIHBjbChlKXtyZXR1cm4gbmV3IFBjbChlKX1zdGF0aWMgcGRmKGUpe3JldHVybiBuZXcgUGRmKGUpfXN0YXRpYyBwZGZhKGUpe3JldHVybiBuZXcgUGRmYShlKX1zdGF0aWMgcGVybWlzc2lvbnMoZSl7cmV0dXJuIG5ldyBQZXJtaXNzaW9ucyhlKX1zdGF0aWMgcGlja1RyYXlCeVBERlNpemUoZSl7cmV0dXJuIG5ldyBQaWNrVHJheUJ5UERGU2l6ZShlKX1zdGF0aWMgcGljdHVyZShlKXtyZXR1cm4gbmV3IGNvbmZpZ19QaWN0dXJlKGUpfXN0YXRpYyBwbGFpbnRleHRNZXRhZGF0YShlKXtyZXR1cm4gbmV3IFBsYWludGV4dE1ldGFkYXRhKGUpfXN0YXRpYyBwcmVzZW5jZShlKXtyZXR1cm4gbmV3IFByZXNlbmNlKGUpfXN0YXRpYyBwcmVzZW50KGUpe3JldHVybiBuZXcgUHJlc2VudChlKX1zdGF0aWMgcHJpbnQoZSl7cmV0dXJuIG5ldyBQcmludChlKX1zdGF0aWMgcHJpbnRIaWdoUXVhbGl0eShlKXtyZXR1cm4gbmV3IFByaW50SGlnaFF1YWxpdHkoZSl9c3RhdGljIHByaW50U2NhbGluZyhlKXtyZXR1cm4gbmV3IFByaW50U2NhbGluZyhlKX1zdGF0aWMgcHJpbnRlck5hbWUoZSl7cmV0dXJuIG5ldyBQcmludGVyTmFtZShlKX1zdGF0aWMgcHJvZHVjZXIoZSl7cmV0dXJuIG5ldyBQcm9kdWNlcihlKX1zdGF0aWMgcHMoZSl7cmV0dXJuIG5ldyBQcyhlKX1zdGF0aWMgcmFuZ2UoZSl7cmV0dXJuIG5ldyBSYW5nZShlKX1zdGF0aWMgcmVjb3JkKGUpe3JldHVybiBuZXcgUmVjb3JkKGUpfXN0YXRpYyByZWxldmFudChlKXtyZXR1cm4gbmV3IFJlbGV2YW50KGUpfXN0YXRpYyByZW5hbWUoZSl7cmV0dXJuIG5ldyBSZW5hbWUoZSl9c3RhdGljIHJlbmRlclBvbGljeShlKXtyZXR1cm4gbmV3IFJlbmRlclBvbGljeShlKX1zdGF0aWMgcnVuU2NyaXB0cyhlKXtyZXR1cm4gbmV3IFJ1blNjcmlwdHMoZSl9c3RhdGljIHNjcmlwdChlKXtyZXR1cm4gbmV3IGNvbmZpZ19TY3JpcHQoZSl9c3RhdGljIHNjcmlwdE1vZGVsKGUpe3JldHVybiBuZXcgU2NyaXB0TW9kZWwoZSl9c3RhdGljIHNldmVyaXR5KGUpe3JldHVybiBuZXcgU2V2ZXJpdHkoZSl9c3RhdGljIHNpbGVudFByaW50KGUpe3JldHVybiBuZXcgU2lsZW50UHJpbnQoZSl9c3RhdGljIHN0YXBsZShlKXtyZXR1cm4gbmV3IFN0YXBsZShlKX1zdGF0aWMgc3RhcnROb2RlKGUpe3JldHVybiBuZXcgU3RhcnROb2RlKGUpfXN0YXRpYyBzdGFydFBhZ2UoZSl7cmV0dXJuIG5ldyBTdGFydFBhZ2UoZSl9c3RhdGljIHN1Ym1pdEZvcm1hdChlKXtyZXR1cm4gbmV3IFN1Ym1pdEZvcm1hdChlKX1zdGF0aWMgc3VibWl0VXJsKGUpe3JldHVybiBuZXcgU3VibWl0VXJsKGUpfXN0YXRpYyBzdWJzZXRCZWxvdyhlKXtyZXR1cm4gbmV3IFN1YnNldEJlbG93KGUpfXN0YXRpYyBzdXBwcmVzc0Jhbm5lcihlKXtyZXR1cm4gbmV3IFN1cHByZXNzQmFubmVyKGUpfXN0YXRpYyB0YWdnZWQoZSl7cmV0dXJuIG5ldyBUYWdnZWQoZSl9c3RhdGljIHRlbXBsYXRlKGUpe3JldHVybiBuZXcgY29uZmlnX1RlbXBsYXRlKGUpfXN0YXRpYyB0ZW1wbGF0ZUNhY2hlKGUpe3JldHVybiBuZXcgVGVtcGxhdGVDYWNoZShlKX1zdGF0aWMgdGhyZXNob2xkKGUpe3JldHVybiBuZXcgVGhyZXNob2xkKGUpfXN0YXRpYyB0byhlKXtyZXR1cm4gbmV3IFRvKGUpfXN0YXRpYyB0cmFjZShlKXtyZXR1cm4gbmV3IFRyYWNlKGUpfXN0YXRpYyB0cmFuc2Zvcm0oZSl7cmV0dXJuIG5ldyBUcmFuc2Zvcm0oZSl9c3RhdGljIHR5cGUoZSl7cmV0dXJuIG5ldyBUeXBlKGUpfXN0YXRpYyB1cmkoZSl7cmV0dXJuIG5ldyBVcmkoZSl9c3RhdGljIHZhbGlkYXRlKGUpe3JldHVybiBuZXcgY29uZmlnX1ZhbGlkYXRlKGUpfXN0YXRpYyB2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyhlKXtyZXR1cm4gbmV3IFZhbGlkYXRlQXBwcm92YWxTaWduYXR1cmVzKGUpfXN0YXRpYyB2YWxpZGF0aW9uTWVzc2FnaW5nKGUpe3JldHVybiBuZXcgVmFsaWRhdGlvbk1lc3NhZ2luZyhlKX1zdGF0aWMgdmVyc2lvbihlKXtyZXR1cm4gbmV3IFZlcnNpb24oZSl9c3RhdGljIHZlcnNpb25Db250cm9sKGUpe3JldHVybiBuZXcgVmVyc2lvbkNvbnRyb2woZSl9c3RhdGljIHZpZXdlclByZWZlcmVuY2VzKGUpe3JldHVybiBuZXcgVmlld2VyUHJlZmVyZW5jZXMoZSl9c3RhdGljIHdlYkNsaWVudChlKXtyZXR1cm4gbmV3IFdlYkNsaWVudChlKX1zdGF0aWMgd2hpdGVzcGFjZShlKXtyZXR1cm4gbmV3IFdoaXRlc3BhY2UoZSl9c3RhdGljIHdpbmRvdyhlKXtyZXR1cm4gbmV3IFdpbmRvdyhlKX1zdGF0aWMgeGRjKGUpe3JldHVybiBuZXcgWGRjKGUpfXN0YXRpYyB4ZHAoZSl7cmV0dXJuIG5ldyBYZHAoZSl9c3RhdGljIHhzbChlKXtyZXR1cm4gbmV3IFhzbChlKX1zdGF0aWMgenBsKGUpe3JldHVybiBuZXcgWnBsKGUpfX1jb25zdCBxbz1lby5jb25uZWN0aW9uU2V0LmlkO2NsYXNzIENvbm5lY3Rpb25TZXQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIocW8sImNvbm5lY3Rpb25TZXQiLCEwKTt0aGlzLndzZGxDb25uZWN0aW9uPW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnhtbENvbm5lY3Rpb249bmV3IFhGQU9iamVjdEFycmF5O3RoaXMueHNkQ29ubmVjdGlvbj1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIEVmZmVjdGl2ZUlucHV0UG9saWN5IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKHFvLCJlZmZlY3RpdmVJbnB1dFBvbGljeSIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBFZmZlY3RpdmVPdXRwdXRQb2xpY3kgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIocW8sImVmZmVjdGl2ZU91dHB1dFBvbGljeSIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBPcGVyYXRpb24gZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIocW8sIm9wZXJhdGlvbiIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5pbnB1dD1lLmlucHV0fHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLm91dHB1dD1lLm91dHB1dHx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBSb290RWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihxbywicm9vdEVsZW1lbnQiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgU29hcEFjdGlvbiBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihxbywic29hcEFjdGlvbiIpO3RoaXMuaWQ9ZS5pZHx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51c2U9ZS51c2V8fCIiO3RoaXMudXNlaHJlZj1lLnVzZWhyZWZ8fCIifX1jbGFzcyBTb2FwQWRkcmVzcyBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihxbywic29hcEFkZHJlc3MiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgY29ubmVjdGlvbl9zZXRfVXJpIGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKHFvLCJ1cmkiKTt0aGlzLmlkPWUuaWR8fCIiO3RoaXMubmFtZT1lLm5hbWV8fCIiO3RoaXMudXNlPWUudXNlfHwiIjt0aGlzLnVzZWhyZWY9ZS51c2VocmVmfHwiIn19Y2xhc3MgV3NkbEFkZHJlc3MgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIocW8sIndzZGxBZGRyZXNzIik7dGhpcy5pZD1lLmlkfHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnVzZT1lLnVzZXx8IiI7dGhpcy51c2VocmVmPWUudXNlaHJlZnx8IiJ9fWNsYXNzIFdzZGxDb25uZWN0aW9uIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKHFvLCJ3c2RsQ29ubmVjdGlvbiIsITApO3RoaXMuZGF0YURlc2NyaXB0aW9uPWUuZGF0YURlc2NyaXB0aW9ufHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLmVmZmVjdGl2ZUlucHV0UG9saWN5PW51bGw7dGhpcy5lZmZlY3RpdmVPdXRwdXRQb2xpY3k9bnVsbDt0aGlzLm9wZXJhdGlvbj1udWxsO3RoaXMuc29hcEFjdGlvbj1udWxsO3RoaXMuc29hcEFkZHJlc3M9bnVsbDt0aGlzLndzZGxBZGRyZXNzPW51bGx9fWNsYXNzIFhtbENvbm5lY3Rpb24gZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIocW8sInhtbENvbm5lY3Rpb24iLCEwKTt0aGlzLmRhdGFEZXNjcmlwdGlvbj1lLmRhdGFEZXNjcmlwdGlvbnx8IiI7dGhpcy5uYW1lPWUubmFtZXx8IiI7dGhpcy51cmk9bnVsbH19Y2xhc3MgWHNkQ29ubmVjdGlvbiBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihxbywieHNkQ29ubmVjdGlvbiIsITApO3RoaXMuZGF0YURlc2NyaXB0aW9uPWUuZGF0YURlc2NyaXB0aW9ufHwiIjt0aGlzLm5hbWU9ZS5uYW1lfHwiIjt0aGlzLnJvb3RFbGVtZW50PW51bGw7dGhpcy51cmk9bnVsbH19Y2xhc3MgQ29ubmVjdGlvblNldE5hbWVzcGFjZXtzdGF0aWNbUXNdKGUsdCl7aWYoQ29ubmVjdGlvblNldE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShlKSlyZXR1cm4gQ29ubmVjdGlvblNldE5hbWVzcGFjZVtlXSh0KX1zdGF0aWMgY29ubmVjdGlvblNldChlKXtyZXR1cm4gbmV3IENvbm5lY3Rpb25TZXQoZSl9c3RhdGljIGVmZmVjdGl2ZUlucHV0UG9saWN5KGUpe3JldHVybiBuZXcgRWZmZWN0aXZlSW5wdXRQb2xpY3koZSl9c3RhdGljIGVmZmVjdGl2ZU91dHB1dFBvbGljeShlKXtyZXR1cm4gbmV3IEVmZmVjdGl2ZU91dHB1dFBvbGljeShlKX1zdGF0aWMgb3BlcmF0aW9uKGUpe3JldHVybiBuZXcgT3BlcmF0aW9uKGUpfXN0YXRpYyByb290RWxlbWVudChlKXtyZXR1cm4gbmV3IFJvb3RFbGVtZW50KGUpfXN0YXRpYyBzb2FwQWN0aW9uKGUpe3JldHVybiBuZXcgU29hcEFjdGlvbihlKX1zdGF0aWMgc29hcEFkZHJlc3MoZSl7cmV0dXJuIG5ldyBTb2FwQWRkcmVzcyhlKX1zdGF0aWMgdXJpKGUpe3JldHVybiBuZXcgY29ubmVjdGlvbl9zZXRfVXJpKGUpfXN0YXRpYyB3c2RsQWRkcmVzcyhlKXtyZXR1cm4gbmV3IFdzZGxBZGRyZXNzKGUpfXN0YXRpYyB3c2RsQ29ubmVjdGlvbihlKXtyZXR1cm4gbmV3IFdzZGxDb25uZWN0aW9uKGUpfXN0YXRpYyB4bWxDb25uZWN0aW9uKGUpe3JldHVybiBuZXcgWG1sQ29ubmVjdGlvbihlKX1zdGF0aWMgeHNkQ29ubmVjdGlvbihlKXtyZXR1cm4gbmV3IFhzZENvbm5lY3Rpb24oZSl9fWNvbnN0IFhvPWVvLmRhdGFzZXRzLmlkO2NsYXNzIGRhdGFzZXRzX0RhdGEgZXh0ZW5kcyBYbWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoWG8sImRhdGEiLGUpfVtrc10oKXtyZXR1cm4hMH19Y2xhc3MgRGF0YXNldHMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoWG8sImRhdGFzZXRzIiwhMCk7dGhpcy5kYXRhPW51bGw7dGhpcy5TaWduYXR1cmU9bnVsbH1bQnNdKGUpe2NvbnN0IHQ9ZVtNc107KCJkYXRhIj09PXQmJmVbT3NdPT09WG98fCJTaWduYXR1cmUiPT09dCYmZVtPc109PT1lby5zaWduYXR1cmUuaWQpJiYodGhpc1t0XT1lKTt0aGlzW2ppXShlKX19Y2xhc3MgRGF0YXNldHNOYW1lc3BhY2V7c3RhdGljW1FzXShlLHQpe2lmKERhdGFzZXRzTmFtZXNwYWNlLmhhc093blByb3BlcnR5KGUpKXJldHVybiBEYXRhc2V0c05hbWVzcGFjZVtlXSh0KX1zdGF0aWMgZGF0YXNldHMoZSl7cmV0dXJuIG5ldyBEYXRhc2V0cyhlKX1zdGF0aWMgZGF0YShlKXtyZXR1cm4gbmV3IGRhdGFzZXRzX0RhdGEoZSl9fWNvbnN0IEhvPWVvLmxvY2FsZVNldC5pZDtjbGFzcyBDYWxlbmRhclN5bWJvbHMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImNhbGVuZGFyU3ltYm9scyIsITApO3RoaXMubmFtZT0iZ3JlZ29yaWFuIjt0aGlzLmRheU5hbWVzPW5ldyBYRkFPYmplY3RBcnJheSgyKTt0aGlzLmVyYU5hbWVzPW51bGw7dGhpcy5tZXJpZGllbU5hbWVzPW51bGw7dGhpcy5tb250aE5hbWVzPW5ldyBYRkFPYmplY3RBcnJheSgyKX19Y2xhc3MgQ3VycmVuY3lTeW1ib2wgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImN1cnJlbmN5U3ltYm9sIik7dGhpcy5uYW1lPWdldFN0cmluZ09wdGlvbihlLm5hbWUsWyJzeW1ib2wiLCJpc29uYW1lIiwiZGVjaW1hbCJdKX19Y2xhc3MgQ3VycmVuY3lTeW1ib2xzIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJjdXJyZW5jeVN5bWJvbHMiLCEwKTt0aGlzLmN1cnJlbmN5U3ltYm9sPW5ldyBYRkFPYmplY3RBcnJheSgzKX19Y2xhc3MgRGF0ZVBhdHRlcm4gZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImRhdGVQYXR0ZXJuIik7dGhpcy5uYW1lPWdldFN0cmluZ09wdGlvbihlLm5hbWUsWyJmdWxsIiwibG9uZyIsIm1lZCIsInNob3J0Il0pfX1jbGFzcyBEYXRlUGF0dGVybnMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImRhdGVQYXR0ZXJucyIsITApO3RoaXMuZGF0ZVBhdHRlcm49bmV3IFhGQU9iamVjdEFycmF5KDQpfX1jbGFzcyBEYXRlVGltZVN5bWJvbHMgZXh0ZW5kcyBDb250ZW50T2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJkYXRlVGltZVN5bWJvbHMiKX19Y2xhc3MgRGF5IGV4dGVuZHMgU3RyaW5nT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJkYXkiKX19Y2xhc3MgRGF5TmFtZXMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImRheU5hbWVzIiwhMCk7dGhpcy5hYmJyPWdldEludGVnZXIoe2RhdGE6ZS5hYmJyLGRlZmF1bHRWYWx1ZTowLHZhbGlkYXRlOmU9PjE9PT1lfSk7dGhpcy5kYXk9bmV3IFhGQU9iamVjdEFycmF5KDcpfX1jbGFzcyBFcmEgZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImVyYSIpfX1jbGFzcyBFcmFOYW1lcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihIbywiZXJhTmFtZXMiLCEwKTt0aGlzLmVyYT1uZXcgWEZBT2JqZWN0QXJyYXkoMil9fWNsYXNzIGxvY2FsZV9zZXRfTG9jYWxlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJsb2NhbGUiLCEwKTt0aGlzLmRlc2M9ZS5kZXNjfHwiIjt0aGlzLm5hbWU9Imlzb25hbWUiO3RoaXMuY2FsZW5kYXJTeW1ib2xzPW51bGw7dGhpcy5jdXJyZW5jeVN5bWJvbHM9bnVsbDt0aGlzLmRhdGVQYXR0ZXJucz1udWxsO3RoaXMuZGF0ZVRpbWVTeW1ib2xzPW51bGw7dGhpcy5udW1iZXJQYXR0ZXJucz1udWxsO3RoaXMubnVtYmVyU3ltYm9scz1udWxsO3RoaXMudGltZVBhdHRlcm5zPW51bGw7dGhpcy50eXBlRmFjZXM9bnVsbH19Y2xhc3MgbG9jYWxlX3NldF9Mb2NhbGVTZXQgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sImxvY2FsZVNldCIsITApO3RoaXMubG9jYWxlPW5ldyBYRkFPYmplY3RBcnJheX19Y2xhc3MgTWVyaWRpZW0gZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sIm1lcmlkaWVtIil9fWNsYXNzIE1lcmlkaWVtTmFtZXMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sIm1lcmlkaWVtTmFtZXMiLCEwKTt0aGlzLm1lcmlkaWVtPW5ldyBYRkFPYmplY3RBcnJheSgyKX19Y2xhc3MgTW9udGggZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sIm1vbnRoIil9fWNsYXNzIE1vbnRoTmFtZXMgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sIm1vbnRoTmFtZXMiLCEwKTt0aGlzLmFiYnI9Z2V0SW50ZWdlcih7ZGF0YTplLmFiYnIsZGVmYXVsdFZhbHVlOjAsdmFsaWRhdGU6ZT0+MT09PWV9KTt0aGlzLm1vbnRoPW5ldyBYRkFPYmplY3RBcnJheSgxMil9fWNsYXNzIE51bWJlclBhdHRlcm4gZXh0ZW5kcyBTdHJpbmdPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoSG8sIm51bWJlclBhdHRlcm4iKTt0aGlzLm5hbWU9Z2V0U3RyaW5nT3B0aW9uKGUubmFtZSxbImZ1bGwiLCJsb25nIiwibWVkIiwic2hvcnQiXSl9fWNsYXNzIE51bWJlclBhdHRlcm5zIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJudW1iZXJQYXR0ZXJucyIsITApO3RoaXMubnVtYmVyUGF0dGVybj1uZXcgWEZBT2JqZWN0QXJyYXkoNCl9fWNsYXNzIE51bWJlclN5bWJvbCBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihIbywibnVtYmVyU3ltYm9sIik7dGhpcy5uYW1lPWdldFN0cmluZ09wdGlvbihlLm5hbWUsWyJkZWNpbWFsIiwiZ3JvdXBpbmciLCJwZXJjZW50IiwibWludXMiLCJ6ZXJvIl0pfX1jbGFzcyBOdW1iZXJTeW1ib2xzIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJudW1iZXJTeW1ib2xzIiwhMCk7dGhpcy5udW1iZXJTeW1ib2w9bmV3IFhGQU9iamVjdEFycmF5KDUpfX1jbGFzcyBUaW1lUGF0dGVybiBleHRlbmRzIFN0cmluZ09iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihIbywidGltZVBhdHRlcm4iKTt0aGlzLm5hbWU9Z2V0U3RyaW5nT3B0aW9uKGUubmFtZSxbImZ1bGwiLCJsb25nIiwibWVkIiwic2hvcnQiXSl9fWNsYXNzIFRpbWVQYXR0ZXJucyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihIbywidGltZVBhdHRlcm5zIiwhMCk7dGhpcy50aW1lUGF0dGVybj1uZXcgWEZBT2JqZWN0QXJyYXkoNCl9fWNsYXNzIFR5cGVGYWNlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKEhvLCJ0eXBlRmFjZSIsITApO3RoaXMubmFtZT0iInxlLm5hbWV9fWNsYXNzIFR5cGVGYWNlcyBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihIbywidHlwZUZhY2VzIiwhMCk7dGhpcy50eXBlRmFjZT1uZXcgWEZBT2JqZWN0QXJyYXl9fWNsYXNzIExvY2FsZVNldE5hbWVzcGFjZXtzdGF0aWNbUXNdKGUsdCl7aWYoTG9jYWxlU2V0TmFtZXNwYWNlLmhhc093blByb3BlcnR5KGUpKXJldHVybiBMb2NhbGVTZXROYW1lc3BhY2VbZV0odCl9c3RhdGljIGNhbGVuZGFyU3ltYm9scyhlKXtyZXR1cm4gbmV3IENhbGVuZGFyU3ltYm9scyhlKX1zdGF0aWMgY3VycmVuY3lTeW1ib2woZSl7cmV0dXJuIG5ldyBDdXJyZW5jeVN5bWJvbChlKX1zdGF0aWMgY3VycmVuY3lTeW1ib2xzKGUpe3JldHVybiBuZXcgQ3VycmVuY3lTeW1ib2xzKGUpfXN0YXRpYyBkYXRlUGF0dGVybihlKXtyZXR1cm4gbmV3IERhdGVQYXR0ZXJuKGUpfXN0YXRpYyBkYXRlUGF0dGVybnMoZSl7cmV0dXJuIG5ldyBEYXRlUGF0dGVybnMoZSl9c3RhdGljIGRhdGVUaW1lU3ltYm9scyhlKXtyZXR1cm4gbmV3IERhdGVUaW1lU3ltYm9scyhlKX1zdGF0aWMgZGF5KGUpe3JldHVybiBuZXcgRGF5KGUpfXN0YXRpYyBkYXlOYW1lcyhlKXtyZXR1cm4gbmV3IERheU5hbWVzKGUpfXN0YXRpYyBlcmEoZSl7cmV0dXJuIG5ldyBFcmEoZSl9c3RhdGljIGVyYU5hbWVzKGUpe3JldHVybiBuZXcgRXJhTmFtZXMoZSl9c3RhdGljIGxvY2FsZShlKXtyZXR1cm4gbmV3IGxvY2FsZV9zZXRfTG9jYWxlKGUpfXN0YXRpYyBsb2NhbGVTZXQoZSl7cmV0dXJuIG5ldyBsb2NhbGVfc2V0X0xvY2FsZVNldChlKX1zdGF0aWMgbWVyaWRpZW0oZSl7cmV0dXJuIG5ldyBNZXJpZGllbShlKX1zdGF0aWMgbWVyaWRpZW1OYW1lcyhlKXtyZXR1cm4gbmV3IE1lcmlkaWVtTmFtZXMoZSl9c3RhdGljIG1vbnRoKGUpe3JldHVybiBuZXcgTW9udGgoZSl9c3RhdGljIG1vbnRoTmFtZXMoZSl7cmV0dXJuIG5ldyBNb250aE5hbWVzKGUpfXN0YXRpYyBudW1iZXJQYXR0ZXJuKGUpe3JldHVybiBuZXcgTnVtYmVyUGF0dGVybihlKX1zdGF0aWMgbnVtYmVyUGF0dGVybnMoZSl7cmV0dXJuIG5ldyBOdW1iZXJQYXR0ZXJucyhlKX1zdGF0aWMgbnVtYmVyU3ltYm9sKGUpe3JldHVybiBuZXcgTnVtYmVyU3ltYm9sKGUpfXN0YXRpYyBudW1iZXJTeW1ib2xzKGUpe3JldHVybiBuZXcgTnVtYmVyU3ltYm9scyhlKX1zdGF0aWMgdGltZVBhdHRlcm4oZSl7cmV0dXJuIG5ldyBUaW1lUGF0dGVybihlKX1zdGF0aWMgdGltZVBhdHRlcm5zKGUpe3JldHVybiBuZXcgVGltZVBhdHRlcm5zKGUpfXN0YXRpYyB0eXBlRmFjZShlKXtyZXR1cm4gbmV3IFR5cGVGYWNlKGUpfXN0YXRpYyB0eXBlRmFjZXMoZSl7cmV0dXJuIG5ldyBUeXBlRmFjZXMoZSl9fWNvbnN0IFdvPWVvLnNpZ25hdHVyZS5pZDtjbGFzcyBzaWduYXR1cmVfU2lnbmF0dXJlIGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKFdvLCJzaWduYXR1cmUiLCEwKX19Y2xhc3MgU2lnbmF0dXJlTmFtZXNwYWNle3N0YXRpY1tRc10oZSx0KXtpZihTaWduYXR1cmVOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkoZSkpcmV0dXJuIFNpZ25hdHVyZU5hbWVzcGFjZVtlXSh0KX1zdGF0aWMgc2lnbmF0dXJlKGUpe3JldHVybiBuZXcgc2lnbmF0dXJlX1NpZ25hdHVyZShlKX19Y29uc3Qgem89ZW8uc3R5bGVzaGVldC5pZDtjbGFzcyBTdHlsZXNoZWV0IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKHpvLCJzdHlsZXNoZWV0IiwhMCl9fWNsYXNzIFN0eWxlc2hlZXROYW1lc3BhY2V7c3RhdGljW1FzXShlLHQpe2lmKFN0eWxlc2hlZXROYW1lc3BhY2UuaGFzT3duUHJvcGVydHkoZSkpcmV0dXJuIFN0eWxlc2hlZXROYW1lc3BhY2VbZV0odCl9c3RhdGljIHN0eWxlc2hlZXQoZSl7cmV0dXJuIG5ldyBTdHlsZXNoZWV0KGUpfX1jb25zdCBHbz1lby54ZHAuaWQ7Y2xhc3MgeGRwX1hkcCBleHRlbmRzIFhGQU9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihHbywieGRwIiwhMCk7dGhpcy51dWlkPWUudXVpZHx8IiI7dGhpcy50aW1lU3RhbXA9ZS50aW1lU3RhbXB8fCIiO3RoaXMuY29uZmlnPW51bGw7dGhpcy5jb25uZWN0aW9uU2V0PW51bGw7dGhpcy5kYXRhc2V0cz1udWxsO3RoaXMubG9jYWxlU2V0PW51bGw7dGhpcy5zdHlsZXNoZWV0PW5ldyBYRkFPYmplY3RBcnJheTt0aGlzLnRlbXBsYXRlPW51bGx9W1JzXShlKXtjb25zdCB0PWVvW2VbTXNdXTtyZXR1cm4gdCYmZVtPc109PT10LmlkfX1jbGFzcyBYZHBOYW1lc3BhY2V7c3RhdGljW1FzXShlLHQpe2lmKFhkcE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShlKSlyZXR1cm4gWGRwTmFtZXNwYWNlW2VdKHQpfXN0YXRpYyB4ZHAoZSl7cmV0dXJuIG5ldyB4ZHBfWGRwKGUpfX1jb25zdCAkbz1lby54aHRtbC5pZCxWbz1TeW1ib2woKSxLbz1uZXcgU2V0KFsiY29sb3IiLCJmb250IiwiZm9udC1mYW1pbHkiLCJmb250LXNpemUiLCJmb250LXN0cmV0Y2giLCJmb250LXN0eWxlIiwiZm9udC13ZWlnaHQiLCJtYXJnaW4iLCJtYXJnaW4tYm90dG9tIiwibWFyZ2luLWxlZnQiLCJtYXJnaW4tcmlnaHQiLCJtYXJnaW4tdG9wIiwibGV0dGVyLXNwYWNpbmciLCJsaW5lLWhlaWdodCIsIm9ycGhhbnMiLCJwYWdlLWJyZWFrLWFmdGVyIiwicGFnZS1icmVhay1iZWZvcmUiLCJwYWdlLWJyZWFrLWluc2lkZSIsInRhYi1pbnRlcnZhbCIsInRhYi1zdG9wIiwidGV4dC1hbGlnbiIsInRleHQtZGVjb3JhdGlvbiIsInRleHQtaW5kZW50IiwidmVydGljYWwtYWxpZ24iLCJ3aWRvd3MiLCJrZXJuaW5nLW1vZGUiLCJ4ZmEtZm9udC1ob3Jpem9udGFsLXNjYWxlIiwieGZhLWZvbnQtdmVydGljYWwtc2NhbGUiLCJ4ZmEtc3BhY2VydW4iLCJ4ZmEtdGFiLXN0b3BzIl0pLEpvPW5ldyBNYXAoW1sicGFnZS1icmVhay1hZnRlciIsImJyZWFrQWZ0ZXIiXSxbInBhZ2UtYnJlYWstYmVmb3JlIiwiYnJlYWtCZWZvcmUiXSxbInBhZ2UtYnJlYWstaW5zaWRlIiwiYnJlYWtJbnNpZGUiXSxbImtlcm5pbmctbW9kZSIsZT0+Im5vbmUiPT09ZT8ibm9uZSI6Im5vcm1hbCJdLFsieGZhLWZvbnQtaG9yaXpvbnRhbC1zY2FsZSIsZT0+YHNjYWxlWCgke01hdGgubWF4KDAscGFyc2VJbnQoZSkvMTAwKS50b0ZpeGVkKDIpfSlgXSxbInhmYS1mb250LXZlcnRpY2FsLXNjYWxlIixlPT5gc2NhbGVZKCR7TWF0aC5tYXgoMCxwYXJzZUludChlKS8xMDApLnRvRml4ZWQoMil9KWBdLFsieGZhLXNwYWNlcnVuIiwiIl0sWyJ4ZmEtdGFiLXN0b3BzIiwiIl0sWyJmb250LXNpemUiLChlLHQpPT5tZWFzdXJlVG9TdHJpbmcoLjk5KihlPXQuZm9udFNpemU9TWF0aC5hYnMoZ2V0TWVhc3VyZW1lbnQoZSkpKSldLFsibGV0dGVyLXNwYWNpbmciLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsibGluZS1oZWlnaHQiLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsibWFyZ2luIixlPT5tZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQoZSkpXSxbIm1hcmdpbi1ib3R0b20iLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsibWFyZ2luLWxlZnQiLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsibWFyZ2luLXJpZ2h0IixlPT5tZWFzdXJlVG9TdHJpbmcoZ2V0TWVhc3VyZW1lbnQoZSkpXSxbIm1hcmdpbi10b3AiLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsidGV4dC1pbmRlbnQiLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldLFsiZm9udC1mYW1pbHkiLGU9PmVdLFsidmVydGljYWwtYWxpZ24iLGU9Pm1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudChlKSldXSksWW89L1xzKy9nLFpvPS9bXHJcbl0rL2csUW89L1xyXG4/L2c7ZnVuY3Rpb24gbWFwU3R5bGUoZSx0LHIpe2NvbnN0IGE9T2JqZWN0LmNyZWF0ZShudWxsKTtpZighZSlyZXR1cm4gYTtjb25zdCBuPU9iamVjdC5jcmVhdGUobnVsbCk7Zm9yKGNvbnN0W3Qscl1vZiBlLnNwbGl0KCI7IikubWFwKGU9PmUuc3BsaXQoIjoiLDIpKSl7Y29uc3QgZT1Kby5nZXQodCk7aWYoIiI9PT1lKWNvbnRpbnVlO2xldCBpPXI7ZSYmKGk9InN0cmluZyI9PXR5cGVvZiBlP2U6ZShyLG4pKTt0LmVuZHNXaXRoKCJzY2FsZSIpP2EudHJhbnNmb3JtPWEudHJhbnNmb3JtP2Ake2FbdF19ICR7aX1gOmk6YVt0LnJlcGxhY2VBbGwoLy0oW2EtekEtWl0pL2csKGUsdCk9PnQudG9VcHBlckNhc2UoKSldPWl9YS5mb250RmFtaWx5JiZzZXRGb250RmFtaWx5KHt0eXBlZmFjZTphLmZvbnRGYW1pbHksd2VpZ2h0OmEuZm9udFdlaWdodHx8Im5vcm1hbCIscG9zdHVyZTphLmZvbnRTdHlsZXx8Im5vcm1hbCIsc2l6ZTpuLmZvbnRTaXplfHwwfSx0LHRbZ3NdLmZvbnRGaW5kZXIsYSk7aWYociYmYS52ZXJ0aWNhbEFsaWduJiYiMHB4IiE9PWEudmVydGljYWxBbGlnbiYmYS5mb250U2l6ZSl7Y29uc3QgZT0uNTgzLHQ9LjMzMyxyPWdldE1lYXN1cmVtZW50KGEuZm9udFNpemUpO2EuZm9udFNpemU9bWVhc3VyZVRvU3RyaW5nKHIqZSk7YS52ZXJ0aWNhbEFsaWduPW1lYXN1cmVUb1N0cmluZyhNYXRoLnNpZ24oZ2V0TWVhc3VyZW1lbnQoYS52ZXJ0aWNhbEFsaWduKSkqcip0KX1yJiZhLmZvbnRTaXplJiYoYS5mb250U2l6ZT1gY2FsYygke2EuZm9udFNpemV9ICogdmFyKC0tdG90YWwtc2NhbGUtZmFjdG9yKSlgKTtmaXhUZXh0SW5kZW50KGEpO3JldHVybiBhfWNvbnN0IGVjPW5ldyBTZXQoWyJib2R5IiwiaHRtbCJdKTtjbGFzcyBYaHRtbE9iamVjdCBleHRlbmRzIFhtbE9iamVjdHtjb25zdHJ1Y3RvcihlLHQpe3N1cGVyKCRvLHQpO3RoaXNbVm9dPSExO3RoaXMuc3R5bGU9ZS5zdHlsZXx8IiJ9W1hpXShlKXtzdXBlcltYaV0oZSk7dGhpcy5zdHlsZT1mdW5jdGlvbiBjaGVja1N0eWxlKGUpe3JldHVybiBlLnN0eWxlP2Uuc3R5bGUuc3BsaXQoIjsiKS5maWx0ZXIoZT0+ISFlLnRyaW0oKSkubWFwKGU9PmUuc3BsaXQoIjoiLDIpLm1hcChlPT5lLnRyaW0oKSkpLmZpbHRlcigoW3Qscl0pPT57ImZvbnQtZmFtaWx5Ij09PXQmJmVbZ3NdLnVzZWRUeXBlZmFjZXMuYWRkKHIpO3JldHVybiBLby5oYXModCl9KS5tYXAoZT0+ZS5qb2luKCI6IikpLmpvaW4oIjsiKToiIn0odGhpcyl9W1BpXSgpe3JldHVybiFlYy5oYXModGhpc1tNc10pfVtFc10oZSx0PSExKXtpZih0KXRoaXNbVm9dPSEwO2Vsc2V7ZT1lLnJlcGxhY2VBbGwoWm8sIiIpO3RoaXMuc3R5bGUuaW5jbHVkZXMoInhmYS1zcGFjZXJ1bjp5ZXMiKXx8KGU9ZS5yZXBsYWNlQWxsKFlvLCIgIikpfWUmJih0aGlzWyRpXSs9ZSl9W05zXShlLHQ9ITApe2NvbnN0IHI9T2JqZWN0LmNyZWF0ZShudWxsKSxhPXt0b3A6TmFOLGJvdHRvbTpOYU4sbGVmdDpOYU4scmlnaHQ6TmFOfTtsZXQgbj1udWxsO2Zvcihjb25zdFtlLHRdb2YgdGhpcy5zdHlsZS5zcGxpdCgiOyIpLm1hcChlPT5lLnNwbGl0KCI6IiwyKSkpc3dpdGNoKGUpe2Nhc2UiZm9udC1mYW1pbHkiOnIudHlwZWZhY2U9c3RyaXBRdW90ZXModCk7YnJlYWs7Y2FzZSJmb250LXNpemUiOnIuc2l6ZT1nZXRNZWFzdXJlbWVudCh0KTticmVhaztjYXNlImZvbnQtd2VpZ2h0IjpyLndlaWdodD10O2JyZWFrO2Nhc2UiZm9udC1zdHlsZSI6ci5wb3N0dXJlPXQ7YnJlYWs7Y2FzZSJsZXR0ZXItc3BhY2luZyI6ci5sZXR0ZXJTcGFjaW5nPWdldE1lYXN1cmVtZW50KHQpO2JyZWFrO2Nhc2UibWFyZ2luIjpjb25zdCBlPXQuc3BsaXQoLyBcdC8pLm1hcChlPT5nZXRNZWFzdXJlbWVudChlKSk7c3dpdGNoKGUubGVuZ3RoKXtjYXNlIDE6YS50b3A9YS5ib3R0b209YS5sZWZ0PWEucmlnaHQ9ZVswXTticmVhaztjYXNlIDI6YS50b3A9YS5ib3R0b209ZVswXTthLmxlZnQ9YS5yaWdodD1lWzFdO2JyZWFrO2Nhc2UgMzphLnRvcD1lWzBdO2EuYm90dG9tPWVbMl07YS5sZWZ0PWEucmlnaHQ9ZVsxXTticmVhaztjYXNlIDQ6YS50b3A9ZVswXTthLmxlZnQ9ZVsxXTthLmJvdHRvbT1lWzJdO2EucmlnaHQ9ZVszXX1icmVhaztjYXNlIm1hcmdpbi10b3AiOmEudG9wPWdldE1lYXN1cmVtZW50KHQpO2JyZWFrO2Nhc2UibWFyZ2luLWJvdHRvbSI6YS5ib3R0b209Z2V0TWVhc3VyZW1lbnQodCk7YnJlYWs7Y2FzZSJtYXJnaW4tbGVmdCI6YS5sZWZ0PWdldE1lYXN1cmVtZW50KHQpO2JyZWFrO2Nhc2UibWFyZ2luLXJpZ2h0IjphLnJpZ2h0PWdldE1lYXN1cmVtZW50KHQpO2JyZWFrO2Nhc2UibGluZS1oZWlnaHQiOm49Z2V0TWVhc3VyZW1lbnQodCl9ZS5wdXNoRGF0YShyLGEsbik7aWYodGhpc1skaV0pZS5hZGRTdHJpbmcodGhpc1skaV0pO2Vsc2UgZm9yKGNvbnN0IHQgb2YgdGhpc1tjc10oKSkiI3RleHQiIT09dFtNc10/dFtOc10oZSk6ZS5hZGRTdHJpbmcodFskaV0pO3QmJmUucG9wRm9udCgpfVtLc10oZSl7Y29uc3QgdD1bXTt0aGlzW0ppXT17Y2hpbGRyZW46dH07dGhpc1txaV0oe30pO2lmKDA9PT10Lmxlbmd0aCYmIXRoaXNbJGldKXJldHVybiBIVE1MUmVzdWx0LkVNUFRZO2xldCByO3I9dGhpc1tWb10/dGhpc1skaV0/dGhpc1skaV0ucmVwbGFjZUFsbChRbywiXG4iKTp2b2lkIDA6dGhpc1skaV18fHZvaWQgMDtyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOnRoaXNbTXNdLGF0dHJpYnV0ZXM6e2hyZWY6dGhpcy5ocmVmLHN0eWxlOm1hcFN0eWxlKHRoaXMuc3R5bGUsdGhpcyx0aGlzW1ZvXSl9LGNoaWxkcmVuOnQsdmFsdWU6cn0pfX1jbGFzcyBBIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiYSIpO3RoaXMuaHJlZj1maXhVUkwoZS5ocmVmKXx8IiJ9fWNsYXNzIEIgZXh0ZW5kcyBYaHRtbE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJiIil9W05zXShlKXtlLnB1c2hGb250KHt3ZWlnaHQ6ImJvbGQifSk7c3VwZXJbTnNdKGUpO2UucG9wRm9udCgpfX1jbGFzcyBCb2R5IGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiYm9keSIpfVtLc10oZSl7Y29uc3QgdD1zdXBlcltLc10oZSkse2h0bWw6cn09dDtpZighcilyZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTtyLm5hbWU9ImRpdiI7ci5hdHRyaWJ1dGVzLmNsYXNzPVsieGZhUmljaCJdO3JldHVybiB0fX1jbGFzcyBCciBleHRlbmRzIFhodG1sT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUsImJyIil9WyRzXSgpe3JldHVybiJcbiJ9W05zXShlKXtlLmFkZFN0cmluZygiXG4iKX1bS3NdKGUpe3JldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moe25hbWU6ImJyIn0pfX1jbGFzcyBIdG1sIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwiaHRtbCIpfVtLc10oZSl7Y29uc3QgdD1bXTt0aGlzW0ppXT17Y2hpbGRyZW46dH07dGhpc1txaV0oe30pO2lmKDA9PT10Lmxlbmd0aClyZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhUmljaCJdLHN0eWxlOnt9fSx2YWx1ZTp0aGlzWyRpXXx8IiJ9KTtpZigxPT09dC5sZW5ndGgpe2NvbnN0IGU9dFswXTtpZihlLmF0dHJpYnV0ZXM/LmNsYXNzLmluY2x1ZGVzKCJ4ZmFSaWNoIikpcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhlKX1yZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHtuYW1lOiJkaXYiLGF0dHJpYnV0ZXM6e2NsYXNzOlsieGZhUmljaCJdLHN0eWxlOnt9fSxjaGlsZHJlbjp0fSl9fWNsYXNzIEkgZXh0ZW5kcyBYaHRtbE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJpIil9W05zXShlKXtlLnB1c2hGb250KHtwb3N0dXJlOiJpdGFsaWMifSk7c3VwZXJbTnNdKGUpO2UucG9wRm9udCgpfX1jbGFzcyBMaSBleHRlbmRzIFhodG1sT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUsImxpIil9fWNsYXNzIE9sIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwib2wiKX19Y2xhc3MgUCBleHRlbmRzIFhodG1sT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUsInAiKX1bTnNdKGUpe3N1cGVyW05zXShlLCExKTtlLmFkZFN0cmluZygiXG4iKTtlLmFkZFBhcmEoKTtlLnBvcEZvbnQoKX1bJHNdKCl7cmV0dXJuIHRoaXNbZHNdKClbY3NdKCkuYXQoLTEpPT09dGhpcz9zdXBlclskc10oKTpzdXBlclskc10oKSsiXG4ifX1jbGFzcyBTcGFuIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwic3BhbiIpfX1jbGFzcyBTdWIgZXh0ZW5kcyBYaHRtbE9iamVjdHtjb25zdHJ1Y3RvcihlKXtzdXBlcihlLCJzdWIiKX19Y2xhc3MgU3VwIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwic3VwIil9fWNsYXNzIFVsIGV4dGVuZHMgWGh0bWxPYmplY3R7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSwidWwiKX19Y2xhc3MgWGh0bWxOYW1lc3BhY2V7c3RhdGljW1FzXShlLHQpe2lmKFhodG1sTmFtZXNwYWNlLmhhc093blByb3BlcnR5KGUpKXJldHVybiBYaHRtbE5hbWVzcGFjZVtlXSh0KX1zdGF0aWMgYShlKXtyZXR1cm4gbmV3IEEoZSl9c3RhdGljIGIoZSl7cmV0dXJuIG5ldyBCKGUpfXN0YXRpYyBib2R5KGUpe3JldHVybiBuZXcgQm9keShlKX1zdGF0aWMgYnIoZSl7cmV0dXJuIG5ldyBCcihlKX1zdGF0aWMgaHRtbChlKXtyZXR1cm4gbmV3IEh0bWwoZSl9c3RhdGljIGkoZSl7cmV0dXJuIG5ldyBJKGUpfXN0YXRpYyBsaShlKXtyZXR1cm4gbmV3IExpKGUpfXN0YXRpYyBvbChlKXtyZXR1cm4gbmV3IE9sKGUpfXN0YXRpYyBwKGUpe3JldHVybiBuZXcgUChlKX1zdGF0aWMgc3BhbihlKXtyZXR1cm4gbmV3IFNwYW4oZSl9c3RhdGljIHN1YihlKXtyZXR1cm4gbmV3IFN1YihlKX1zdGF0aWMgc3VwKGUpe3JldHVybiBuZXcgU3VwKGUpfXN0YXRpYyB1bChlKXtyZXR1cm4gbmV3IFVsKGUpfX1jb25zdCB0Yz17Y29uZmlnOkNvbmZpZ05hbWVzcGFjZSxjb25uZWN0aW9uOkNvbm5lY3Rpb25TZXROYW1lc3BhY2UsZGF0YXNldHM6RGF0YXNldHNOYW1lc3BhY2UsbG9jYWxlU2V0OkxvY2FsZVNldE5hbWVzcGFjZSxzaWduYXR1cmU6U2lnbmF0dXJlTmFtZXNwYWNlLHN0eWxlc2hlZXQ6U3R5bGVzaGVldE5hbWVzcGFjZSx0ZW1wbGF0ZTpUZW1wbGF0ZU5hbWVzcGFjZSx4ZHA6WGRwTmFtZXNwYWNlLHhodG1sOlhodG1sTmFtZXNwYWNlfTtjbGFzcyBVbmtub3duTmFtZXNwYWNle2NvbnN0cnVjdG9yKGUpe3RoaXMubmFtZXNwYWNlSWQ9ZX1bUXNdKGUsdCl7cmV0dXJuIG5ldyBYbWxPYmplY3QodGhpcy5uYW1lc3BhY2VJZCxlLHQpfX1jbGFzcyBSb290IGV4dGVuZHMgWEZBT2JqZWN0e2NvbnN0cnVjdG9yKGUpe3N1cGVyKC0xLCJyb290IixPYmplY3QuY3JlYXRlKG51bGwpKTt0aGlzLmVsZW1lbnQ9bnVsbDt0aGlzW21zXT1lfVtCc10oZSl7dGhpcy5lbGVtZW50PWU7cmV0dXJuITB9W1lpXSgpe3N1cGVyW1lpXSgpO2lmKHRoaXMuZWxlbWVudC50ZW1wbGF0ZSBpbnN0YW5jZW9mIFRlbXBsYXRlKXt0aGlzW21zXS5zZXQoVXMsdGhpcy5lbGVtZW50KTt0aGlzLmVsZW1lbnQudGVtcGxhdGVbcXNdKHRoaXNbbXNdKTt0aGlzLmVsZW1lbnQudGVtcGxhdGVbbXNdPXRoaXNbbXNdfX19Y2xhc3MgRW1wdHkgZXh0ZW5kcyBYRkFPYmplY3R7Y29uc3RydWN0b3IoKXtzdXBlcigtMSwiIixPYmplY3QuY3JlYXRlKG51bGwpKX1bQnNdKGUpe3JldHVybiExfX1jbGFzcyBCdWlsZGVye2NvbnN0cnVjdG9yKGU9bnVsbCl7dGhpcy5fbmFtZXNwYWNlU3RhY2s9W107dGhpcy5fbnNBZ25vc3RpY0xldmVsPTA7dGhpcy5fbmFtZXNwYWNlUHJlZml4ZXM9bmV3IE1hcDt0aGlzLl9uYW1lc3BhY2VzPW5ldyBNYXA7dGhpcy5fbmV4dE5zSWQ9TWF0aC5tYXgoLi4uT2JqZWN0LnZhbHVlcyhlbykubWFwKCh7aWQ6ZX0pPT5lKSk7dGhpcy5fY3VycmVudE5hbWVzcGFjZT1lfHxuZXcgVW5rbm93bk5hbWVzcGFjZSgrK3RoaXMuX25leHROc0lkKX1idWlsZFJvb3QoZSl7cmV0dXJuIG5ldyBSb290KGUpfWJ1aWxkKHtuc1ByZWZpeDplLG5hbWU6dCxhdHRyaWJ1dGVzOnIsbmFtZXNwYWNlOmEscHJlZml4ZXM6bn0pe2NvbnN0IGk9bnVsbCE9PWE7aWYoaSl7dGhpcy5fbmFtZXNwYWNlU3RhY2sucHVzaCh0aGlzLl9jdXJyZW50TmFtZXNwYWNlKTt0aGlzLl9jdXJyZW50TmFtZXNwYWNlPXRoaXMuX3NlYXJjaE5hbWVzcGFjZShhKX1uJiZ0aGlzLl9hZGROYW1lc3BhY2VQcmVmaXgobik7aWYoci5oYXNPd25Qcm9wZXJ0eShEcykpe2NvbnN0IGU9dGMuZGF0YXNldHMsdD1yW0RzXTtsZXQgYT1udWxsO2Zvcihjb25zdFtyLG5db2YgT2JqZWN0LmVudHJpZXModCkpe2lmKHRoaXMuX2dldE5hbWVzcGFjZVRvVXNlKHIpPT09ZSl7YT17eGZhOm59O2JyZWFrfX1hP3JbRHNdPWE6ZGVsZXRlIHJbRHNdfWNvbnN0IHM9dGhpcy5fZ2V0TmFtZXNwYWNlVG9Vc2UoZSksbz1zPy5bUXNdKHQscil8fG5ldyBFbXB0eTtvW2tzXSgpJiZ0aGlzLl9uc0Fnbm9zdGljTGV2ZWwrKzsoaXx8bnx8b1trc10oKSkmJihvW1dpXT17aGFzTmFtZXNwYWNlOmkscHJlZml4ZXM6bixuc0Fnbm9zdGljOm9ba3NdKCl9KTtyZXR1cm4gb31pc05zQWdub3N0aWMoKXtyZXR1cm4gdGhpcy5fbnNBZ25vc3RpY0xldmVsPjB9X3NlYXJjaE5hbWVzcGFjZShlKXtsZXQgdD10aGlzLl9uYW1lc3BhY2VzLmdldChlKTtpZih0KXJldHVybiB0O2Zvcihjb25zdFtyLHtjaGVjazphfV1vZiBPYmplY3QuZW50cmllcyhlbykpaWYoYShlKSl7dD10Y1tyXTtpZih0KXt0aGlzLl9uYW1lc3BhY2VzLnNldChlLHQpO3JldHVybiB0fWJyZWFrfXQ9bmV3IFVua25vd25OYW1lc3BhY2UoKyt0aGlzLl9uZXh0TnNJZCk7dGhpcy5fbmFtZXNwYWNlcy5zZXQoZSx0KTtyZXR1cm4gdH1fYWRkTmFtZXNwYWNlUHJlZml4KGUpe2Zvcihjb25zdHtwcmVmaXg6dCx2YWx1ZTpyfW9mIGUpe2NvbnN0IGU9dGhpcy5fc2VhcmNoTmFtZXNwYWNlKHIpO2xldCBhPXRoaXMuX25hbWVzcGFjZVByZWZpeGVzLmdldCh0KTtpZighYSl7YT1bXTt0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5zZXQodCxhKX1hLnB1c2goZSl9fV9nZXROYW1lc3BhY2VUb1VzZShlKXtpZighZSlyZXR1cm4gdGhpcy5fY3VycmVudE5hbWVzcGFjZTtjb25zdCB0PXRoaXMuX25hbWVzcGFjZVByZWZpeGVzLmdldChlKTtpZih0Py5sZW5ndGg+MClyZXR1cm4gdC5hdCgtMSk7d2FybihgVW5rbm93biBuYW1lc3BhY2UgcHJlZml4OiAke2V9LmApO3JldHVybiBudWxsfWNsZWFuKGUpe2NvbnN0e2hhc05hbWVzcGFjZTp0LHByZWZpeGVzOnIsbnNBZ25vc3RpYzphfT1lO3QmJih0aGlzLl9jdXJyZW50TmFtZXNwYWNlPXRoaXMuX25hbWVzcGFjZVN0YWNrLnBvcCgpKTtyJiZyLmZvckVhY2goKHtwcmVmaXg6ZX0pPT57dGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMuZ2V0KGUpLnBvcCgpfSk7YSYmdGhpcy5fbnNBZ25vc3RpY0xldmVsLS19fWNsYXNzIFhGQVBhcnNlciBleHRlbmRzIFhNTFBhcnNlckJhc2V7Y29uc3RydWN0b3IoZT1udWxsLHQ9ITEpe3N1cGVyKCk7dGhpcy5fYnVpbGRlcj1uZXcgQnVpbGRlcihlKTt0aGlzLl9zdGFjaz1bXTt0aGlzLl9nbG9iYWxEYXRhPXt1c2VkVHlwZWZhY2VzOm5ldyBTZXR9O3RoaXMuX2lkcz1uZXcgTWFwO3RoaXMuX2N1cnJlbnQ9dGhpcy5fYnVpbGRlci5idWlsZFJvb3QodGhpcy5faWRzKTt0aGlzLl9lcnJvckNvZGU9a2k7dGhpcy5fd2hpdGVSZWdleD0vXlxzKyQvO3RoaXMuX25ic3BzPS9ceGEwKy9nO3RoaXMuX3JpY2hUZXh0PXR9cGFyc2UoZSl7dGhpcy5wYXJzZVhtbChlKTtpZih0aGlzLl9lcnJvckNvZGU9PT1raSl7dGhpcy5fY3VycmVudFtZaV0oKTtyZXR1cm4gdGhpcy5fY3VycmVudC5lbGVtZW50fX1vblRleHQoZSl7ZT1lLnJlcGxhY2UodGhpcy5fbmJzcHMsZT0+ZS5zbGljZSgxKSsiICIpO3RoaXMuX3JpY2hUZXh0fHx0aGlzLl9jdXJyZW50W1BpXSgpP3RoaXMuX2N1cnJlbnRbRXNdKGUsdGhpcy5fcmljaFRleHQpOnRoaXMuX3doaXRlUmVnZXgudGVzdChlKXx8dGhpcy5fY3VycmVudFtFc10oZS50cmltKCkpfW9uQ2RhdGEoZSl7dGhpcy5fY3VycmVudFtFc10oZSl9X21rQXR0cmlidXRlcyhlLHQpe2xldCByPW51bGwsYT1udWxsO2NvbnN0IG49T2JqZWN0LmNyZWF0ZSh7fSk7Zm9yKGNvbnN0e25hbWU6aSx2YWx1ZTpzfW9mIGUpaWYoInhtbG5zIj09PWkpcj93YXJuKGBYRkEgLSBtdWx0aXBsZSBuYW1lc3BhY2UgZGVmaW5pdGlvbiBpbiA8JHt0fT5gKTpyPXM7ZWxzZSBpZihpLnN0YXJ0c1dpdGgoInhtbG5zOiIpKXtjb25zdCBlPWkuc3Vic3RyaW5nKDYpO2E/Pz1bXTthLnB1c2goe3ByZWZpeDplLHZhbHVlOnN9KX1lbHNle2NvbnN0IGU9aS5pbmRleE9mKCI6Iik7aWYoLTE9PT1lKW5baV09cztlbHNle2NvbnN0IHQ9bltEc10/Pz1PYmplY3QuY3JlYXRlKG51bGwpLFtyLGFdPVtpLnNsaWNlKDAsZSksaS5zbGljZShlKzEpXTsodFtyXXx8PU9iamVjdC5jcmVhdGUobnVsbCkpW2FdPXN9fXJldHVybltyLGEsbl19X2dldE5hbWVBbmRQcmVmaXgoZSx0KXtjb25zdCByPWUuaW5kZXhPZigiOiIpO3JldHVybi0xPT09cj9bZSxudWxsXTpbZS5zdWJzdHJpbmcocisxKSx0PyIiOmUuc3Vic3RyaW5nKDAscildfW9uQmVnaW5FbGVtZW50KGUsdCxyKXtjb25zdFthLG4saV09dGhpcy5fbWtBdHRyaWJ1dGVzKHQsZSksW3Msb109dGhpcy5fZ2V0TmFtZUFuZFByZWZpeChlLHRoaXMuX2J1aWxkZXIuaXNOc0Fnbm9zdGljKCkpLGM9dGhpcy5fYnVpbGRlci5idWlsZCh7bnNQcmVmaXg6byxuYW1lOnMsYXR0cmlidXRlczppLG5hbWVzcGFjZTphLHByZWZpeGVzOm59KTtjW2dzXT10aGlzLl9nbG9iYWxEYXRhO2lmKHIpe2NbWWldKCk7dGhpcy5fY3VycmVudFtCc10oYykmJmNbSHNdKHRoaXMuX2lkcyk7Y1tYaV0odGhpcy5fYnVpbGRlcil9ZWxzZXt0aGlzLl9zdGFjay5wdXNoKHRoaXMuX2N1cnJlbnQpO3RoaXMuX2N1cnJlbnQ9Y319b25FbmRFbGVtZW50KGUpe2NvbnN0IHQ9dGhpcy5fY3VycmVudDtpZih0W3dzXSgpJiYic3RyaW5nIj09dHlwZW9mIHRbJGldKXtjb25zdCBlPW5ldyBYRkFQYXJzZXI7ZS5fZ2xvYmFsRGF0YT10aGlzLl9nbG9iYWxEYXRhO2NvbnN0IHI9ZS5wYXJzZSh0WyRpXSk7dFskaV09bnVsbDt0W0JzXShyKX10W1lpXSgpO3RoaXMuX2N1cnJlbnQ9dGhpcy5fc3RhY2sucG9wKCk7dGhpcy5fY3VycmVudFtCc10odCkmJnRbSHNdKHRoaXMuX2lkcyk7dFtYaV0odGhpcy5fYnVpbGRlcil9b25FcnJvcihlKXt0aGlzLl9lcnJvckNvZGU9ZX19Y2xhc3MgWEZBRmFjdG9yeXtjb25zdHJ1Y3RvcihlKXt0cnl7dGhpcy5yb290PShuZXcgWEZBUGFyc2VyKS5wYXJzZShYRkFGYWN0b3J5Ll9jcmVhdGVEb2N1bWVudChlKSk7Y29uc3QgdD1uZXcgQmluZGVyKHRoaXMucm9vdCk7dGhpcy5mb3JtPXQuYmluZCgpO3RoaXMuZGF0YUhhbmRsZXI9bmV3IERhdGFIYW5kbGVyKHRoaXMucm9vdCx0LmdldERhdGEoKSk7dGhpcy5mb3JtW2dzXS50ZW1wbGF0ZT10aGlzLmZvcm19Y2F0Y2goZSl7d2FybihgWEZBIC0gYW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHBhcnNpbmcgYW5kIGJpbmRpbmc6ICR7ZX1gKX19aXNWYWxpZCgpe3JldHVybiEoIXRoaXMucm9vdHx8IXRoaXMuZm9ybSl9X2NyZWF0ZVBhZ2VzSGVscGVyKCl7Y29uc3QgZT10aGlzLmZvcm1bVnNdKCk7cmV0dXJuIG5ldyBQcm9taXNlKCh0LHIpPT57Y29uc3QgbmV4dEl0ZXJhdGlvbj0oKT0+e3RyeXtjb25zdCByPWUubmV4dCgpO3IuZG9uZT90KHIudmFsdWUpOnNldFRpbWVvdXQobmV4dEl0ZXJhdGlvbiwwKX1jYXRjaChlKXtyKGUpfX07c2V0VGltZW91dChuZXh0SXRlcmF0aW9uLDApfSl9YXN5bmMgX2NyZWF0ZVBhZ2VzKCl7dHJ5e3RoaXMucGFnZXM9YXdhaXQgdGhpcy5fY3JlYXRlUGFnZXNIZWxwZXIoKTt0aGlzLmRpbXM9dGhpcy5wYWdlcy5jaGlsZHJlbi5tYXAoZT0+e2NvbnN0e3dpZHRoOnQsaGVpZ2h0OnJ9PWUuYXR0cmlidXRlcy5zdHlsZTtyZXR1cm5bMCwwLHBhcnNlSW50KHQpLHBhcnNlSW50KHIpXX0pfWNhdGNoKGUpe3dhcm4oYFhGQSAtIGFuIGVycm9yIG9jY3VycmVkIGR1cmluZyBsYXlvdXQ6ICR7ZX1gKX19Z2V0Qm91bmRpbmdCb3goZSl7cmV0dXJuIHRoaXMuZGltc1tlXX1hc3luYyBnZXROdW1QYWdlcygpe3RoaXMucGFnZXN8fGF3YWl0IHRoaXMuX2NyZWF0ZVBhZ2VzKCk7cmV0dXJuIHRoaXMuZGltcy5sZW5ndGh9c2V0SW1hZ2VzKGUpe3RoaXMuZm9ybVtnc10uaW1hZ2VzPWV9c2V0Rm9udHMoZSl7dGhpcy5mb3JtW2dzXS5mb250RmluZGVyPW5ldyBGb250RmluZGVyKGUpO2NvbnN0IHQ9W107Zm9yKGxldCBlIG9mIHRoaXMuZm9ybVtnc10udXNlZFR5cGVmYWNlcyl7ZT1zdHJpcFF1b3RlcyhlKTt0aGlzLmZvcm1bZ3NdLmZvbnRGaW5kZXIuZmluZChlKXx8dC5wdXNoKGUpfXJldHVybiB0Lmxlbmd0aD4wP3Q6bnVsbH1hcHBlbmRGb250cyhlLHQpe3RoaXMuZm9ybVtnc10uZm9udEZpbmRlci5hZGQoZSx0KX1hc3luYyBnZXRQYWdlcygpe3RoaXMucGFnZXN8fGF3YWl0IHRoaXMuX2NyZWF0ZVBhZ2VzKCk7Y29uc3QgZT10aGlzLnBhZ2VzO3RoaXMucGFnZXM9bnVsbDtyZXR1cm4gZX1zZXJpYWxpemVEYXRhKGUpe3JldHVybiB0aGlzLmRhdGFIYW5kbGVyLnNlcmlhbGl6ZShlKX1zdGF0aWMgX2NyZWF0ZURvY3VtZW50KGUpe3JldHVybiBlWyIveGRwOnhkcCJdP09iamVjdC52YWx1ZXMoZSkuam9pbigiIik6ZVsieGRwOnhkcCJdfXN0YXRpYyBnZXRSaWNoVGV4dEFzSHRtbChlKXtpZighZXx8InN0cmluZyIhPXR5cGVvZiBlKXJldHVybiBudWxsO3RyeXtsZXQgdD1uZXcgWEZBUGFyc2VyKFhodG1sTmFtZXNwYWNlLCEwKS5wYXJzZShlKTtpZighWyJib2R5IiwieGh0bWwiXS5pbmNsdWRlcyh0W01zXSkpe2NvbnN0IGU9WGh0bWxOYW1lc3BhY2UuYm9keSh7fSk7ZVtqaV0odCk7dD1lfWNvbnN0IHI9dFtLc10oKTtpZighci5zdWNjZXNzKXJldHVybiBudWxsO2NvbnN0e2h0bWw6YX09cix7YXR0cmlidXRlczpufT1hO2lmKG4pe24uY2xhc3MmJihuLmNsYXNzPW4uY2xhc3MuZmlsdGVyKGU9PiFlLnN0YXJ0c1dpdGgoInhmYSIpKSk7bi5kaXI9ImF1dG8ifXJldHVybntodG1sOmEsc3RyOnRbJHNdKCl9fWNhdGNoKGUpe3dhcm4oYFhGQSAtIGFuIGVycm9yIG9jY3VycmVkIGR1cmluZyBwYXJzaW5nIG9mIHJpY2ggdGV4dDogJHtlfWApfXJldHVybiBudWxsfX1jbGFzcyBBbm5vdGF0aW9uRmFjdG9yeXtzdGF0aWMgY3JlYXRlR2xvYmFscyhlKXtyZXR1cm4gUHJvbWlzZS5hbGwoW2UuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm0iKSxlLmVuc3VyZURvYygieGZhRGF0YXNldHMiKSxlLmVuc3VyZUNhdGFsb2coInN0cnVjdFRyZWVSb290IiksZS5lbnN1cmVDYXRhbG9nKCJiYXNlVXJsIiksZS5lbnN1cmVDYXRhbG9nKCJhdHRhY2htZW50cyIpLGUuZW5zdXJlQ2F0YWxvZygiZ2xvYmFsQ29sb3JTcGFjZUNhY2hlIildKS50aGVuKChbdCxyLGEsbixpLHNdKT0+KHtwZGZNYW5hZ2VyOmUsYWNyb0Zvcm06dCBpbnN0YW5jZW9mIERpY3Q/dDpEaWN0LmVtcHR5LHhmYURhdGFzZXRzOnIsc3RydWN0VHJlZVJvb3Q6YSxiYXNlVXJsOm4sYXR0YWNobWVudHM6aSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6c30pLGU9Pnt3YXJuKGBjcmVhdGVHbG9iYWxzOiAiJHtlfSIuYCk7cmV0dXJuIG51bGx9KX1zdGF0aWMgYXN5bmMgY3JlYXRlKGUsdCxyLGEsbixpLHMsbyl7Y29uc3QgYz1uP2F3YWl0IHRoaXMuX2dldFBhZ2VJbmRleChlLHQsci5wZGZNYW5hZ2VyKTpudWxsO3JldHVybiByLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsIl9jcmVhdGUiLFtlLHQscixhLG4saSxzLGMsb10pfXN0YXRpYyBfY3JlYXRlKGUsdCxyLGEsbj0hMSxpPW51bGwscz1udWxsLG89bnVsbCxjPW51bGwpe2NvbnN0IGw9ZS5mZXRjaElmUmVmKHQpO2lmKCEobCBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtsZXQgaD1sLmdldCgiU3VidHlwZSIpO2g9aCBpbnN0YW5jZW9mIE5hbWU/aC5uYW1lOm51bGw7aWYocyYmIXMuaGFzKE1baC50b1VwcGVyQ2FzZSgpXSkpcmV0dXJuIG51bGw7Y29uc3R7YWNyb0Zvcm06dSxwZGZNYW5hZ2VyOmR9PXIsZj10IGluc3RhbmNlb2YgUmVmP3QudG9TdHJpbmcoKTpgYW5ub3RfJHthLmNyZWF0ZU9iaklkKCl9YCxnPXt4cmVmOmUscmVmOnQsZGljdDpsLHN1YnR5cGU6aCxpZDpmLGFubm90YXRpb25HbG9iYWxzOnIsY29sbGVjdEZpZWxkczpuLG9ycGhhbkZpZWxkczppLG5lZWRBcHBlYXJhbmNlczohbiYmITA9PT11LmdldCgiTmVlZEFwcGVhcmFuY2VzIikscGFnZUluZGV4Om8sZXZhbHVhdG9yT3B0aW9uczpkLmV2YWx1YXRvck9wdGlvbnMscGFnZVJlZjpjfTtzd2l0Y2goaCl7Y2FzZSJMaW5rIjpyZXR1cm4gbmV3IExpbmtBbm5vdGF0aW9uKGcpO2Nhc2UiVGV4dCI6cmV0dXJuIG5ldyBUZXh0QW5ub3RhdGlvbihnKTtjYXNlIldpZGdldCI6bGV0IGU9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDpsLGtleToiRlQifSk7ZT1lIGluc3RhbmNlb2YgTmFtZT9lLm5hbWU6bnVsbDtzd2l0Y2goZSl7Y2FzZSJUeCI6cmV0dXJuIG5ldyBUZXh0V2lkZ2V0QW5ub3RhdGlvbihnKTtjYXNlIkJ0biI6cmV0dXJuIG5ldyBCdXR0b25XaWRnZXRBbm5vdGF0aW9uKGcpO2Nhc2UiQ2giOnJldHVybiBuZXcgQ2hvaWNlV2lkZ2V0QW5ub3RhdGlvbihnKTtjYXNlIlNpZyI6cmV0dXJuIG5ldyBTaWduYXR1cmVXaWRnZXRBbm5vdGF0aW9uKGcpfXdhcm4oYFVuaW1wbGVtZW50ZWQgd2lkZ2V0IGZpZWxkIHR5cGUgIiR7ZX0iLCBmYWxsaW5nIGJhY2sgdG8gYmFzZSBmaWVsZCB0eXBlLmApO3JldHVybiBuZXcgV2lkZ2V0QW5ub3RhdGlvbihnKTtjYXNlIlBvcHVwIjpyZXR1cm4gbmV3IFBvcHVwQW5ub3RhdGlvbihnKTtjYXNlIkZyZWVUZXh0IjpyZXR1cm4gbmV3IEZyZWVUZXh0QW5ub3RhdGlvbihnKTtjYXNlIkxpbmUiOnJldHVybiBuZXcgTGluZUFubm90YXRpb24oZyk7Y2FzZSJTcXVhcmUiOnJldHVybiBuZXcgU3F1YXJlQW5ub3RhdGlvbihnKTtjYXNlIkNpcmNsZSI6cmV0dXJuIG5ldyBDaXJjbGVBbm5vdGF0aW9uKGcpO2Nhc2UiUG9seUxpbmUiOnJldHVybiBuZXcgUG9seWxpbmVBbm5vdGF0aW9uKGcpO2Nhc2UiUG9seWdvbiI6cmV0dXJuIG5ldyBQb2x5Z29uQW5ub3RhdGlvbihnKTtjYXNlIkNhcmV0IjpyZXR1cm4gbmV3IENhcmV0QW5ub3RhdGlvbihnKTtjYXNlIkluayI6cmV0dXJuIG5ldyBJbmtBbm5vdGF0aW9uKGcpO2Nhc2UiSGlnaGxpZ2h0IjpyZXR1cm4gbmV3IEhpZ2hsaWdodEFubm90YXRpb24oZyk7Y2FzZSJVbmRlcmxpbmUiOnJldHVybiBuZXcgVW5kZXJsaW5lQW5ub3RhdGlvbihnKTtjYXNlIlNxdWlnZ2x5IjpyZXR1cm4gbmV3IFNxdWlnZ2x5QW5ub3RhdGlvbihnKTtjYXNlIlN0cmlrZU91dCI6cmV0dXJuIG5ldyBTdHJpa2VPdXRBbm5vdGF0aW9uKGcpO2Nhc2UiU3RhbXAiOnJldHVybiBuZXcgU3RhbXBBbm5vdGF0aW9uKGcpO2Nhc2UiRmlsZUF0dGFjaG1lbnQiOnJldHVybiBuZXcgRmlsZUF0dGFjaG1lbnRBbm5vdGF0aW9uKGcpO2RlZmF1bHQ6bnx8d2FybihoP2BVbmltcGxlbWVudGVkIGFubm90YXRpb24gdHlwZSAiJHtofSIsIGZhbGxpbmcgYmFjayB0byBiYXNlIGFubm90YXRpb24uYDoiQW5ub3RhdGlvbiBpcyBtaXNzaW5nIHRoZSByZXF1aXJlZCAvU3VidHlwZS4iKTtyZXR1cm4gbmV3IEFubm90YXRpb24oZyl9fXN0YXRpYyBhc3luYyBfZ2V0UGFnZUluZGV4KGUsdCxyKXt0cnl7Y29uc3QgYT1hd2FpdCBlLmZldGNoSWZSZWZBc3luYyh0KTtpZighKGEgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm4tMTtjb25zdCBuPWEuZ2V0UmF3KCJQIik7aWYobiBpbnN0YW5jZW9mIFJlZil0cnl7cmV0dXJuIGF3YWl0IHIuZW5zdXJlQ2F0YWxvZygiZ2V0UGFnZUluZGV4Iixbbl0pfWNhdGNoKGUpe2luZm8oYF9nZXRQYWdlSW5kZXggLS0gbm90IGEgdmFsaWQgcGFnZSByZWZlcmVuY2U6ICIke2V9Ii5gKX1pZihhLmhhcygiS2lkcyIpKXJldHVybi0xO2NvbnN0IGk9YXdhaXQgci5lbnN1cmVEb2MoIm51bVBhZ2VzIik7Zm9yKGxldCBlPTA7ZTxpO2UrKyl7Y29uc3QgYT1hd2FpdCByLmdldFBhZ2UoZSksbj1hd2FpdCByLmVuc3VyZShhLCJhbm5vdGF0aW9ucyIpO2Zvcihjb25zdCByIG9mIG4paWYociBpbnN0YW5jZW9mIFJlZiYmaXNSZWZzRXF1YWwocix0KSlyZXR1cm4gZX19Y2F0Y2goZSl7d2FybihgX2dldFBhZ2VJbmRleDogIiR7ZX0iLmApfXJldHVybi0xfXN0YXRpYyBnZW5lcmF0ZUltYWdlcyhlLHQscil7aWYoIXIpe3dhcm4oImdlbmVyYXRlSW1hZ2VzOiBPZmZzY3JlZW5DYW52YXMgaXMgbm90IHN1cHBvcnRlZCwgY2Fubm90IHNhdmUgb3IgcHJpbnQgc29tZSBhbm5vdGF0aW9ucyB3aXRoIGltYWdlcy4iKTtyZXR1cm4gbnVsbH1sZXQgYTtmb3IoY29uc3R7Yml0bWFwSWQ6cixiaXRtYXA6bn1vZiBlKWlmKG4pe2F8fD1uZXcgTWFwO2Euc2V0KHIsU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZUltYWdlKG4sdCkpfXJldHVybiBhfXN0YXRpYyBhc3luYyBzYXZlTmV3QW5ub3RhdGlvbnMoZSx0LHIsYSxuKXtjb25zdCBpPWUueHJlZjtsZXQgcztjb25zdCBvPVtdLHtpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDpjfT1lLm9wdGlvbnM7Zm9yKGNvbnN0IGwgb2YgcilpZighbC5kZWxldGVkKXN3aXRjaChsLmFubm90YXRpb25UeXBlKXtjYXNlIG06aWYoIXMpe2NvbnN0IGU9bmV3IERpY3QoaSk7ZS5zZXRJZk5hbWUoIkJhc2VGb250IiwiSGVsdmV0aWNhIik7ZS5zZXRJZk5hbWUoIlR5cGUiLCJGb250Iik7ZS5zZXRJZk5hbWUoIlN1YnR5cGUiLCJUeXBlMSIpO2Uuc2V0SWZOYW1lKCJFbmNvZGluZyIsIldpbkFuc2lFbmNvZGluZyIpO3M9aS5nZXROZXdUZW1wb3JhcnlSZWYoKTtuLnB1dChzLHtkYXRhOmV9KX1vLnB1c2goRnJlZVRleHRBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oaSxsLG4se2V2YWx1YXRvcjplLHRhc2s6dCxiYXNlRm9udFJlZjpzfSkpO2JyZWFrO2Nhc2UgYjpsLnF1YWRQb2ludHM/by5wdXNoKEhpZ2hsaWdodEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbihpLGwsbikpOm8ucHVzaChJbmtBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oaSxsLG4pKTticmVhaztjYXNlIHc6by5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbihpLGwsbikpO2JyZWFrO2Nhc2UgeTpjb25zdCByPWM/YXdhaXQoYT8uZ2V0KGwuYml0bWFwSWQpKTpudWxsO2lmKHI/LmltYWdlU3RyZWFtKXtjb25zdHtpbWFnZVN0cmVhbTplLHNtYXNrU3RyZWFtOnR9PXI7aWYodCl7Y29uc3Qgcj1pLmdldE5ld1RlbXBvcmFyeVJlZigpO24ucHV0KHIse2RhdGE6dH0pO2UuZGljdC5zZXQoIlNNYXNrIixyKX1jb25zdCBhPXIuaW1hZ2VSZWY9aS5nZXROZXdUZW1wb3JhcnlSZWYoKTtuLnB1dChhLHtkYXRhOmV9KTtyLmltYWdlU3RyZWFtPXIuc21hc2tTdHJlYW09bnVsbH1vLnB1c2goU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZU5ld0Fubm90YXRpb24oaSxsLG4se2ltYWdlOnJ9KSk7YnJlYWs7Y2FzZSB4Om8ucHVzaChTdGFtcEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbihpLGwsbix7fSkpfXJldHVybnthbm5vdGF0aW9uczooYXdhaXQgUHJvbWlzZS5hbGwobykpLmZsYXQoKX19c3RhdGljIGFzeW5jIHByaW50TmV3QW5ub3RhdGlvbnMoZSx0LHIsYSxuKXtpZighYSlyZXR1cm4gbnVsbDtjb25zdHtvcHRpb25zOmkseHJlZjpzfT10LG89W107Zm9yKGNvbnN0IGMgb2YgYSlpZighYy5kZWxldGVkKXN3aXRjaChjLmFubm90YXRpb25UeXBlKXtjYXNlIG06by5wdXNoKEZyZWVUZXh0QW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oZSxzLGMse2V2YWx1YXRvcjp0LHRhc2s6cixldmFsdWF0b3JPcHRpb25zOml9KSk7YnJlYWs7Y2FzZSBiOmMucXVhZFBvaW50cz9vLnB1c2goSGlnaGxpZ2h0QW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oZSxzLGMse2V2YWx1YXRvck9wdGlvbnM6aX0pKTpvLnB1c2goSW5rQW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oZSxzLGMse2V2YWx1YXRvck9wdGlvbnM6aX0pKTticmVhaztjYXNlIHc6by5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGUscyxjLHtldmFsdWF0b3JPcHRpb25zOml9KSk7YnJlYWs7Y2FzZSB5OmNvbnN0IGE9aS5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZD9hd2FpdChuPy5nZXQoYy5iaXRtYXBJZCkpOm51bGw7aWYoYT8uaW1hZ2VTdHJlYW0pe2NvbnN0e2ltYWdlU3RyZWFtOmUsc21hc2tTdHJlYW06dH09YTt0JiZlLmRpY3Quc2V0KCJTTWFzayIsdCk7YS5pbWFnZVJlZj1uZXcgSnBlZ1N0cmVhbShlLGUubGVuZ3RoKTthLmltYWdlU3RyZWFtPWEuc21hc2tTdHJlYW09bnVsbH1vLnB1c2goU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihlLHMsYyx7aW1hZ2U6YSxldmFsdWF0b3JPcHRpb25zOml9KSk7YnJlYWs7Y2FzZSB4Om8ucHVzaChTdGFtcEFubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGUscyxjLHtldmFsdWF0b3JPcHRpb25zOml9KSl9cmV0dXJuIFByb21pc2UuYWxsKG8pfX1mdW5jdGlvbiBnZXRSZ2JDb2xvcihlLHQ9bmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpKXtpZighQXJyYXkuaXNBcnJheShlKSlyZXR1cm4gdDtjb25zdCByPXR8fG5ldyBVaW50OENsYW1wZWRBcnJheSgzKTtzd2l0Y2goZS5sZW5ndGgpe2Nhc2UgMDpyZXR1cm4gbnVsbDtjYXNlIDE6Q29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSXRlbShlLDAsciwwKTtyZXR1cm4gcjtjYXNlIDM6Q29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JJdGVtKGUsMCxyLDApO3JldHVybiByO2Nhc2UgNDpDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JJdGVtKGUsMCxyLDApO3JldHVybiByO2RlZmF1bHQ6cmV0dXJuIHR9fWZ1bmN0aW9uIGdldFBkZkNvbG9yQXJyYXkoZSx0PW51bGwpe3JldHVybiBlJiZBcnJheS5mcm9tKGUsZT0+ZS8yNTUpfHx0fWZ1bmN0aW9uIGdldFF1YWRQb2ludHMoZSx0KXtjb25zdCByPWUuZ2V0QXJyYXkoIlF1YWRQb2ludHMiKTtpZighaXNOdW1iZXJBcnJheShyLG51bGwpfHwwPT09ci5sZW5ndGh8fHIubGVuZ3RoJTg+MClyZXR1cm4gbnVsbDtjb25zdCBhPW5ldyBGbG9hdDMyQXJyYXkoci5sZW5ndGgpO2ZvcihsZXQgZT0wLG49ci5sZW5ndGg7ZTxuO2UrPTgpe2NvbnN0W24saSxzLG8sYyxsLGgsdV09ci5zbGljZShlLGUrOCksZD1NYXRoLm1pbihuLHMsYyxoKSxmPU1hdGgubWF4KG4scyxjLGgpLGc9TWF0aC5taW4oaSxvLGwsdSkscD1NYXRoLm1heChpLG8sbCx1KTtpZihudWxsIT09dCYmKGQ8dFswXXx8Zj50WzJdfHxnPHRbMV18fHA+dFszXSkpcmV0dXJuIG51bGw7YS5zZXQoW2QscCxmLHAsZCxnLGYsZ10sZSl9cmV0dXJuIGF9ZnVuY3Rpb24gZ2V0VHJhbnNmb3JtTWF0cml4KGUsdCxyKXtjb25zdCBhPW5ldyBGbG9hdDMyQXJyYXkoWzEvMCwxLzAsLTEvMCwtMS8wXSk7VXRpbC5heGlhbEFsaWduZWRCb3VuZGluZ0JveCh0LHIsYSk7Y29uc3RbbixpLHMsb109YTtpZihuPT09c3x8aT09PW8pcmV0dXJuWzEsMCwwLDEsZVswXSxlWzFdXTtjb25zdCBjPShlWzJdLWVbMF0pLyhzLW4pLGw9KGVbM10tZVsxXSkvKG8taSk7cmV0dXJuW2MsMCwwLGwsZVswXS1uKmMsZVsxXS1pKmxdfWNsYXNzIEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7Y29uc3R7ZGljdDp0LHhyZWY6cixhbm5vdGF0aW9uR2xvYmFsczphLHJlZjpuLG9ycGhhbkZpZWxkczppfT1lLHM9aT8uZ2V0KG4pO3MmJnQuc2V0KCJQYXJlbnQiLHMpO3RoaXMuc2V0VGl0bGUodC5nZXQoIlQiKSk7dGhpcy5zZXRDb250ZW50cyh0LmdldCgiQ29udGVudHMiKSk7dGhpcy5zZXRNb2RpZmljYXRpb25EYXRlKHQuZ2V0KCJNIikpO3RoaXMuc2V0RmxhZ3ModC5nZXQoIkYiKSk7dGhpcy5zZXRSZWN0YW5nbGUodC5nZXRBcnJheSgiUmVjdCIpKTt0aGlzLnNldENvbG9yKHQuZ2V0QXJyYXkoIkMiKSk7dGhpcy5zZXRCb3JkZXJTdHlsZSh0KTt0aGlzLnNldEFwcGVhcmFuY2UodCk7dGhpcy5zZXRPcHRpb25hbENvbnRlbnQodCk7Y29uc3Qgbz10LmdldCgiTUsiKTt0aGlzLnNldEJvcmRlckFuZEJhY2tncm91bmRDb2xvcnMobyk7dGhpcy5zZXRSb3RhdGlvbihvLHQpO3RoaXMucmVmPWUucmVmIGluc3RhbmNlb2YgUmVmP2UucmVmOm51bGw7dGhpcy5fc3RyZWFtcz1bXTt0aGlzLmFwcGVhcmFuY2UmJnRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UpO2NvbnN0IGM9ISEodGhpcy5mbGFncyZVKSxsPSEhKHRoaXMuZmxhZ3MmcSk7dGhpcy5kYXRhPXthbm5vdGF0aW9uRmxhZ3M6dGhpcy5mbGFncyxib3JkZXJTdHlsZTp0aGlzLmJvcmRlclN0eWxlLGNvbG9yOnRoaXMuY29sb3IsYmFja2dyb3VuZENvbG9yOnRoaXMuYmFja2dyb3VuZENvbG9yLGJvcmRlckNvbG9yOnRoaXMuYm9yZGVyQ29sb3Iscm90YXRpb246dGhpcy5yb3RhdGlvbixjb250ZW50c09iajp0aGlzLl9jb250ZW50cyxoYXNBcHBlYXJhbmNlOiEhdGhpcy5hcHBlYXJhbmNlLGlkOmUuaWQsbW9kaWZpY2F0aW9uRGF0ZTp0aGlzLm1vZGlmaWNhdGlvbkRhdGUscmVjdDp0aGlzLnJlY3RhbmdsZSxzdWJ0eXBlOmUuc3VidHlwZSxoYXNPd25DYW52YXM6ITEsbm9Sb3RhdGU6ISEodGhpcy5mbGFncyZMKSxub0hUTUw6YyYmbCxpc0VkaXRhYmxlOiExLHN0cnVjdFBhcmVudDotMX07aWYoYS5zdHJ1Y3RUcmVlUm9vdCl7bGV0IHI9dC5nZXQoIlN0cnVjdFBhcmVudCIpO3RoaXMuZGF0YS5zdHJ1Y3RQYXJlbnQ9cj1OdW1iZXIuaXNJbnRlZ2VyKHIpJiZyPj0wP3I6LTE7YS5zdHJ1Y3RUcmVlUm9vdC5hZGRBbm5vdGF0aW9uSWRUb1BhZ2UoZS5wYWdlUmVmLHIpfWlmKGUuY29sbGVjdEZpZWxkcyl7Y29uc3QgYT10LmdldCgiS2lkcyIpO2lmKEFycmF5LmlzQXJyYXkoYSkpe2NvbnN0IGU9W107Zm9yKGNvbnN0IHQgb2YgYSl0IGluc3RhbmNlb2YgUmVmJiZlLnB1c2godC50b1N0cmluZygpKTswIT09ZS5sZW5ndGgmJih0aGlzLmRhdGEua2lkSWRzPWUpfXRoaXMuZGF0YS5hY3Rpb25zPWNvbGxlY3RBY3Rpb25zKHIsdCxuZSk7dGhpcy5kYXRhLmZpZWxkTmFtZT10aGlzLl9jb25zdHJ1Y3RGaWVsZE5hbWUodCk7dGhpcy5kYXRhLnBhZ2VJbmRleD1lLnBhZ2VJbmRleH1jb25zdCBoPXQuZ2V0KCJJVCIpO2ggaW5zdGFuY2VvZiBOYW1lJiYodGhpcy5kYXRhLml0PWgubmFtZSk7dGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ9ZS5ldmFsdWF0b3JPcHRpb25zLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkO3RoaXMuX2ZhbGxiYWNrRm9udERpY3Q9bnVsbDt0aGlzLl9uZWVkQXBwZWFyYW5jZXM9ITF9X2hhc0ZsYWcoZSx0KXtyZXR1cm4hIShlJnQpfV9idWlsZEZsYWdzKGUsdCl7bGV0e2ZsYWdzOnJ9PXRoaXM7aWYodm9pZCAwPT09ZSl7aWYodm9pZCAwPT09dClyZXR1cm47cmV0dXJuIHQ/ciZ+XzpyJn5OfF99aWYoZSl7cnw9XztyZXR1cm4gdD9yJn5qfE46ciZ+TnxqfXImPX4oTnxqKTtyZXR1cm4gdD9yJn5fOnJ8X31faXNWaWV3YWJsZShlKXtyZXR1cm4hdGhpcy5faGFzRmxhZyhlLEUpJiYhdGhpcy5faGFzRmxhZyhlLGopfV9pc1ByaW50YWJsZShlKXtyZXR1cm4gdGhpcy5faGFzRmxhZyhlLF8pJiYhdGhpcy5faGFzRmxhZyhlLE4pJiYhdGhpcy5faGFzRmxhZyhlLEUpfW11c3RCZVZpZXdlZChlLHQpe2NvbnN0IHI9ZT8uZ2V0KHRoaXMuZGF0YS5pZCk/Lm5vVmlldztyZXR1cm4gdm9pZCAwIT09cj8hcjp0aGlzLnZpZXdhYmxlJiYhdGhpcy5faGFzRmxhZyh0aGlzLmZsYWdzLE4pfW11c3RCZVByaW50ZWQoZSl7Y29uc3QgdD1lPy5nZXQodGhpcy5kYXRhLmlkKT8ubm9QcmludDtyZXR1cm4gdm9pZCAwIT09dD8hdDp0aGlzLnByaW50YWJsZX1tdXN0QmVWaWV3ZWRXaGVuRWRpdGluZyhlLHQ9bnVsbCl7cmV0dXJuIGU/IXRoaXMuZGF0YS5pc0VkaXRhYmxlOiF0Py5oYXModGhpcy5kYXRhLmlkKX1nZXQgdmlld2FibGUoKXtyZXR1cm4gbnVsbCE9PXRoaXMuZGF0YS5xdWFkUG9pbnRzJiYoMD09PXRoaXMuZmxhZ3N8fHRoaXMuX2lzVmlld2FibGUodGhpcy5mbGFncykpfWdldCBwcmludGFibGUoKXtyZXR1cm4gbnVsbCE9PXRoaXMuZGF0YS5xdWFkUG9pbnRzJiYoMCE9PXRoaXMuZmxhZ3MmJnRoaXMuX2lzUHJpbnRhYmxlKHRoaXMuZmxhZ3MpKX1fcGFyc2VTdHJpbmdIZWxwZXIoZSl7Y29uc3QgdD0ic3RyaW5nIj09dHlwZW9mIGU/c3RyaW5nVG9QREZTdHJpbmcoZSk6IiI7cmV0dXJue3N0cjp0LGRpcjp0JiYicnRsIj09PWJpZGkodCkuZGlyPyJydGwiOiJsdHIifX1zZXREZWZhdWx0QXBwZWFyYW5jZShlKXtjb25zdHtkaWN0OnQsYW5ub3RhdGlvbkdsb2JhbHM6cn09ZSxhPWdldEluaGVyaXRhYmxlUHJvcGVydHkoe2RpY3Q6dCxrZXk6IkRBIn0pfHxyLmFjcm9Gb3JtLmdldCgiREEiKTt0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZT0ic3RyaW5nIj09dHlwZW9mIGE/YToiIjt0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhPXBhcnNlRGVmYXVsdEFwcGVhcmFuY2UodGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UpfXNldFRpdGxlKGUpe3RoaXMuX3RpdGxlPXRoaXMuX3BhcnNlU3RyaW5nSGVscGVyKGUpfXNldENvbnRlbnRzKGUpe3RoaXMuX2NvbnRlbnRzPXRoaXMuX3BhcnNlU3RyaW5nSGVscGVyKGUpfXNldE1vZGlmaWNhdGlvbkRhdGUoZSl7dGhpcy5tb2RpZmljYXRpb25EYXRlPSJzdHJpbmciPT10eXBlb2YgZT9lOm51bGx9c2V0RmxhZ3MoZSl7dGhpcy5mbGFncz1OdW1iZXIuaXNJbnRlZ2VyKGUpJiZlPjA/ZTowO3RoaXMuZmxhZ3MmRSYmIkFubm90YXRpb24iIT09dGhpcy5jb25zdHJ1Y3Rvci5uYW1lJiYodGhpcy5mbGFnc149RSl9aGFzRmxhZyhlKXtyZXR1cm4gdGhpcy5faGFzRmxhZyh0aGlzLmZsYWdzLGUpfXNldFJlY3RhbmdsZShlKXt0aGlzLnJlY3RhbmdsZT1sb29rdXBOb3JtYWxSZWN0KGUsWzAsMCwwLDBdKX1zZXRDb2xvcihlKXt0aGlzLmNvbG9yPWdldFJnYkNvbG9yKGUpfXNldExpbmVFbmRpbmdzKGUpe3RoaXMubGluZUVuZGluZ3M9WyJOb25lIiwiTm9uZSJdO2lmKEFycmF5LmlzQXJyYXkoZSkmJjI9PT1lLmxlbmd0aClmb3IobGV0IHQ9MDt0PDI7dCsrKXtjb25zdCByPWVbdF07aWYociBpbnN0YW5jZW9mIE5hbWUpc3dpdGNoKHIubmFtZSl7Y2FzZSJOb25lIjpjb250aW51ZTtjYXNlIlNxdWFyZSI6Y2FzZSJDaXJjbGUiOmNhc2UiRGlhbW9uZCI6Y2FzZSJPcGVuQXJyb3ciOmNhc2UiQ2xvc2VkQXJyb3ciOmNhc2UiQnV0dCI6Y2FzZSJST3BlbkFycm93IjpjYXNlIlJDbG9zZWRBcnJvdyI6Y2FzZSJTbGFzaCI6dGhpcy5saW5lRW5kaW5nc1t0XT1yLm5hbWU7Y29udGludWV9d2FybihgSWdub3JpbmcgaW52YWxpZCBsaW5lRW5kaW5nOiAke3J9YCl9fXNldFJvdGF0aW9uKGUsdCl7dGhpcy5yb3RhdGlvbj0wO2xldCByPWUgaW5zdGFuY2VvZiBEaWN0P2UuZ2V0KCJSIil8fDA6dC5nZXQoIlJvdGF0ZSIpfHwwO2lmKE51bWJlci5pc0ludGVnZXIocikmJjAhPT1yKXtyJT0zNjA7cjwwJiYocis9MzYwKTtyJTkwPT0wJiYodGhpcy5yb3RhdGlvbj1yKX19c2V0Qm9yZGVyQW5kQmFja2dyb3VuZENvbG9ycyhlKXtpZihlIGluc3RhbmNlb2YgRGljdCl7dGhpcy5ib3JkZXJDb2xvcj1nZXRSZ2JDb2xvcihlLmdldEFycmF5KCJCQyIpLG51bGwpO3RoaXMuYmFja2dyb3VuZENvbG9yPWdldFJnYkNvbG9yKGUuZ2V0QXJyYXkoIkJHIiksbnVsbCl9ZWxzZSB0aGlzLmJvcmRlckNvbG9yPXRoaXMuYmFja2dyb3VuZENvbG9yPW51bGx9c2V0Qm9yZGVyU3R5bGUoZSl7dGhpcy5ib3JkZXJTdHlsZT1uZXcgQW5ub3RhdGlvbkJvcmRlclN0eWxlO2lmKGUgaW5zdGFuY2VvZiBEaWN0KWlmKGUuaGFzKCJCUyIpKXtjb25zdCB0PWUuZ2V0KCJCUyIpO2lmKHQgaW5zdGFuY2VvZiBEaWN0KXtjb25zdCBlPXQuZ2V0KCJUeXBlIik7aWYoIWV8fGlzTmFtZShlLCJCb3JkZXIiKSl7dGhpcy5ib3JkZXJTdHlsZS5zZXRXaWR0aCh0LmdldCgiVyIpLHRoaXMucmVjdGFuZ2xlKTt0aGlzLmJvcmRlclN0eWxlLnNldFN0eWxlKHQuZ2V0KCJTIikpO3RoaXMuYm9yZGVyU3R5bGUuc2V0RGFzaEFycmF5KHQuZ2V0QXJyYXkoIkQiKSl9fX1lbHNlIGlmKGUuaGFzKCJCb3JkZXIiKSl7Y29uc3QgdD1lLmdldEFycmF5KCJCb3JkZXIiKTtpZihBcnJheS5pc0FycmF5KHQpJiZ0Lmxlbmd0aD49Myl7dGhpcy5ib3JkZXJTdHlsZS5zZXRIb3Jpem9udGFsQ29ybmVyUmFkaXVzKHRbMF0pO3RoaXMuYm9yZGVyU3R5bGUuc2V0VmVydGljYWxDb3JuZXJSYWRpdXModFsxXSk7dGhpcy5ib3JkZXJTdHlsZS5zZXRXaWR0aCh0WzJdLHRoaXMucmVjdGFuZ2xlKTs0PT09dC5sZW5ndGgmJnRoaXMuYm9yZGVyU3R5bGUuc2V0RGFzaEFycmF5KHRbM10sITApfX1lbHNlIHRoaXMuYm9yZGVyU3R5bGUuc2V0V2lkdGgoMCl9c2V0QXBwZWFyYW5jZShlKXt0aGlzLmFwcGVhcmFuY2U9bnVsbDtjb25zdCB0PWUuZ2V0KCJBUCIpO2lmKCEodCBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtjb25zdCByPXQuZ2V0KCJOIik7aWYociBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pe3RoaXMuYXBwZWFyYW5jZT1yO3JldHVybn1pZighKHIgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm47Y29uc3QgYT1lLmdldCgiQVMiKTtpZighKGEgaW5zdGFuY2VvZiBOYW1lJiZyLmhhcyhhLm5hbWUpKSlyZXR1cm47Y29uc3Qgbj1yLmdldChhLm5hbWUpO24gaW5zdGFuY2VvZiBCYXNlU3RyZWFtJiYodGhpcy5hcHBlYXJhbmNlPW4pfXNldE9wdGlvbmFsQ29udGVudChlKXt0aGlzLm9jPW51bGw7Y29uc3QgdD1lLmdldCgiT0MiKTt0IGluc3RhbmNlb2YgTmFtZT93YXJuKCJzZXRPcHRpb25hbENvbnRlbnQ6IFN1cHBvcnQgZm9yIC9OYW1lLWVudHJ5IGlzIG5vdCBpbXBsZW1lbnRlZC4iKTp0IGluc3RhbmNlb2YgRGljdCYmKHRoaXMub2M9dCl9YXN5bmMgbG9hZFJlc291cmNlcyhlLHQpe2NvbnN0IHI9YXdhaXQgdC5kaWN0LmdldEFzeW5jKCJSZXNvdXJjZXMiKTtyJiZhd2FpdCBPYmplY3RMb2FkZXIubG9hZChyLGUsci54cmVmKTtyZXR1cm4gcn1hc3luYyBnZXRPcGVyYXRvckxpc3QoZSx0LHIsYSl7Y29uc3R7aGFzT3duQ2FudmFzOm4saWQ6aSxyZWN0OnN9PXRoaXMuZGF0YTtsZXQgbz10aGlzLmFwcGVhcmFuY2U7Y29uc3QgbD0hIShuJiZyJmMpO2lmKGwmJigwPT09dGhpcy53aWR0aHx8MD09PXRoaXMuaGVpZ2h0KSl7dGhpcy5kYXRhLmhhc093bkNhbnZhcz0hMTtyZXR1cm57b3BMaXN0Om5ldyBPcGVyYXRvckxpc3Qsc2VwYXJhdGVGb3JtOiExLHNlcGFyYXRlQ2FudmFzOiExfX1pZighbyl7aWYoIWwpcmV0dXJue29wTGlzdDpuZXcgT3BlcmF0b3JMaXN0LHNlcGFyYXRlRm9ybTohMSxzZXBhcmF0ZUNhbnZhczohMX07bz1uZXcgU3RyaW5nU3RyZWFtKCIiKTtvLmRpY3Q9bmV3IERpY3R9Y29uc3QgaD1vLmRpY3QsdT1hd2FpdCB0aGlzLmxvYWRSZXNvdXJjZXMoZ3IsbyksZD1sb29rdXBSZWN0KGguZ2V0QXJyYXkoIkJCb3giKSxbMCwwLDEsMV0pLGY9bG9va3VwTWF0cml4KGguZ2V0QXJyYXkoIk1hdHJpeCIpLGZyKSxnPWdldFRyYW5zZm9ybU1hdHJpeChzLGQsZikscD1uZXcgT3BlcmF0b3JMaXN0O2xldCBtO3RoaXMub2MmJihtPWF3YWl0IGUucGFyc2VNYXJrZWRDb250ZW50UHJvcHModGhpcy5vYyxudWxsKSk7dm9pZCAwIT09bSYmcC5hZGRPcCh2dCxbIk9DIixtXSk7cC5hZGRPcChSdCxbaSxzLGcsZixsXSk7YXdhaXQgZS5nZXRPcGVyYXRvckxpc3Qoe3N0cmVhbTpvLHRhc2s6dCxyZXNvdXJjZXM6dSxvcGVyYXRvckxpc3Q6cCxmYWxsYmFja0ZvbnREaWN0OnRoaXMuX2ZhbGxiYWNrRm9udERpY3R9KTtwLmFkZE9wKEV0LFtdKTt2b2lkIDAhPT1tJiZwLmFkZE9wKEZ0LFtdKTt0aGlzLnJlc2V0KCk7cmV0dXJue29wTGlzdDpwLHNlcGFyYXRlRm9ybTohMSxzZXBhcmF0ZUNhbnZhczpsfX1hc3luYyBzYXZlKGUsdCxyLGEpe3JldHVybiBudWxsfWdldCBvdmVybGF5c1RleHRDb250ZW50KCl7cmV0dXJuITF9Z2V0IGhhc1RleHRDb250ZW50KCl7cmV0dXJuITF9YXN5bmMgZXh0cmFjdFRleHRDb250ZW50KGUsdCxyKXtpZighdGhpcy5hcHBlYXJhbmNlKXJldHVybjtjb25zdCBhPWF3YWl0IHRoaXMubG9hZFJlc291cmNlcyhwcix0aGlzLmFwcGVhcmFuY2UpLG49W10saT1bXTtsZXQgcz1udWxsO2NvbnN0IG89e2Rlc2lyZWRTaXplOk1hdGguSW5maW5pdHkscmVhZHk6ITAsZW5xdWV1ZShlLHQpe2Zvcihjb25zdCB0IG9mIGUuaXRlbXMpaWYodm9pZCAwIT09dC5zdHIpe3N8fD10LnRyYW5zZm9ybS5zbGljZSgtMik7aS5wdXNoKHQuc3RyKTtpZih0Lmhhc0VPTCl7bi5wdXNoKGkuam9pbigiIikudHJpbUVuZCgpKTtpLmxlbmd0aD0wfX19fTthd2FpdCBlLmdldFRleHRDb250ZW50KHtzdHJlYW06dGhpcy5hcHBlYXJhbmNlLHRhc2s6dCxyZXNvdXJjZXM6YSxpbmNsdWRlTWFya2VkQ29udGVudDohMCxrZWVwV2hpdGVTcGFjZTohMCxzaW5rOm8sdmlld0JveDpyfSk7dGhpcy5yZXNldCgpO2kubGVuZ3RoJiZuLnB1c2goaS5qb2luKCIiKS50cmltRW5kKCkpO2lmKG4ubGVuZ3RoPjF8fG5bMF0pe2NvbnN0IGU9dGhpcy5hcHBlYXJhbmNlLmRpY3QsdD1sb29rdXBSZWN0KGUuZ2V0QXJyYXkoIkJCb3giKSxudWxsKSxyPWxvb2t1cE1hdHJpeChlLmdldEFycmF5KCJNYXRyaXgiKSxudWxsKTt0aGlzLmRhdGEudGV4dFBvc2l0aW9uPXRoaXMuX3RyYW5zZm9ybVBvaW50KHMsdCxyKTt0aGlzLmRhdGEudGV4dENvbnRlbnQ9bn19X3RyYW5zZm9ybVBvaW50KGUsdCxyKXtjb25zdHtyZWN0OmF9PXRoaXMuZGF0YTt0fHw9WzAsMCwxLDFdO3J8fD1bMSwwLDAsMSwwLDBdO2NvbnN0IG49Z2V0VHJhbnNmb3JtTWF0cml4KGEsdCxyKTtuWzRdLT1hWzBdO25bNV0tPWFbMV07Y29uc3QgaT1lLnNsaWNlKCk7VXRpbC5hcHBseVRyYW5zZm9ybShpLG4pO1V0aWwuYXBwbHlUcmFuc2Zvcm0oaSxyKTtyZXR1cm4gaX1nZXRGaWVsZE9iamVjdCgpe3JldHVybiB0aGlzLmRhdGEua2lkSWRzP3tpZDp0aGlzLmRhdGEuaWQsYWN0aW9uczp0aGlzLmRhdGEuYWN0aW9ucyxuYW1lOnRoaXMuZGF0YS5maWVsZE5hbWUsc3Ryb2tlQ29sb3I6dGhpcy5kYXRhLmJvcmRlckNvbG9yLGZpbGxDb2xvcjp0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLHR5cGU6IiIsa2lkSWRzOnRoaXMuZGF0YS5raWRJZHMscGFnZTp0aGlzLmRhdGEucGFnZUluZGV4LHJvdGF0aW9uOnRoaXMucm90YXRpb259Om51bGx9cmVzZXQoKXtmb3IoY29uc3QgZSBvZiB0aGlzLl9zdHJlYW1zKWUucmVzZXQoKX1fY29uc3RydWN0RmllbGROYW1lKGUpe2lmKCFlLmhhcygiVCIpJiYhZS5oYXMoIlBhcmVudCIpKXt3YXJuKCJVbmtub3duIGZpZWxkIG5hbWUsIGZhbGxpbmcgYmFjayB0byBlbXB0eSBmaWVsZCBuYW1lLiIpO3JldHVybiIifWlmKCFlLmhhcygiUGFyZW50IikpcmV0dXJuIHN0cmluZ1RvUERGU3RyaW5nKGUuZ2V0KCJUIikpO2NvbnN0IHQ9W107ZS5oYXMoIlQiKSYmdC51bnNoaWZ0KHN0cmluZ1RvUERGU3RyaW5nKGUuZ2V0KCJUIikpKTtsZXQgcj1lO2NvbnN0IGE9bmV3IFJlZlNldDtlLm9iaklkJiZhLnB1dChlLm9iaklkKTtmb3IoO3IuaGFzKCJQYXJlbnQiKTspe3I9ci5nZXQoIlBhcmVudCIpO2lmKCEociBpbnN0YW5jZW9mIERpY3QpfHxyLm9iaklkJiZhLmhhcyhyLm9iaklkKSlicmVhaztyLm9iaklkJiZhLnB1dChyLm9iaklkKTtyLmhhcygiVCIpJiZ0LnVuc2hpZnQoc3RyaW5nVG9QREZTdHJpbmcoci5nZXQoIlQiKSkpfXJldHVybiB0LmpvaW4oIi4iKX1nZXQgd2lkdGgoKXtyZXR1cm4gdGhpcy5kYXRhLnJlY3RbMl0tdGhpcy5kYXRhLnJlY3RbMF19Z2V0IGhlaWdodCgpe3JldHVybiB0aGlzLmRhdGEucmVjdFszXS10aGlzLmRhdGEucmVjdFsxXX19Y2xhc3MgQW5ub3RhdGlvbkJvcmRlclN0eWxle2NvbnN0cnVjdG9yKCl7dGhpcy53aWR0aD0xO3RoaXMucmF3V2lkdGg9MTt0aGlzLnN0eWxlPVE7dGhpcy5kYXNoQXJyYXk9WzNdO3RoaXMuaG9yaXpvbnRhbENvcm5lclJhZGl1cz0wO3RoaXMudmVydGljYWxDb3JuZXJSYWRpdXM9MH1zZXRXaWR0aChlLHQ9WzAsMCwwLDBdKXtpZihlIGluc3RhbmNlb2YgTmFtZSl0aGlzLndpZHRoPTA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIGUpe2lmKGU+MCl7dGhpcy5yYXdXaWR0aD1lO2NvbnN0IHI9KHRbMl0tdFswXSkvMixhPSh0WzNdLXRbMV0pLzI7aWYocj4wJiZhPjAmJihlPnJ8fGU+YSkpe3dhcm4oYEFubm90YXRpb25Cb3JkZXJTdHlsZS5zZXRXaWR0aCAtIGlnbm9yaW5nIHdpZHRoOiAke2V9YCk7ZT0xfX10aGlzLndpZHRoPWV9fXNldFN0eWxlKGUpe2lmKGUgaW5zdGFuY2VvZiBOYW1lKXN3aXRjaChlLm5hbWUpe2Nhc2UiUyI6dGhpcy5zdHlsZT1RO2JyZWFrO2Nhc2UiRCI6dGhpcy5zdHlsZT1lZTticmVhaztjYXNlIkIiOnRoaXMuc3R5bGU9dGU7YnJlYWs7Y2FzZSJJIjp0aGlzLnN0eWxlPXJlO2JyZWFrO2Nhc2UiVSI6dGhpcy5zdHlsZT1hZX19c2V0RGFzaEFycmF5KGUsdD0hMSl7aWYoQXJyYXkuaXNBcnJheShlKSl7bGV0IHI9ITAsYT0hMDtmb3IoY29uc3QgdCBvZiBlKXtpZighKCt0Pj0wKSl7cj0hMTticmVha310PjAmJihhPSExKX1pZigwPT09ZS5sZW5ndGh8fHImJiFhKXt0aGlzLmRhc2hBcnJheT1lO3QmJnRoaXMuc2V0U3R5bGUoTmFtZS5nZXQoIkQiKSl9ZWxzZSB0aGlzLndpZHRoPTB9ZWxzZSBlJiYodGhpcy53aWR0aD0wKX1zZXRIb3Jpem9udGFsQ29ybmVyUmFkaXVzKGUpe051bWJlci5pc0ludGVnZXIoZSkmJih0aGlzLmhvcml6b250YWxDb3JuZXJSYWRpdXM9ZSl9c2V0VmVydGljYWxDb3JuZXJSYWRpdXMoZSl7TnVtYmVyLmlzSW50ZWdlcihlKSYmKHRoaXMudmVydGljYWxDb3JuZXJSYWRpdXM9ZSl9fWNsYXNzIE1hcmt1cEFubm90YXRpb24gZXh0ZW5kcyBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO2NvbnN0e2RpY3Q6dH09ZTtpZih0LmhhcygiSVJUIikpe2NvbnN0IGU9dC5nZXRSYXcoIklSVCIpO3RoaXMuZGF0YS5pblJlcGx5VG89ZSBpbnN0YW5jZW9mIFJlZj9lLnRvU3RyaW5nKCk6bnVsbDtjb25zdCByPXQuZ2V0KCJSVCIpO3RoaXMuZGF0YS5yZXBseVR5cGU9ciBpbnN0YW5jZW9mIE5hbWU/ci5uYW1lOlJ9bGV0IHI9bnVsbDtpZih0aGlzLmRhdGEucmVwbHlUeXBlPT09RCl7Y29uc3QgZT10LmdldCgiSVJUIik7dGhpcy5zZXRUaXRsZShlLmdldCgiVCIpKTt0aGlzLmRhdGEudGl0bGVPYmo9dGhpcy5fdGl0bGU7dGhpcy5zZXRDb250ZW50cyhlLmdldCgiQ29udGVudHMiKSk7dGhpcy5kYXRhLmNvbnRlbnRzT2JqPXRoaXMuX2NvbnRlbnRzO2lmKGUuaGFzKCJDcmVhdGlvbkRhdGUiKSl7dGhpcy5zZXRDcmVhdGlvbkRhdGUoZS5nZXQoIkNyZWF0aW9uRGF0ZSIpKTt0aGlzLmRhdGEuY3JlYXRpb25EYXRlPXRoaXMuY3JlYXRpb25EYXRlfWVsc2UgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZT1udWxsO2lmKGUuaGFzKCJNIikpe3RoaXMuc2V0TW9kaWZpY2F0aW9uRGF0ZShlLmdldCgiTSIpKTt0aGlzLmRhdGEubW9kaWZpY2F0aW9uRGF0ZT10aGlzLm1vZGlmaWNhdGlvbkRhdGV9ZWxzZSB0aGlzLmRhdGEubW9kaWZpY2F0aW9uRGF0ZT1udWxsO3I9ZS5nZXRSYXcoIlBvcHVwIik7aWYoZS5oYXMoIkMiKSl7dGhpcy5zZXRDb2xvcihlLmdldEFycmF5KCJDIikpO3RoaXMuZGF0YS5jb2xvcj10aGlzLmNvbG9yfWVsc2UgdGhpcy5kYXRhLmNvbG9yPW51bGx9ZWxzZXt0aGlzLmRhdGEudGl0bGVPYmo9dGhpcy5fdGl0bGU7dGhpcy5zZXRDcmVhdGlvbkRhdGUodC5nZXQoIkNyZWF0aW9uRGF0ZSIpKTt0aGlzLmRhdGEuY3JlYXRpb25EYXRlPXRoaXMuY3JlYXRpb25EYXRlO3I9dC5nZXRSYXcoIlBvcHVwIik7dC5oYXMoIkMiKXx8KHRoaXMuZGF0YS5jb2xvcj1udWxsKX10aGlzLmRhdGEucG9wdXBSZWY9ciBpbnN0YW5jZW9mIFJlZj9yLnRvU3RyaW5nKCk6bnVsbDt0LmhhcygiUkMiKSYmKHRoaXMuZGF0YS5yaWNoVGV4dD1YRkFGYWN0b3J5LmdldFJpY2hUZXh0QXNIdG1sKHQuZ2V0KCJSQyIpKSl9c2V0Q3JlYXRpb25EYXRlKGUpe3RoaXMuY3JlYXRpb25EYXRlPSJzdHJpbmciPT10eXBlb2YgZT9lOm51bGx9X3NldERlZmF1bHRBcHBlYXJhbmNlKHt4cmVmOmUsZXh0cmE6dCxzdHJva2VDb2xvcjpyLGZpbGxDb2xvcjphLGJsZW5kTW9kZTpuLHN0cm9rZUFscGhhOmksZmlsbEFscGhhOnMscG9pbnRzQ2FsbGJhY2s6b30pe2NvbnN0IGM9dGhpcy5kYXRhLnJlY3Q9WzEvMCwxLzAsLTEvMCwtMS8wXSxsPVsicSJdO3QmJmwucHVzaCh0KTtyJiZsLnB1c2goYCR7clswXX0gJHtyWzFdfSAke3JbMl19IFJHYCk7YSYmbC5wdXNoKGAke2FbMF19ICR7YVsxXX0gJHthWzJdfSByZ2ApO2NvbnN0IGg9dGhpcy5kYXRhLnF1YWRQb2ludHN8fEZsb2F0MzJBcnJheS5mcm9tKFt0aGlzLnJlY3RhbmdsZVswXSx0aGlzLnJlY3RhbmdsZVszXSx0aGlzLnJlY3RhbmdsZVsyXSx0aGlzLnJlY3RhbmdsZVszXSx0aGlzLnJlY3RhbmdsZVswXSx0aGlzLnJlY3RhbmdsZVsxXSx0aGlzLnJlY3RhbmdsZVsyXSx0aGlzLnJlY3RhbmdsZVsxXV0pO2ZvcihsZXQgZT0wLHQ9aC5sZW5ndGg7ZTx0O2UrPTgpe2NvbnN0IHQ9byhsLGguc3ViYXJyYXkoZSxlKzgpKTtVdGlsLnJlY3RCb3VuZGluZ0JveCguLi50LGMpfWwucHVzaCgiUSIpO2NvbnN0IHU9bmV3IERpY3QoZSksZD1uZXcgRGljdChlKTtkLnNldElmTmFtZSgiU3VidHlwZSIsIkZvcm0iKTtjb25zdCBmPW5ldyBTdHJpbmdTdHJlYW0obC5qb2luKCIgIikpO2YuZGljdD1kO3Uuc2V0KCJGbTAiLGYpO2NvbnN0IGc9bmV3IERpY3QoZSk7biYmZy5zZXRJZk5hbWUoIkJNIixuKTtnLnNldElmTnVtYmVyKCJDQSIsaSk7Zy5zZXRJZk51bWJlcigiY2EiLHMpO2NvbnN0IHA9bmV3IERpY3QoZSk7cC5zZXQoIkdTMCIsZyk7Y29uc3QgbT1uZXcgRGljdChlKTttLnNldCgiRXh0R1N0YXRlIixwKTttLnNldCgiWE9iamVjdCIsdSk7Y29uc3QgYj1uZXcgRGljdChlKTtiLnNldCgiUmVzb3VyY2VzIixtKTtiLnNldCgiQkJveCIsYyk7dGhpcy5hcHBlYXJhbmNlPW5ldyBTdHJpbmdTdHJlYW0oIi9HUzAgZ3MgL0ZtMCBEbyIpO3RoaXMuYXBwZWFyYW5jZS5kaWN0PWI7dGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuYXBwZWFyYW5jZSxmKX1zdGF0aWMgYXN5bmMgY3JlYXRlTmV3QW5ub3RhdGlvbihlLHQscixhKXtjb25zdCBuPXQucmVmfHw9ZS5nZXROZXdUZW1wb3JhcnlSZWYoKSxpPWF3YWl0IHRoaXMuY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbSh0LGUsYSk7bGV0IHM7aWYoaSl7Y29uc3QgYT1lLmdldE5ld1RlbXBvcmFyeVJlZigpO3M9dGhpcy5jcmVhdGVOZXdEaWN0KHQsZSx7YXBSZWY6YX0pO3IucHV0KGEse2RhdGE6aX0pfWVsc2Ugcz10aGlzLmNyZWF0ZU5ld0RpY3QodCxlLHt9KTtOdW1iZXIuaXNJbnRlZ2VyKHQucGFyZW50VHJlZUlkKSYmcy5zZXQoIlN0cnVjdFBhcmVudCIsdC5wYXJlbnRUcmVlSWQpO3IucHV0KG4se2RhdGE6c30pO2NvbnN0IG89e3JlZjpufSx7cG9wdXA6Y309dDtpZihjKXtpZihjLmRlbGV0ZWQpe3MuZGVsZXRlKCJQb3B1cCIpO3MuZGVsZXRlKCJDb250ZW50cyIpO3MuZGVsZXRlKCJSQyIpO3JldHVybiBvfWNvbnN0IHQ9Yy5yZWZ8fD1lLmdldE5ld1RlbXBvcmFyeVJlZigpO2MucGFyZW50PW47Y29uc3QgYT1Qb3B1cEFubm90YXRpb24uY3JlYXRlTmV3RGljdChjLGUpO3IucHV0KHQse2RhdGE6YX0pO3Muc2V0SWZEZWZpbmVkKCJDb250ZW50cyIsc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShjLmNvbnRlbnRzKSk7cy5zZXQoIlBvcHVwIix0KTtyZXR1cm5bbyx7cmVmOnR9XX1yZXR1cm4gb31zdGF0aWMgYXN5bmMgY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGUsdCxyLGEpe2NvbnN0IG49YXdhaXQgdGhpcy5jcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKHIsdCxhKSxpPXRoaXMuY3JlYXRlTmV3RGljdChyLHQsbj97YXA6bn06e30pLHM9bmV3IHRoaXMucHJvdG90eXBlLmNvbnN0cnVjdG9yKHtkaWN0OmkseHJlZjp0LGFubm90YXRpb25HbG9iYWxzOmUsZXZhbHVhdG9yT3B0aW9uczphLmV2YWx1YXRvck9wdGlvbnN9KTtyLnJlZiYmKHMucmVmPXMucmVmVG9SZXBsYWNlPXIucmVmKTtyZXR1cm4gc319Y2xhc3MgV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cixhbm5vdGF0aW9uR2xvYmFsczphfT1lLG49dGhpcy5kYXRhO3RoaXMuX25lZWRBcHBlYXJhbmNlcz1lLm5lZWRBcHBlYXJhbmNlcztuLmFubm90YXRpb25UeXBlPU0uV0lER0VUO3ZvaWQgMD09PW4uZmllbGROYW1lJiYobi5maWVsZE5hbWU9dGhpcy5fY29uc3RydWN0RmllbGROYW1lKHQpKTt2b2lkIDA9PT1uLmFjdGlvbnMmJihuLmFjdGlvbnM9Y29sbGVjdEFjdGlvbnMocix0LG5lKSk7bGV0IGk9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiViIsZ2V0QXJyYXk6ITB9KTtuLmZpZWxkVmFsdWU9dGhpcy5fZGVjb2RlRm9ybVZhbHVlKGkpO2NvbnN0IHM9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiRFYiLGdldEFycmF5OiEwfSk7bi5kZWZhdWx0RmllbGRWYWx1ZT10aGlzLl9kZWNvZGVGb3JtVmFsdWUocyk7aWYodm9pZCAwPT09aSYmYS54ZmFEYXRhc2V0cyl7Y29uc3QgZT10aGlzLl90aXRsZS5zdHI7aWYoZSl7dGhpcy5faGFzVmFsdWVGcm9tWEZBPSEwO24uZmllbGRWYWx1ZT1pPWEueGZhRGF0YXNldHMuZ2V0VmFsdWUoZSl9fXZvaWQgMD09PWkmJm51bGwhPT1uLmRlZmF1bHRGaWVsZFZhbHVlJiYobi5maWVsZFZhbHVlPW4uZGVmYXVsdEZpZWxkVmFsdWUpO24uYWx0ZXJuYXRpdmVUZXh0PXN0cmluZ1RvUERGU3RyaW5nKHQuZ2V0KCJUVSIpfHwiIik7dGhpcy5zZXREZWZhdWx0QXBwZWFyYW5jZShlKTtuLmhhc0FwcGVhcmFuY2V8fD10aGlzLl9uZWVkQXBwZWFyYW5jZXMmJnZvaWQgMCE9PW4uZmllbGRWYWx1ZSYmbnVsbCE9PW4uZmllbGRWYWx1ZTtjb25zdCBvPWdldEluaGVyaXRhYmxlUHJvcGVydHkoe2RpY3Q6dCxrZXk6IkZUIn0pO24uZmllbGRUeXBlPW8gaW5zdGFuY2VvZiBOYW1lP28ubmFtZTpudWxsO2NvbnN0IGM9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiRFIifSksbD1hLmFjcm9Gb3JtLmdldCgiRFIiKSxoPXRoaXMuYXBwZWFyYW5jZT8uZGljdC5nZXQoIlJlc291cmNlcyIpO3RoaXMuX2ZpZWxkUmVzb3VyY2VzPXtsb2NhbFJlc291cmNlczpjLGFjcm9Gb3JtUmVzb3VyY2VzOmwsYXBwZWFyYW5jZVJlc291cmNlczpoLG1lcmdlZFJlc291cmNlczpEaWN0Lm1lcmdlKHt4cmVmOnIsZGljdEFycmF5OltjLGgsbF0sbWVyZ2VTdWJEaWN0czohMH0pfTtuLmZpZWxkRmxhZ3M9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiRmYifSk7KCFOdW1iZXIuaXNJbnRlZ2VyKG4uZmllbGRGbGFncyl8fG4uZmllbGRGbGFnczwwKSYmKG4uZmllbGRGbGFncz0wKTtuLnBhc3N3b3JkPXRoaXMuaGFzRmllbGRGbGFnKHopO24ucmVhZE9ubHk9dGhpcy5oYXNGaWVsZEZsYWcoWCk7bi5yZXF1aXJlZD10aGlzLmhhc0ZpZWxkRmxhZyhIKTtuLmhpZGRlbj10aGlzLl9oYXNGbGFnKG4uYW5ub3RhdGlvbkZsYWdzLE4pfHx0aGlzLl9oYXNGbGFnKG4uYW5ub3RhdGlvbkZsYWdzLGopfV9kZWNvZGVGb3JtVmFsdWUoZSl7cmV0dXJuIEFycmF5LmlzQXJyYXkoZSk/ZS5maWx0ZXIoZT0+InN0cmluZyI9PXR5cGVvZiBlKS5tYXAoZT0+c3RyaW5nVG9QREZTdHJpbmcoZSkpOmUgaW5zdGFuY2VvZiBOYW1lP3N0cmluZ1RvUERGU3RyaW5nKGUubmFtZSk6InN0cmluZyI9PXR5cGVvZiBlP3N0cmluZ1RvUERGU3RyaW5nKGUpOm51bGx9aGFzRmllbGRGbGFnKGUpe3JldHVybiEhKHRoaXMuZGF0YS5maWVsZEZsYWdzJmUpfV9pc1ZpZXdhYmxlKGUpe3JldHVybiEwfW11c3RCZVZpZXdlZChlLHQpe3JldHVybiB0P3RoaXMudmlld2FibGU6c3VwZXIubXVzdEJlVmlld2VkKGUsdCkmJiF0aGlzLl9oYXNGbGFnKHRoaXMuZmxhZ3Msail9Z2V0Um90YXRpb25NYXRyaXgoZSl7bGV0IHQ9ZT8uZ2V0KHRoaXMuZGF0YS5pZCk/LnJvdGF0aW9uO3ZvaWQgMD09PXQmJih0PXRoaXMucm90YXRpb24pO3JldHVybiAwPT09dD9mcjpnZXRSb3RhdGlvbk1hdHJpeCh0LHRoaXMud2lkdGgsdGhpcy5oZWlnaHQpfWdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhlKXtsZXQgdD1lPy5nZXQodGhpcy5kYXRhLmlkKT8ucm90YXRpb247dm9pZCAwPT09dCYmKHQ9dGhpcy5yb3RhdGlvbik7aWYoIXRoaXMuYmFja2dyb3VuZENvbG9yJiYhdGhpcy5ib3JkZXJDb2xvcilyZXR1cm4iIjtjb25zdCByPTA9PT10fHwxODA9PT10P2AwIDAgJHt0aGlzLndpZHRofSAke3RoaXMuaGVpZ2h0fSByZWA6YDAgMCAke3RoaXMuaGVpZ2h0fSAke3RoaXMud2lkdGh9IHJlYDtsZXQgYT0iIjt0aGlzLmJhY2tncm91bmRDb2xvciYmKGE9YCR7Z2V0UGRmQ29sb3IodGhpcy5iYWNrZ3JvdW5kQ29sb3IsITApfSAke3J9IGYgYCk7aWYodGhpcy5ib3JkZXJDb2xvcil7YSs9YCR7dGhpcy5ib3JkZXJTdHlsZS53aWR0aHx8MX0gdyAke2dldFBkZkNvbG9yKHRoaXMuYm9yZGVyQ29sb3IsITEpfSAke3J9IFMgYH1yZXR1cm4gYX1hc3luYyBnZXRPcGVyYXRvckxpc3QoZSx0LHIsYSl7aWYociZ1JiYhKHRoaXMgaW5zdGFuY2VvZiBTaWduYXR1cmVXaWRnZXRBbm5vdGF0aW9uKSYmIXRoaXMuZGF0YS5ub0hUTUwmJiF0aGlzLmRhdGEuaGFzT3duQ2FudmFzKXJldHVybntvcExpc3Q6bmV3IE9wZXJhdG9yTGlzdCxzZXBhcmF0ZUZvcm06ITAsc2VwYXJhdGVDYW52YXM6ITF9O2lmKCF0aGlzLl9oYXNUZXh0KXJldHVybiBzdXBlci5nZXRPcGVyYXRvckxpc3QoZSx0LHIsYSk7Y29uc3Qgbj1hd2FpdCB0aGlzLl9nZXRBcHBlYXJhbmNlKGUsdCxyLGEpO2lmKHRoaXMuYXBwZWFyYW5jZSYmbnVsbD09PW4pcmV0dXJuIHN1cGVyLmdldE9wZXJhdG9yTGlzdChlLHQscixhKTtjb25zdCBpPW5ldyBPcGVyYXRvckxpc3Q7aWYoIXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlfHxudWxsPT09bilyZXR1cm57b3BMaXN0Omksc2VwYXJhdGVGb3JtOiExLHNlcGFyYXRlQ2FudmFzOiExfTtjb25zdCBzPSEhKHRoaXMuZGF0YS5oYXNPd25DYW52YXMmJnImYyksbz1bMCwwLHRoaXMud2lkdGgsdGhpcy5oZWlnaHRdLGw9Z2V0VHJhbnNmb3JtTWF0cml4KHRoaXMuZGF0YS5yZWN0LG8sWzEsMCwwLDEsMCwwXSk7bGV0IGg7dGhpcy5vYyYmKGg9YXdhaXQgZS5wYXJzZU1hcmtlZENvbnRlbnRQcm9wcyh0aGlzLm9jLG51bGwpKTt2b2lkIDAhPT1oJiZpLmFkZE9wKHZ0LFsiT0MiLGhdKTtpLmFkZE9wKFJ0LFt0aGlzLmRhdGEuaWQsdGhpcy5kYXRhLnJlY3QsbCx0aGlzLmdldFJvdGF0aW9uTWF0cml4KGEpLHNdKTtjb25zdCBkPW5ldyBTdHJpbmdTdHJlYW0obik7YXdhaXQgZS5nZXRPcGVyYXRvckxpc3Qoe3N0cmVhbTpkLHRhc2s6dCxyZXNvdXJjZXM6dGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzLG9wZXJhdG9yTGlzdDppfSk7aS5hZGRPcChFdCxbXSk7dm9pZCAwIT09aCYmaS5hZGRPcChGdCxbXSk7cmV0dXJue29wTGlzdDppLHNlcGFyYXRlRm9ybTohMSxzZXBhcmF0ZUNhbnZhczpzfX1fZ2V0TUtEaWN0KGUpe2NvbnN0IHQ9bmV3IERpY3QobnVsbCk7ZSYmdC5zZXQoIlIiLGUpO3Quc2V0SWZBcnJheSgiQkMiLGdldFBkZkNvbG9yQXJyYXkodGhpcy5ib3JkZXJDb2xvcikpO3Quc2V0SWZBcnJheSgiQkciLGdldFBkZkNvbG9yQXJyYXkodGhpcy5iYWNrZ3JvdW5kQ29sb3IpKTtyZXR1cm4gdC5zaXplPjA/dDpudWxsfWFtZW5kU2F2ZWREaWN0KGUsdCl7fXNldFZhbHVlKGUsdCxyLGEpe2NvbnN0e2RpY3Q6bixyZWY6aX09ZnVuY3Rpb24gZ2V0UGFyZW50VG9VcGRhdGUoZSx0LHIpe2NvbnN0IGE9bmV3IFJlZlNldCxuPWUsaT17ZGljdDpudWxsLHJlZjpudWxsfTtmb3IoO2UgaW5zdGFuY2VvZiBEaWN0JiYhYS5oYXModCk7KXthLnB1dCh0KTtpZihlLmhhcygiVCIpKWJyZWFrO2lmKCEoKHQ9ZS5nZXRSYXcoIlBhcmVudCIpKWluc3RhbmNlb2YgUmVmKSlyZXR1cm4gaTtlPXIuZmV0Y2godCl9aWYoZSBpbnN0YW5jZW9mIERpY3QmJmUhPT1uKXtpLmRpY3Q9ZTtpLnJlZj10fXJldHVybiBpfShlLHRoaXMucmVmLHIpO2lmKG4pe2lmKCFhLmhhcyhpKSl7Y29uc3QgZT1uLmNsb25lKCk7ZS5zZXQoIlYiLHQpO2EucHV0KGkse2RhdGE6ZX0pO3JldHVybiBlfX1lbHNlIGUuc2V0KCJWIix0KTtyZXR1cm4gbnVsbH1hc3luYyBzYXZlKGUsdCxyLGEpe2NvbnN0IG49cj8uZ2V0KHRoaXMuZGF0YS5pZCksaT10aGlzLl9idWlsZEZsYWdzKG4/Lm5vVmlldyxuPy5ub1ByaW50KTtsZXQgcz1uPy52YWx1ZSxvPW4/LnJvdGF0aW9uO2lmKHM9PT10aGlzLmRhdGEuZmllbGRWYWx1ZXx8dm9pZCAwPT09cyl7aWYoIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSYmdm9pZCAwPT09byYmdm9pZCAwPT09aSlyZXR1cm47c3x8PXRoaXMuZGF0YS5maWVsZFZhbHVlfWlmKHZvaWQgMD09PW8mJiF0aGlzLl9oYXNWYWx1ZUZyb21YRkEmJkFycmF5LmlzQXJyYXkocykmJkFycmF5LmlzQXJyYXkodGhpcy5kYXRhLmZpZWxkVmFsdWUpJiZpc0FycmF5RXF1YWwocyx0aGlzLmRhdGEuZmllbGRWYWx1ZSkmJnZvaWQgMD09PWkpcmV0dXJuO3ZvaWQgMD09PW8mJihvPXRoaXMucm90YXRpb24pO2xldCBjPW51bGw7aWYoIXRoaXMuX25lZWRBcHBlYXJhbmNlcyl7Yz1hd2FpdCB0aGlzLl9nZXRBcHBlYXJhbmNlKGUsdCxoLHIpO2lmKG51bGw9PT1jJiZ2b2lkIDA9PT1pKXJldHVybn1sZXQgbD0hMTtpZihjPy5uZWVkQXBwZWFyYW5jZXMpe2w9ITA7Yz1udWxsfWNvbnN0e3hyZWY6dX09ZSxkPXUuZmV0Y2hJZlJlZih0aGlzLnJlZik7aWYoIShkIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuO2NvbnN0IGY9bmV3IERpY3QodSk7Zm9yKGNvbnN0IGUgb2YgZC5nZXRLZXlzKCkpIkFQIiE9PWUmJmYuc2V0KGUsZC5nZXRSYXcoZSkpO2lmKHZvaWQgMCE9PWkpe2Yuc2V0KCJGIixpKTtpZihudWxsPT09YyYmIWwpe2NvbnN0IGU9ZC5nZXRSYXcoIkFQIik7ZSYmZi5zZXQoIkFQIixlKX19Y29uc3QgZz17cGF0aDp0aGlzLmRhdGEuZmllbGROYW1lLHZhbHVlOnN9LHA9dGhpcy5zZXRWYWx1ZShmLEFycmF5LmlzQXJyYXkocyk/cy5tYXAoc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSk6c3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShzKSx1LGEpO3RoaXMuYW1lbmRTYXZlZERpY3QocixwfHxmKTtjb25zdCBtPXRoaXMuX2dldE1LRGljdChvKTttJiZmLnNldCgiTUsiLG0pO2EucHV0KHRoaXMucmVmLHtkYXRhOmYseGZhOmcsbmVlZEFwcGVhcmFuY2VzOmx9KTtpZihudWxsIT09Yyl7Y29uc3QgZT11LmdldE5ld1RlbXBvcmFyeVJlZigpLHQ9bmV3IERpY3QodSk7Zi5zZXQoIkFQIix0KTt0LnNldCgiTiIsZSk7Y29uc3Qgbj10aGlzLl9nZXRTYXZlRmllbGRSZXNvdXJjZXModSksaT1uZXcgU3RyaW5nU3RyZWFtKGMpLHM9aS5kaWN0PW5ldyBEaWN0KHUpO3Muc2V0SWZOYW1lKCJTdWJ0eXBlIiwiRm9ybSIpO3Muc2V0KCJSZXNvdXJjZXMiLG4pO2NvbnN0IGw9byUxODA9PTA/WzAsMCx0aGlzLndpZHRoLHRoaXMuaGVpZ2h0XTpbMCwwLHRoaXMuaGVpZ2h0LHRoaXMud2lkdGhdO3Muc2V0KCJCQm94IixsKTtjb25zdCBoPXRoaXMuZ2V0Um90YXRpb25NYXRyaXgocik7aCE9PWZyJiZzLnNldCgiTWF0cml4IixoKTthLnB1dChlLHtkYXRhOmkseGZhOm51bGwsbmVlZEFwcGVhcmFuY2VzOiExfSl9Zi5zZXQoIk0iLGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZSgpfWApfWFzeW5jIF9nZXRBcHBlYXJhbmNlKGUsdCxyLGEpe2lmKHRoaXMuZGF0YS5wYXNzd29yZClyZXR1cm4gbnVsbDtjb25zdCBuPWE/LmdldCh0aGlzLmRhdGEuaWQpO2xldCBpLG87aWYobil7aT1uLmZvcm1hdHRlZFZhbHVlfHxuLnZhbHVlO289bi5yb3RhdGlvbn1pZih2b2lkIDA9PT1vJiZ2b2lkIDA9PT1pJiYhdGhpcy5fbmVlZEFwcGVhcmFuY2VzJiYoIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQXx8dGhpcy5hcHBlYXJhbmNlKSlyZXR1cm4gbnVsbDtjb25zdCBjPXRoaXMuZ2V0Qm9yZGVyQW5kQmFja2dyb3VuZEFwcGVhcmFuY2VzKGEpO2lmKHZvaWQgMD09PWkpe2k9dGhpcy5kYXRhLmZpZWxkVmFsdWU7aWYoIWkpcmV0dXJuYC9UeCBCTUMgcSAke2N9USBFTUNgfUFycmF5LmlzQXJyYXkoaSkmJjE9PT1pLmxlbmd0aCYmKGk9aVswXSk7YXNzZXJ0KCJzdHJpbmciPT10eXBlb2YgaSwiRXhwZWN0ZWQgYHZhbHVlYCB0byBiZSBhIHN0cmluZy4iKTtpPWkudHJpbUVuZCgpO2lmKHRoaXMuZGF0YS5jb21ibyl7Y29uc3QgZT10aGlzLmRhdGEub3B0aW9ucy5maW5kKCh7ZXhwb3J0VmFsdWU6ZX0pPT5pPT09ZSk7aT1lPy5kaXNwbGF5VmFsdWV8fGl9aWYoIiI9PT1pKXJldHVybmAvVHggQk1DIHEgJHtjfVEgRU1DYDt2b2lkIDA9PT1vJiYobz10aGlzLnJvdGF0aW9uKTtsZXQgbCx1PS0xO2lmKHRoaXMuZGF0YS5tdWx0aUxpbmUpe2w9aS5zcGxpdCgvXHJcbj98XG4vKS5tYXAoZT0+ZS5ub3JtYWxpemUoIk5GQyIpKTt1PWwubGVuZ3RofWVsc2UgbD1baS5yZXBsYWNlKC9cclxuP3xcbi8sIiIpLm5vcm1hbGl6ZSgiTkZDIildO2xldHt3aWR0aDpkLGhlaWdodDpmfT10aGlzOzkwIT09byYmMjcwIT09b3x8KFtkLGZdPVtmLGRdKTt0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZXx8KHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE9cGFyc2VEZWZhdWx0QXBwZWFyYW5jZSh0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZT0iL0hlbHZldGljYSAwIFRmIDAgZyIpKTtsZXQgZyxwLG0sYj1hd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShlLHQsdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSx0aGlzLl9maWVsZFJlc291cmNlcy5tZXJnZWRSZXNvdXJjZXMpO2NvbnN0IHk9W107bGV0IHc9ITE7Zm9yKGNvbnN0IGUgb2YgbCl7Y29uc3QgdD1iLmVuY29kZVN0cmluZyhlKTt0Lmxlbmd0aD4xJiYodz0hMCk7eS5wdXNoKHQuam9pbigiIikpfWlmKHcmJnImaClyZXR1cm57bmVlZEFwcGVhcmFuY2VzOiEwfTtpZih3JiZ0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCl7Y29uc3Qgcj10aGlzLmRhdGEuY29tYj8ibW9ub3NwYWNlIjoic2Fucy1zZXJpZiIsYT1uZXcgRmFrZVVuaWNvZGVGb250KGUueHJlZixyKSxuPWEuY3JlYXRlRm9udFJlc291cmNlcyhsLmpvaW4oIiIpKSxzPW4uZ2V0UmF3KCJGb250Iik7aWYodGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzLmhhcygiRm9udCIpKXtjb25zdCBlPXRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcy5nZXQoIkZvbnQiKTtmb3IoY29uc3QgdCBvZiBzLmdldEtleXMoKSllLnNldCh0LHMuZ2V0UmF3KHQpKX1lbHNlIHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcy5zZXQoIkZvbnQiLHMpO2NvbnN0IG89YS5mb250TmFtZS5uYW1lO2I9YXdhaXQgV2lkZ2V0QW5ub3RhdGlvbi5fZ2V0Rm9udERhdGEoZSx0LHtmb250TmFtZTpvLGZvbnRTaXplOjB9LG4pO2ZvcihsZXQgZT0wLHQ9eS5sZW5ndGg7ZTx0O2UrKyl5W2VdPXN0cmluZ1RvVVRGMTZTdHJpbmcobFtlXSk7Y29uc3QgYz1PYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSk7dGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250U2l6ZT0wO3RoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEuZm9udE5hbWU9bztbZyxwLG1dPXRoaXMuX2NvbXB1dGVGb250U2l6ZShmLTIsZC00LGksYix1KTt0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhPWN9ZWxzZXt0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZHx8d2FybigiX2dldEFwcGVhcmFuY2U6IE9mZnNjcmVlbkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkLCBhbm5vdGF0aW9uIG1heSBub3QgcmVuZGVyIGNvcnJlY3RseS4iKTtbZyxwLG1dPXRoaXMuX2NvbXB1dGVGb250U2l6ZShmLTIsZC00LGksYix1KX1sZXQgeD1iLmRlc2NlbnQ7eD1pc05hTih4KT9zKm06TWF0aC5tYXgocyptLE1hdGguYWJzKHgpKnApO2NvbnN0IFM9TWF0aC5taW4oTWF0aC5mbG9vcigoZi1wKS8yKSwxKSxrPXRoaXMuZGF0YS50ZXh0QWxpZ25tZW50O2lmKHRoaXMuZGF0YS5tdWx0aUxpbmUpcmV0dXJuIHRoaXMuX2dldE11bHRpbGluZUFwcGVhcmFuY2UoZyx5LGIscCxkLGYsaywyLFMseCxtLGEpO2lmKHRoaXMuZGF0YS5jb21iKXJldHVybiB0aGlzLl9nZXRDb21iQXBwZWFyYW5jZShnLGIseVswXSxwLGQsZiwyLFMseCxtLGEpO2NvbnN0IEM9Uyt4O2lmKDA9PT1rfHxrPjIpcmV0dXJuYC9UeCBCTUMgcSAke2N9QlQgYCtnK2AgMSAwIDAgMSAke251bWJlclRvU3RyaW5nKDIpfSAke251bWJlclRvU3RyaW5nKEMpfSBUbSAoJHtlc2NhcGVTdHJpbmcoeVswXSl9KSBUaiBFVCBRIEVNQ2A7cmV0dXJuYC9UeCBCTUMgcSAke2N9QlQgYCtnK2AgMSAwIDAgMSAwIDAgVG0gJHt0aGlzLl9yZW5kZXJUZXh0KHlbMF0sYixwLGQsayx7c2hpZnQ6MH0sMixDKX0gRVQgUSBFTUNgfXN0YXRpYyBhc3luYyBfZ2V0Rm9udERhdGEoZSx0LHIsYSl7Y29uc3Qgbj1uZXcgT3BlcmF0b3JMaXN0LGk9e2ZvbnQ6bnVsbCxjbG9uZSgpe3JldHVybiB0aGlzfX0se2ZvbnROYW1lOnMsZm9udFNpemU6b309cjthd2FpdCBlLmhhbmRsZVNldEZvbnQoYSxbcyYmTmFtZS5nZXQocyksb10sbnVsbCxuLHQsaSxudWxsKTtyZXR1cm4gaS5mb250fV9nZXRUZXh0V2lkdGgoZSx0KXtyZXR1cm4gTWF0aC5zdW1QcmVjaXNlKHQuY2hhcnNUb0dseXBocyhlKS5tYXAoZT0+ZS53aWR0aCkpLzFlM31fY29tcHV0ZUZvbnRTaXplKGUsdCxyLGEsaSl7bGV0e2ZvbnRTaXplOnN9PXRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEsbz0oc3x8MTIpKm4sYz1NYXRoLnJvdW5kKGUvbyk7aWYoIXMpe2NvbnN0IHJvdW5kV2l0aFR3b0RpZ2l0cz1lPT5NYXRoLmZsb29yKDEwMCplKS8xMDA7aWYoLTE9PT1pKXtjb25zdCBpPXRoaXMuX2dldFRleHRXaWR0aChyLGEpO3M9cm91bmRXaXRoVHdvRGlnaXRzKE1hdGgubWluKGUvbix0L2kpKTtjPTF9ZWxzZXtjb25zdCBsPXIuc3BsaXQoL1xyXG4/fFxuLyksaD1bXTtmb3IoY29uc3QgZSBvZiBsKXtjb25zdCB0PWEuZW5jb2RlU3RyaW5nKGUpLmpvaW4oIiIpLHI9YS5jaGFyc1RvR2x5cGhzKHQpLG49YS5nZXRDaGFyUG9zaXRpb25zKHQpO2gucHVzaCh7bGluZTp0LGdseXBoczpyLHBvc2l0aW9uczpufSl9Y29uc3QgaXNUb29CaWc9cj0+e2xldCBuPTA7Zm9yKGNvbnN0IGkgb2YgaCl7bis9dGhpcy5fc3BsaXRMaW5lKG51bGwsYSxyLHQsaSkubGVuZ3RoKnI7aWYobj5lKXJldHVybiEwfXJldHVybiExfTtjPU1hdGgubWF4KGMsaSk7Zm9yKDs7KXtvPWUvYztzPXJvdW5kV2l0aFR3b0RpZ2l0cyhvL24pO2lmKCFpc1Rvb0JpZyhzKSlicmVhaztjKyt9fWNvbnN0e2ZvbnROYW1lOmwsZm9udENvbG9yOmh9PXRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGE7dGhpcy5fZGVmYXVsdEFwcGVhcmFuY2U9ZnVuY3Rpb24gY3JlYXRlRGVmYXVsdEFwcGVhcmFuY2Uoe2ZvbnRTaXplOmUsZm9udE5hbWU6dCxmb250Q29sb3I6cn0pe3JldHVybmAvJHtlc2NhcGVQREZOYW1lKHQpfSAke2V9IFRmICR7Z2V0UGRmQ29sb3IociwhMCl9YH0oe2ZvbnRTaXplOnMsZm9udE5hbWU6bCxmb250Q29sb3I6aH0pfXJldHVyblt0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSxzLGUvY119X3JlbmRlclRleHQoZSx0LHIsYSxuLGkscyxvKXtsZXQgYztpZigxPT09bil7Yz0oYS10aGlzLl9nZXRUZXh0V2lkdGgoZSx0KSpyKS8yfWVsc2UgaWYoMj09PW4pe2M9YS10aGlzLl9nZXRUZXh0V2lkdGgoZSx0KSpyLXN9ZWxzZSBjPXM7Y29uc3QgbD1udW1iZXJUb1N0cmluZyhjLWkuc2hpZnQpO2kuc2hpZnQ9YztyZXR1cm5gJHtsfSAke289bnVtYmVyVG9TdHJpbmcobyl9IFRkICgke2VzY2FwZVN0cmluZyhlKX0pIFRqYH1fZ2V0U2F2ZUZpZWxkUmVzb3VyY2VzKGUpe2NvbnN0e2xvY2FsUmVzb3VyY2VzOnQsYXBwZWFyYW5jZVJlc291cmNlczpyLGFjcm9Gb3JtUmVzb3VyY2VzOmF9PXRoaXMuX2ZpZWxkUmVzb3VyY2VzLG49dGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YT8uZm9udE5hbWU7aWYoIW4pcmV0dXJuIHR8fERpY3QuZW1wdHk7Zm9yKGNvbnN0IGUgb2ZbdCxyXSlpZihlIGluc3RhbmNlb2YgRGljdCl7Y29uc3QgdD1lLmdldCgiRm9udCIpO2lmKHQgaW5zdGFuY2VvZiBEaWN0JiZ0LmhhcyhuKSlyZXR1cm4gZX1pZihhIGluc3RhbmNlb2YgRGljdCl7Y29uc3Qgcj1hLmdldCgiRm9udCIpO2lmKHIgaW5zdGFuY2VvZiBEaWN0JiZyLmhhcyhuKSl7Y29uc3QgYT1uZXcgRGljdChlKTthLnNldChuLHIuZ2V0UmF3KG4pKTtjb25zdCBpPW5ldyBEaWN0KGUpO2kuc2V0KCJGb250IixhKTtyZXR1cm4gRGljdC5tZXJnZSh7eHJlZjplLGRpY3RBcnJheTpbaSx0XSxtZXJnZVN1YkRpY3RzOiEwfSl9fXJldHVybiB0fHxEaWN0LmVtcHR5fWdldEZpZWxkT2JqZWN0KCl7cmV0dXJuIG51bGx9fWNsYXNzIFRleHRXaWRnZXRBbm5vdGF0aW9uIGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTtjb25zdHtkaWN0OnR9PWU7aWYodC5oYXMoIlBNRCIpKXt0aGlzLmZsYWdzfD1OO3RoaXMuZGF0YS5oaWRkZW49ITA7d2FybigiQmFyY29kZXMgYXJlIG5vdCBzdXBwb3J0ZWQiKX10aGlzLmRhdGEuaGFzT3duQ2FudmFzPXRoaXMuZGF0YS5yZWFkT25seSYmIXRoaXMuZGF0YS5ub0hUTUw7dGhpcy5faGFzVGV4dD0hMDsic3RyaW5nIiE9dHlwZW9mIHRoaXMuZGF0YS5maWVsZFZhbHVlJiYodGhpcy5kYXRhLmZpZWxkVmFsdWU9IiIpO2xldCByPWdldEluaGVyaXRhYmxlUHJvcGVydHkoe2RpY3Q6dCxrZXk6IlEifSk7KCFOdW1iZXIuaXNJbnRlZ2VyKHIpfHxyPDB8fHI+MikmJihyPW51bGwpO3RoaXMuZGF0YS50ZXh0QWxpZ25tZW50PXI7bGV0IGE9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiTWF4TGVuIn0pOyghTnVtYmVyLmlzSW50ZWdlcihhKXx8YTwwKSYmKGE9MCk7dGhpcy5kYXRhLm1heExlbj1hO3RoaXMuZGF0YS5tdWx0aUxpbmU9dGhpcy5oYXNGaWVsZEZsYWcoVyk7dGhpcy5kYXRhLmNvbWI9dGhpcy5oYXNGaWVsZEZsYWcoWikmJiF0aGlzLmRhdGEubXVsdGlMaW5lJiYhdGhpcy5kYXRhLnBhc3N3b3JkJiYhdGhpcy5oYXNGaWVsZEZsYWcoSykmJjAhPT10aGlzLmRhdGEubWF4TGVuO3RoaXMuZGF0YS5kb05vdFNjcm9sbD10aGlzLmhhc0ZpZWxkRmxhZyhZKTtjb25zdHtkYXRhOnthY3Rpb25zOm59fT10aGlzO2lmKCFuKXJldHVybjtjb25zdCBpPS9eQUYoRGF0ZXxUaW1lKV8oPzpLZXlzdHJva2V8Rm9ybWF0KSg/OkV4KT9cKFsnIl0/KFteJyJdKylbJyJdP1wpOyQvO2xldCBzPSExOygxPT09bi5Gb3JtYXQ/Lmxlbmd0aCYmMT09PW4uS2V5c3Ryb2tlPy5sZW5ndGgmJmkudGVzdChuLkZvcm1hdFswXSkmJmkudGVzdChuLktleXN0cm9rZVswXSl8fDA9PT1uLkZvcm1hdD8ubGVuZ3RoJiYxPT09bi5LZXlzdHJva2U/Lmxlbmd0aCYmaS50ZXN0KG4uS2V5c3Ryb2tlWzBdKXx8MD09PW4uS2V5c3Ryb2tlPy5sZW5ndGgmJjE9PT1uLkZvcm1hdD8ubGVuZ3RoJiZpLnRlc3Qobi5Gb3JtYXRbMF0pKSYmKHM9ITApO2NvbnN0IG89W107bi5Gb3JtYXQmJm8ucHVzaCguLi5uLkZvcm1hdCk7bi5LZXlzdHJva2UmJm8ucHVzaCguLi5uLktleXN0cm9rZSk7aWYocyl7ZGVsZXRlIG4uS2V5c3Ryb2tlO24uRm9ybWF0PW99Zm9yKGNvbnN0IGUgb2Ygbyl7Y29uc3QgdD1lLm1hdGNoKGkpO2lmKCF0KWNvbnRpbnVlO2NvbnN0IHI9IkRhdGUiPT09dFsxXTtsZXQgYT10WzJdO2NvbnN0IG49cGFyc2VJbnQoYSwxMCk7aXNOYU4obil8fE1hdGguZmxvb3IoTWF0aC5sb2cxMChuKSkrMSE9PXRbMl0ubGVuZ3RofHwoYT0ocj9TaTpBaSlbbl0/P2EpO3RoaXMuZGF0YS5kYXRldGltZUZvcm1hdD1hO2lmKCFzKWJyZWFrO2lmKHIpe2lmKC9ISHxNTXxzc3xoLy50ZXN0KGEpKXt0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlPSJkYXRldGltZS1sb2NhbCI7dGhpcy5kYXRhLnRpbWVTdGVwPS9zcy8udGVzdChhKT8xOjYwfWVsc2UgdGhpcy5kYXRhLmRhdGV0aW1lVHlwZT0iZGF0ZSI7YnJlYWt9dGhpcy5kYXRhLmRhdGV0aW1lVHlwZT0idGltZSI7dGhpcy5kYXRhLnRpbWVTdGVwPS9zcy8udGVzdChhKT8xOjYwO2JyZWFrfX1nZXQgaGFzVGV4dENvbnRlbnQoKXtyZXR1cm4hIXRoaXMuYXBwZWFyYW5jZSYmIXRoaXMuX25lZWRBcHBlYXJhbmNlc31fZ2V0Q29tYkFwcGVhcmFuY2UoZSx0LHIsYSxuLGkscyxvLGMsbCxoKXtjb25zdCB1PW4vdGhpcy5kYXRhLm1heExlbixkPXRoaXMuZ2V0Qm9yZGVyQW5kQmFja2dyb3VuZEFwcGVhcmFuY2VzKGgpLGY9W10sZz10LmdldENoYXJQb3NpdGlvbnMocik7Zm9yKGNvbnN0W2UsdF1vZiBnKWYucHVzaChgKCR7ZXNjYXBlU3RyaW5nKHIuc3Vic3RyaW5nKGUsdCkpfSkgVGpgKTtjb25zdCBwPWYuam9pbihgICR7bnVtYmVyVG9TdHJpbmcodSl9IDAgVGQgYCk7cmV0dXJuYC9UeCBCTUMgcSAke2R9QlQgYCtlK2AgMSAwIDAgMSAke251bWJlclRvU3RyaW5nKHMpfSAke251bWJlclRvU3RyaW5nKG8rYyl9IFRtICR7cH0gRVQgUSBFTUNgfV9nZXRNdWx0aWxpbmVBcHBlYXJhbmNlKGUsdCxyLGEsbixpLHMsbyxjLGwsaCx1KXtjb25zdCBkPVtdLGY9bi0yKm8sZz17c2hpZnQ6MH07Zm9yKGxldCBlPTAsaT10Lmxlbmd0aDtlPGk7ZSsrKXtjb25zdCBpPXRbZV0sdT10aGlzLl9zcGxpdExpbmUoaSxyLGEsZik7Zm9yKGxldCB0PTAsaT11Lmxlbmd0aDt0PGk7dCsrKXtjb25zdCBpPXVbdF0sZj0wPT09ZSYmMD09PXQ/LWMtKGgtbCk6LWg7ZC5wdXNoKHRoaXMuX3JlbmRlclRleHQoaSxyLGEsbixzLGcsbyxmKSl9fWNvbnN0IHA9dGhpcy5nZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXModSksbT1kLmpvaW4oIlxuIik7cmV0dXJuYC9UeCBCTUMgcSAke3B9QlQgYCtlK2AgMSAwIDAgMSAwICR7bnVtYmVyVG9TdHJpbmcoaSl9IFRtICR7bX0gRVQgUSBFTUNgfV9zcGxpdExpbmUoZSx0LHIsYSxuPXt9KXtlPW4ubGluZXx8ZTtjb25zdCBpPW4uZ2x5cGhzfHx0LmNoYXJzVG9HbHlwaHMoZSk7aWYoaS5sZW5ndGg8PTEpcmV0dXJuW2VdO2NvbnN0IHM9bi5wb3NpdGlvbnN8fHQuZ2V0Q2hhclBvc2l0aW9ucyhlKSxvPXIvMWUzLGM9W107bGV0IGw9LTEsaD0tMSx1PS0xLGQ9MCxmPTA7Zm9yKGxldCB0PTAscj1pLmxlbmd0aDt0PHI7dCsrKXtjb25zdFtyLG5dPXNbdF0sZz1pW3RdLHA9Zy53aWR0aCpvO2lmKCIgIj09PWcudW5pY29kZSlpZihmK3A+YSl7Yy5wdXNoKGUuc3Vic3RyaW5nKGQscikpO2Q9cjtmPXA7bD0tMTt1PS0xfWVsc2V7Zis9cDtsPXI7aD1uO3U9dH1lbHNlIGlmKGYrcD5hKWlmKC0xIT09bCl7Yy5wdXNoKGUuc3Vic3RyaW5nKGQsaCkpO2Q9aDt0PXUrMTtsPS0xO2Y9MH1lbHNle2MucHVzaChlLnN1YnN0cmluZyhkLHIpKTtkPXI7Zj1wfWVsc2UgZis9cH1kPGUubGVuZ3RoJiZjLnB1c2goZS5zdWJzdHJpbmcoZCxlLmxlbmd0aCkpO3JldHVybiBjfWFzeW5jIGV4dHJhY3RUZXh0Q29udGVudChlLHQscil7YXdhaXQgc3VwZXIuZXh0cmFjdFRleHRDb250ZW50KGUsdCxyKTtjb25zdCBhPXRoaXMuZGF0YS50ZXh0Q29udGVudDtpZighYSlyZXR1cm47Y29uc3Qgbj1hLmpvaW4oIlxuIik7aWYobj09PXRoaXMuZGF0YS5maWVsZFZhbHVlKXJldHVybjtjb25zdCBpPW4ucmVwbGFjZUFsbCgvKFsuKis/XiR7fSgpfFtcXVxcXSl8KFxzKykvZywoZSx0KT0+dD9gXFwke3R9YDoiXFxzKyIpO25ldyBSZWdFeHAoYF5cXHMqJHtpfVxccyokYCkudGVzdCh0aGlzLmRhdGEuZmllbGRWYWx1ZSkmJih0aGlzLmRhdGEudGV4dENvbnRlbnQ9dGhpcy5kYXRhLmZpZWxkVmFsdWUuc3BsaXQoIlxuIikpfWdldEZpZWxkT2JqZWN0KCl7cmV0dXJue2lkOnRoaXMuZGF0YS5pZCx2YWx1ZTp0aGlzLmRhdGEuZmllbGRWYWx1ZSxkZWZhdWx0VmFsdWU6dGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlfHwiIixtdWx0aWxpbmU6dGhpcy5kYXRhLm11bHRpTGluZSxwYXNzd29yZDp0aGlzLmRhdGEucGFzc3dvcmQsY2hhckxpbWl0OnRoaXMuZGF0YS5tYXhMZW4sY29tYjp0aGlzLmRhdGEuY29tYixlZGl0YWJsZTohdGhpcy5kYXRhLnJlYWRPbmx5LGhpZGRlbjp0aGlzLmRhdGEuaGlkZGVuLG5hbWU6dGhpcy5kYXRhLmZpZWxkTmFtZSxyZWN0OnRoaXMuZGF0YS5yZWN0LGFjdGlvbnM6dGhpcy5kYXRhLmFjdGlvbnMscGFnZTp0aGlzLmRhdGEucGFnZUluZGV4LHN0cm9rZUNvbG9yOnRoaXMuZGF0YS5ib3JkZXJDb2xvcixmaWxsQ29sb3I6dGhpcy5kYXRhLmJhY2tncm91bmRDb2xvcixyb3RhdGlvbjp0aGlzLnJvdGF0aW9uLGRhdGV0aW1lRm9ybWF0OnRoaXMuZGF0YS5kYXRldGltZUZvcm1hdCxoYXNEYXRldGltZUhUTUw6ISF0aGlzLmRhdGEuZGF0ZXRpbWVUeXBlLHR5cGU6InRleHQifX19Y2xhc3MgQnV0dG9uV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIFdpZGdldEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7dGhpcy5jaGVja2VkQXBwZWFyYW5jZT1udWxsO3RoaXMudW5jaGVja2VkQXBwZWFyYW5jZT1udWxsO2NvbnN0IHQ9dGhpcy5oYXNGaWVsZEZsYWcoRykscj10aGlzLmhhc0ZpZWxkRmxhZygkKTt0aGlzLmRhdGEuY2hlY2tCb3g9IXQmJiFyO3RoaXMuZGF0YS5yYWRpb0J1dHRvbj10JiYhcjt0aGlzLmRhdGEucHVzaEJ1dHRvbj1yO3RoaXMuZGF0YS5pc1Rvb2x0aXBPbmx5PSExO2lmKHRoaXMuZGF0YS5jaGVja0JveCl0aGlzLl9wcm9jZXNzQ2hlY2tCb3goZSk7ZWxzZSBpZih0aGlzLmRhdGEucmFkaW9CdXR0b24pdGhpcy5fcHJvY2Vzc1JhZGlvQnV0dG9uKGUpO2Vsc2UgaWYodGhpcy5kYXRhLnB1c2hCdXR0b24pe3RoaXMuZGF0YS5oYXNPd25DYW52YXM9ITA7dGhpcy5kYXRhLm5vSFRNTD0hMTt0aGlzLl9wcm9jZXNzUHVzaEJ1dHRvbihlKX1lbHNlIHdhcm4oIkludmFsaWQgZmllbGQgZmxhZ3MgZm9yIGJ1dHRvbiB3aWRnZXQgYW5ub3RhdGlvbiIpfWFzeW5jIGdldE9wZXJhdG9yTGlzdChlLHQscixhKXtpZih0aGlzLmRhdGEucHVzaEJ1dHRvbilyZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGUsdCxyLCExLGEpO2xldCBuPW51bGwsaT1udWxsO2lmKGEpe2NvbnN0IGU9YS5nZXQodGhpcy5kYXRhLmlkKTtuPWU/ZS52YWx1ZTpudWxsO2k9ZT9lLnJvdGF0aW9uOm51bGx9aWYobnVsbD09PW4mJnRoaXMuYXBwZWFyYW5jZSlyZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGUsdCxyLGEpO251bGw9PW4mJihuPXRoaXMuZGF0YS5jaGVja0JveD90aGlzLmRhdGEuZmllbGRWYWx1ZT09PXRoaXMuZGF0YS5leHBvcnRWYWx1ZTp0aGlzLmRhdGEuZmllbGRWYWx1ZT09PXRoaXMuZGF0YS5idXR0b25WYWx1ZSk7Y29uc3Qgcz1uP3RoaXMuY2hlY2tlZEFwcGVhcmFuY2U6dGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlO2lmKHMpe2NvbnN0IG49dGhpcy5hcHBlYXJhbmNlLG89bG9va3VwTWF0cml4KHMuZGljdC5nZXRBcnJheSgiTWF0cml4IiksZnIpO2kmJnMuZGljdC5zZXQoIk1hdHJpeCIsdGhpcy5nZXRSb3RhdGlvbk1hdHJpeChhKSk7dGhpcy5hcHBlYXJhbmNlPXM7Y29uc3QgYz1zdXBlci5nZXRPcGVyYXRvckxpc3QoZSx0LHIsYSk7dGhpcy5hcHBlYXJhbmNlPW47cy5kaWN0LnNldCgiTWF0cml4IixvKTtyZXR1cm4gY31yZXR1cm57b3BMaXN0Om5ldyBPcGVyYXRvckxpc3Qsc2VwYXJhdGVGb3JtOiExLHNlcGFyYXRlQ2FudmFzOiExfX1hc3luYyBzYXZlKGUsdCxyLGEpe3RoaXMuZGF0YS5jaGVja0JveD90aGlzLl9zYXZlQ2hlY2tib3goZSx0LHIsYSk6dGhpcy5kYXRhLnJhZGlvQnV0dG9uJiZ0aGlzLl9zYXZlUmFkaW9CdXR0b24oZSx0LHIsYSl9YXN5bmMgX3NhdmVDaGVja2JveChlLHQscixhKXtpZighcilyZXR1cm47Y29uc3Qgbj1yLmdldCh0aGlzLmRhdGEuaWQpLGk9dGhpcy5fYnVpbGRGbGFncyhuPy5ub1ZpZXcsbj8ubm9QcmludCk7bGV0IHM9bj8ucm90YXRpb24sbz1uPy52YWx1ZTtpZih2b2lkIDA9PT1zJiZ2b2lkIDA9PT1pKXtpZih2b2lkIDA9PT1vKXJldHVybjtpZih0aGlzLmRhdGEuZmllbGRWYWx1ZT09PXRoaXMuZGF0YS5leHBvcnRWYWx1ZT09PW8pcmV0dXJufWxldCBjPWUueHJlZi5mZXRjaElmUmVmKHRoaXMucmVmKTtpZighKGMgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm47Yz1jLmNsb25lKCk7dm9pZCAwPT09cyYmKHM9dGhpcy5yb3RhdGlvbik7dm9pZCAwPT09byYmKG89dGhpcy5kYXRhLmZpZWxkVmFsdWU9PT10aGlzLmRhdGEuZXhwb3J0VmFsdWUpO2NvbnN0IGw9e3BhdGg6dGhpcy5kYXRhLmZpZWxkTmFtZSx2YWx1ZTpvP3RoaXMuZGF0YS5leHBvcnRWYWx1ZToiIn0saD1OYW1lLmdldChvP3RoaXMuZGF0YS5leHBvcnRWYWx1ZToiT2ZmIik7dGhpcy5zZXRWYWx1ZShjLGgsZS54cmVmLGEpO2Muc2V0KCJBUyIsaCk7Yy5zZXQoIk0iLGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZSgpfWApO3ZvaWQgMCE9PWkmJmMuc2V0KCJGIixpKTtjb25zdCB1PXRoaXMuX2dldE1LRGljdChzKTt1JiZjLnNldCgiTUsiLHUpO2EucHV0KHRoaXMucmVmLHtkYXRhOmMseGZhOmwsbmVlZEFwcGVhcmFuY2VzOiExfSl9YXN5bmMgX3NhdmVSYWRpb0J1dHRvbihlLHQscixhKXtpZighcilyZXR1cm47Y29uc3Qgbj1yLmdldCh0aGlzLmRhdGEuaWQpLGk9dGhpcy5fYnVpbGRGbGFncyhuPy5ub1ZpZXcsbj8ubm9QcmludCk7bGV0IHM9bj8ucm90YXRpb24sbz1uPy52YWx1ZTtpZih2b2lkIDA9PT1zJiZ2b2lkIDA9PT1pKXtpZih2b2lkIDA9PT1vKXJldHVybjtpZih0aGlzLmRhdGEuZmllbGRWYWx1ZT09PXRoaXMuZGF0YS5idXR0b25WYWx1ZT09PW8pcmV0dXJufWxldCBjPWUueHJlZi5mZXRjaElmUmVmKHRoaXMucmVmKTtpZighKGMgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm47Yz1jLmNsb25lKCk7dm9pZCAwPT09byYmKG89dGhpcy5kYXRhLmZpZWxkVmFsdWU9PT10aGlzLmRhdGEuYnV0dG9uVmFsdWUpO3ZvaWQgMD09PXMmJihzPXRoaXMucm90YXRpb24pO2NvbnN0IGw9e3BhdGg6dGhpcy5kYXRhLmZpZWxkTmFtZSx2YWx1ZTpvP3RoaXMuZGF0YS5idXR0b25WYWx1ZToiIn0saD1OYW1lLmdldChvP3RoaXMuZGF0YS5idXR0b25WYWx1ZToiT2ZmIik7byYmdGhpcy5zZXRWYWx1ZShjLGgsZS54cmVmLGEpO2Muc2V0KCJBUyIsaCk7Yy5zZXQoIk0iLGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZSgpfWApO3ZvaWQgMCE9PWkmJmMuc2V0KCJGIixpKTtjb25zdCB1PXRoaXMuX2dldE1LRGljdChzKTt1JiZjLnNldCgiTUsiLHUpO2EucHV0KHRoaXMucmVmLHtkYXRhOmMseGZhOmwsbmVlZEFwcGVhcmFuY2VzOiExfSl9X2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShlLHQpe2NvbnN0e3dpZHRoOnIsaGVpZ2h0OmF9PXRoaXMsbj1bMCwwLHIsYV0saT0uOCpNYXRoLm1pbihyLGEpO2xldCBzLG87aWYoImNoZWNrIj09PXQpe3M9e3dpZHRoOi43NTUqaSxoZWlnaHQ6LjcwNSppfTtvPSIzIn1lbHNlIGlmKCJkaXNjIj09PXQpe3M9e3dpZHRoOi43OTEqaSxoZWlnaHQ6LjcwNSppfTtvPSJsIn1lbHNlIHVucmVhY2hhYmxlKGBfZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlIC0gdW5zdXBwb3J0ZWQgdHlwZTogJHt0fWApO2NvbnN0IGM9YHEgQlQgL1BkZkpzWmFEYiAke2l9IFRmIDAgZyAke251bWJlclRvU3RyaW5nKChyLXMud2lkdGgpLzIpfSAke251bWJlclRvU3RyaW5nKChhLXMuaGVpZ2h0KS8yKX0gVGQgKCR7b30pIFRqIEVUIFFgLGw9bmV3IERpY3QoZS54cmVmKTtsLnNldCgiRm9ybVR5cGUiLDEpO2wuc2V0SWZOYW1lKCJTdWJ0eXBlIiwiRm9ybSIpO2wuc2V0SWZOYW1lKCJUeXBlIiwiWE9iamVjdCIpO2wuc2V0KCJCQm94IixuKTtsLnNldCgiTWF0cml4IixbMSwwLDAsMSwwLDBdKTtsLnNldCgiTGVuZ3RoIixjLmxlbmd0aCk7Y29uc3QgaD1uZXcgRGljdChlLnhyZWYpLHU9bmV3IERpY3QoZS54cmVmKTt1LnNldCgiUGRmSnNaYURiIix0aGlzLmZhbGxiYWNrRm9udERpY3QpO2guc2V0KCJGb250Iix1KTtsLnNldCgiUmVzb3VyY2VzIixoKTt0aGlzLmNoZWNrZWRBcHBlYXJhbmNlPW5ldyBTdHJpbmdTdHJlYW0oYyk7dGhpcy5jaGVja2VkQXBwZWFyYW5jZS5kaWN0PWw7dGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpfV9wcm9jZXNzQ2hlY2tCb3goZSl7Y29uc3QgdD1lLmRpY3QuZ2V0KCJBUCIpO2lmKCEodCBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtjb25zdCByPXQuZ2V0KCJOIik7aWYoIShyIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuO2NvbnN0IGE9dGhpcy5fZGVjb2RlRm9ybVZhbHVlKGUuZGljdC5nZXQoIkFTIikpOyJzdHJpbmciPT10eXBlb2YgYSYmKHRoaXMuZGF0YS5maWVsZFZhbHVlPWEpO2NvbnN0IG49bnVsbCE9PXRoaXMuZGF0YS5maWVsZFZhbHVlJiYiT2ZmIiE9PXRoaXMuZGF0YS5maWVsZFZhbHVlP3RoaXMuZGF0YS5maWVsZFZhbHVlOiJZZXMiLGk9dGhpcy5fZGVjb2RlRm9ybVZhbHVlKHIuZ2V0S2V5cygpKTtpZigwPT09aS5sZW5ndGgpaS5wdXNoKCJPZmYiLG4pO2Vsc2UgaWYoMT09PWkubGVuZ3RoKSJPZmYiPT09aVswXT9pLnB1c2gobik6aS51bnNoaWZ0KCJPZmYiKTtlbHNlIGlmKGkuaW5jbHVkZXMobikpe2kubGVuZ3RoPTA7aS5wdXNoKCJPZmYiLG4pfWVsc2V7Y29uc3QgZT1pLmZpbmQoZT0+Ik9mZiIhPT1lKTtpLmxlbmd0aD0wO2kucHVzaCgiT2ZmIixlKX1pLmluY2x1ZGVzKHRoaXMuZGF0YS5maWVsZFZhbHVlKXx8KHRoaXMuZGF0YS5maWVsZFZhbHVlPSJPZmYiKTt0aGlzLmRhdGEuZXhwb3J0VmFsdWU9aVsxXTtjb25zdCBzPXIuZ2V0KHRoaXMuZGF0YS5leHBvcnRWYWx1ZSk7dGhpcy5jaGVja2VkQXBwZWFyYW5jZT1zIGluc3RhbmNlb2YgQmFzZVN0cmVhbT9zOm51bGw7Y29uc3Qgbz1yLmdldCgiT2ZmIik7dGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlPW8gaW5zdGFuY2VvZiBCYXNlU3RyZWFtP286bnVsbDt0aGlzLmNoZWNrZWRBcHBlYXJhbmNlP3RoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmNoZWNrZWRBcHBlYXJhbmNlKTp0aGlzLl9nZXREZWZhdWx0Q2hlY2tlZEFwcGVhcmFuY2UoZSwiY2hlY2siKTt0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UmJnRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UpO3RoaXMuX2ZhbGxiYWNrRm9udERpY3Q9dGhpcy5mYWxsYmFja0ZvbnREaWN0O251bGw9PT10aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWUmJih0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWU9Ik9mZiIpfV9wcm9jZXNzUmFkaW9CdXR0b24oZSl7dGhpcy5kYXRhLmJ1dHRvblZhbHVlPW51bGw7Y29uc3QgdD1lLmRpY3QuZ2V0KCJQYXJlbnQiKTtpZih0IGluc3RhbmNlb2YgRGljdCl7dGhpcy5wYXJlbnQ9ZS5kaWN0LmdldFJhdygiUGFyZW50Iik7Y29uc3Qgcj10LmdldCgiViIpO3IgaW5zdGFuY2VvZiBOYW1lJiYodGhpcy5kYXRhLmZpZWxkVmFsdWU9dGhpcy5fZGVjb2RlRm9ybVZhbHVlKHIpKX1jb25zdCByPWUuZGljdC5nZXQoIkFQIik7aWYoIShyIGluc3RhbmNlb2YgRGljdCkpcmV0dXJuO2NvbnN0IGE9ci5nZXQoIk4iKTtpZighKGEgaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm47Zm9yKGNvbnN0IGUgb2YgYS5nZXRLZXlzKCkpaWYoIk9mZiIhPT1lKXt0aGlzLmRhdGEuYnV0dG9uVmFsdWU9dGhpcy5fZGVjb2RlRm9ybVZhbHVlKGUpO2JyZWFrfWNvbnN0IG49YS5nZXQodGhpcy5kYXRhLmJ1dHRvblZhbHVlKTt0aGlzLmNoZWNrZWRBcHBlYXJhbmNlPW4gaW5zdGFuY2VvZiBCYXNlU3RyZWFtP246bnVsbDtjb25zdCBpPWEuZ2V0KCJPZmYiKTt0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2U9aSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0/aTpudWxsO3RoaXMuY2hlY2tlZEFwcGVhcmFuY2U/dGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpOnRoaXMuX2dldERlZmF1bHRDaGVja2VkQXBwZWFyYW5jZShlLCJkaXNjIik7dGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlJiZ0aGlzLl9zdHJlYW1zLnB1c2godGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKTt0aGlzLl9mYWxsYmFja0ZvbnREaWN0PXRoaXMuZmFsbGJhY2tGb250RGljdDtudWxsPT09dGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlJiYodGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlPSJPZmYiKX1fcHJvY2Vzc1B1c2hCdXR0b24oZSl7Y29uc3R7ZGljdDp0LGFubm90YXRpb25HbG9iYWxzOnJ9PWU7aWYodC5oYXMoIkEiKXx8dC5oYXMoIkFBIil8fHRoaXMuZGF0YS5hbHRlcm5hdGl2ZVRleHQpe3RoaXMuZGF0YS5pc1Rvb2x0aXBPbmx5PSF0LmhhcygiQSIpJiYhdC5oYXMoIkFBIik7Q2F0YWxvZy5wYXJzZURlc3REaWN0aW9uYXJ5KHtkZXN0RGljdDp0LHJlc3VsdE9iajp0aGlzLmRhdGEsZG9jQmFzZVVybDpyLmJhc2VVcmwsZG9jQXR0YWNobWVudHM6ci5hdHRhY2htZW50c30pfWVsc2Ugd2FybigiUHVzaCBidXR0b25zIHdpdGhvdXQgYWN0aW9uIGRpY3Rpb25hcmllcyBhcmUgbm90IHN1cHBvcnRlZCIpfWdldEZpZWxkT2JqZWN0KCl7bGV0IGUsdD0iYnV0dG9uIjtpZih0aGlzLmRhdGEuY2hlY2tCb3gpe3Q9ImNoZWNrYm94IjtlPXRoaXMuZGF0YS5leHBvcnRWYWx1ZX1lbHNlIGlmKHRoaXMuZGF0YS5yYWRpb0J1dHRvbil7dD0icmFkaW9idXR0b24iO2U9dGhpcy5kYXRhLmJ1dHRvblZhbHVlfXJldHVybntpZDp0aGlzLmRhdGEuaWQsdmFsdWU6dGhpcy5kYXRhLmZpZWxkVmFsdWV8fCJPZmYiLGRlZmF1bHRWYWx1ZTp0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWUsZXhwb3J0VmFsdWVzOmUsZWRpdGFibGU6IXRoaXMuZGF0YS5yZWFkT25seSxuYW1lOnRoaXMuZGF0YS5maWVsZE5hbWUscmVjdDp0aGlzLmRhdGEucmVjdCxoaWRkZW46dGhpcy5kYXRhLmhpZGRlbixhY3Rpb25zOnRoaXMuZGF0YS5hY3Rpb25zLHBhZ2U6dGhpcy5kYXRhLnBhZ2VJbmRleCxzdHJva2VDb2xvcjp0aGlzLmRhdGEuYm9yZGVyQ29sb3IsZmlsbENvbG9yOnRoaXMuZGF0YS5iYWNrZ3JvdW5kQ29sb3Iscm90YXRpb246dGhpcy5yb3RhdGlvbix0eXBlOnR9fWdldCBmYWxsYmFja0ZvbnREaWN0KCl7Y29uc3QgZT1uZXcgRGljdDtlLnNldElmTmFtZSgiQmFzZUZvbnQiLCJaYXBmRGluZ2JhdHMiKTtlLnNldElmTmFtZSgiVHlwZSIsIkZhbGxiYWNrVHlwZSIpO2Uuc2V0SWZOYW1lKCJTdWJ0eXBlIiwiRmFsbGJhY2tUeXBlIik7ZS5zZXRJZk5hbWUoIkVuY29kaW5nIiwiWmFwZkRpbmdiYXRzRW5jb2RpbmciKTtyZXR1cm4gc2hhZG93KHRoaXMsImZhbGxiYWNrRm9udERpY3QiLGUpfX1jbGFzcyBDaG9pY2VXaWRnZXRBbm5vdGF0aW9uIGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTtjb25zdHtkaWN0OnQseHJlZjpyfT1lO3RoaXMuaW5kaWNlcz10LmdldEFycmF5KCJJIik7dGhpcy5oYXNJbmRpY2VzPUFycmF5LmlzQXJyYXkodGhpcy5pbmRpY2VzKSYmdGhpcy5pbmRpY2VzLmxlbmd0aD4wO3RoaXMuZGF0YS5vcHRpb25zPVtdO2NvbnN0IGE9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0LGtleToiT3B0In0pO2lmKEFycmF5LmlzQXJyYXkoYSkpZm9yKGxldCBlPTAsdD1hLmxlbmd0aDtlPHQ7ZSsrKXtjb25zdCB0PXIuZmV0Y2hJZlJlZihhW2VdKSxuPUFycmF5LmlzQXJyYXkodCk7dGhpcy5kYXRhLm9wdGlvbnNbZV09e2V4cG9ydFZhbHVlOnRoaXMuX2RlY29kZUZvcm1WYWx1ZShuP3IuZmV0Y2hJZlJlZih0WzBdKTp0KSxkaXNwbGF5VmFsdWU6dGhpcy5fZGVjb2RlRm9ybVZhbHVlKG4/ci5mZXRjaElmUmVmKHRbMV0pOnQpfX1pZih0aGlzLmhhc0luZGljZXMpe3RoaXMuZGF0YS5maWVsZFZhbHVlPVtdO2NvbnN0IGU9dGhpcy5kYXRhLm9wdGlvbnMubGVuZ3RoO2Zvcihjb25zdCB0IG9mIHRoaXMuaW5kaWNlcylOdW1iZXIuaXNJbnRlZ2VyKHQpJiZ0Pj0wJiZ0PGUmJnRoaXMuZGF0YS5maWVsZFZhbHVlLnB1c2godGhpcy5kYXRhLm9wdGlvbnNbdF0uZXhwb3J0VmFsdWUpfWVsc2Uic3RyaW5nIj09dHlwZW9mIHRoaXMuZGF0YS5maWVsZFZhbHVlP3RoaXMuZGF0YS5maWVsZFZhbHVlPVt0aGlzLmRhdGEuZmllbGRWYWx1ZV06dGhpcy5kYXRhLmZpZWxkVmFsdWV8fD1bXTswPT09dGhpcy5kYXRhLm9wdGlvbnMubGVuZ3RoJiZ0aGlzLmRhdGEuZmllbGRWYWx1ZS5sZW5ndGg+MCYmKHRoaXMuZGF0YS5vcHRpb25zPXRoaXMuZGF0YS5maWVsZFZhbHVlLm1hcChlPT4oe2V4cG9ydFZhbHVlOmUsZGlzcGxheVZhbHVlOmV9KSkpO3RoaXMuZGF0YS5jb21ibz10aGlzLmhhc0ZpZWxkRmxhZyhWKTt0aGlzLmRhdGEubXVsdGlTZWxlY3Q9dGhpcy5oYXNGaWVsZEZsYWcoSik7dGhpcy5faGFzVGV4dD0hMH1nZXRGaWVsZE9iamVjdCgpe2NvbnN0IGU9dGhpcy5kYXRhLmNvbWJvPyJjb21ib2JveCI6Imxpc3Rib3giLHQ9dGhpcy5kYXRhLmZpZWxkVmFsdWUubGVuZ3RoPjA/dGhpcy5kYXRhLmZpZWxkVmFsdWVbMF06bnVsbDtyZXR1cm57aWQ6dGhpcy5kYXRhLmlkLHZhbHVlOnQsZGVmYXVsdFZhbHVlOnRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSxlZGl0YWJsZTohdGhpcy5kYXRhLnJlYWRPbmx5LG5hbWU6dGhpcy5kYXRhLmZpZWxkTmFtZSxyZWN0OnRoaXMuZGF0YS5yZWN0LG51bUl0ZW1zOnRoaXMuZGF0YS5maWVsZFZhbHVlLmxlbmd0aCxtdWx0aXBsZVNlbGVjdGlvbjp0aGlzLmRhdGEubXVsdGlTZWxlY3QsaGlkZGVuOnRoaXMuZGF0YS5oaWRkZW4sYWN0aW9uczp0aGlzLmRhdGEuYWN0aW9ucyxpdGVtczp0aGlzLmRhdGEub3B0aW9ucyxwYWdlOnRoaXMuZGF0YS5wYWdlSW5kZXgsc3Ryb2tlQ29sb3I6dGhpcy5kYXRhLmJvcmRlckNvbG9yLGZpbGxDb2xvcjp0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLHJvdGF0aW9uOnRoaXMucm90YXRpb24sdHlwZTplfX1hbWVuZFNhdmVkRGljdChlLHQpe2lmKCF0aGlzLmhhc0luZGljZXMpcmV0dXJuO2xldCByPWU/LmdldCh0aGlzLmRhdGEuaWQpPy52YWx1ZTtBcnJheS5pc0FycmF5KHIpfHwocj1bcl0pO2NvbnN0IGE9W10se29wdGlvbnM6bn09dGhpcy5kYXRhO2ZvcihsZXQgZT0wLHQ9MCxpPW4ubGVuZ3RoO2U8aTtlKyspaWYobltlXS5leHBvcnRWYWx1ZT09PXJbdF0pe2EucHVzaChlKTt0Kz0xfXQuc2V0KCJJIixhKX1hc3luYyBfZ2V0QXBwZWFyYW5jZShlLHQscixhKXtpZih0aGlzLmRhdGEuY29tYm8pcmV0dXJuIHN1cGVyLl9nZXRBcHBlYXJhbmNlKGUsdCxyLGEpO2xldCBpLHM7Y29uc3Qgbz1hPy5nZXQodGhpcy5kYXRhLmlkKTtpZihvKXtzPW8ucm90YXRpb247aT1vLnZhbHVlfWlmKHZvaWQgMD09PXMmJnZvaWQgMD09PWkmJiF0aGlzLl9uZWVkQXBwZWFyYW5jZXMpcmV0dXJuIG51bGw7dm9pZCAwPT09aT9pPXRoaXMuZGF0YS5maWVsZFZhbHVlOkFycmF5LmlzQXJyYXkoaSl8fChpPVtpXSk7bGV0e3dpZHRoOmMsaGVpZ2h0Omx9PXRoaXM7OTAhPT1zJiYyNzAhPT1zfHwoW2MsbF09W2wsY10pO2NvbnN0IGg9dGhpcy5kYXRhLm9wdGlvbnMubGVuZ3RoLHU9W107Zm9yKGxldCBlPTA7ZTxoO2UrKyl7Y29uc3R7ZXhwb3J0VmFsdWU6dH09dGhpcy5kYXRhLm9wdGlvbnNbZV07aS5pbmNsdWRlcyh0KSYmdS5wdXNoKGUpfXRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlfHwodGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YT1wYXJzZURlZmF1bHRBcHBlYXJhbmNlKHRoaXMuX2RlZmF1bHRBcHBlYXJhbmNlPSIvSGVsdmV0aWNhIDAgVGYgMCBnIikpO2NvbnN0IGQ9YXdhaXQgV2lkZ2V0QW5ub3RhdGlvbi5fZ2V0Rm9udERhdGEoZSx0LHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEsdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzKTtsZXQgZix7Zm9udFNpemU6Z309dGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTtpZihnKWY9dGhpcy5fZGVmYXVsdEFwcGVhcmFuY2U7ZWxzZXtjb25zdCBlPShsLTEpL2g7bGV0IHQscj0tMTtmb3IoY29uc3R7ZGlzcGxheVZhbHVlOmV9b2YgdGhpcy5kYXRhLm9wdGlvbnMpe2NvbnN0IGE9dGhpcy5fZ2V0VGV4dFdpZHRoKGUsZCk7aWYoYT5yKXtyPWE7dD1lfX1bZixnXT10aGlzLl9jb21wdXRlRm9udFNpemUoZSxjLTQsdCxkLC0xKX1jb25zdCBwPWcqbixtPShwLWcpLzIsYj1NYXRoLmZsb29yKGwvcCk7bGV0IHk9MDtpZih1Lmxlbmd0aD4wKXtjb25zdCBlPU1hdGgubWluKC4uLnUpLHQ9TWF0aC5tYXgoLi4udSk7eT1NYXRoLm1heCgwLHQtYisxKTt5PmUmJih5PWUpfWNvbnN0IHc9TWF0aC5taW4oeStiKzEsaCkseD1bIi9UeCBCTUMgcSIsYDEgMSAke2N9ICR7bH0gcmUgVyBuYF07aWYodS5sZW5ndGgpe3gucHVzaCgiMC42MDAwMDYgMC43NTY4NjYgMC44NTQ5MDQgcmciKTtmb3IoY29uc3QgZSBvZiB1KXk8PWUmJmU8dyYmeC5wdXNoKGAxICR7bC0oZS15KzEpKnB9ICR7Y30gJHtwfSByZSBmYCl9eC5wdXNoKCJCVCIsZixgMSAwIDAgMSAwICR7bH0gVG1gKTtjb25zdCBTPXtzaGlmdDowfTtmb3IobGV0IGU9eTtlPHc7ZSsrKXtjb25zdHtkaXNwbGF5VmFsdWU6dH09dGhpcy5kYXRhLm9wdGlvbnNbZV0scj1lPT09eT9tOjA7eC5wdXNoKHRoaXMuX3JlbmRlclRleHQodCxkLGcsYywwLFMsMiwtcCtyKSl9eC5wdXNoKCJFVCBRIEVNQyIpO3JldHVybiB4LmpvaW4oIlxuIil9fWNsYXNzIFNpZ25hdHVyZVdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBXaWRnZXRBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO3RoaXMuZGF0YS5maWVsZFZhbHVlPW51bGw7dGhpcy5kYXRhLmhhc093bkNhbnZhcz10aGlzLmRhdGEubm9Sb3RhdGU7dGhpcy5kYXRhLm5vSFRNTD0hdGhpcy5kYXRhLmhhc093bkNhbnZhc31nZXRGaWVsZE9iamVjdCgpe3JldHVybntpZDp0aGlzLmRhdGEuaWQsdmFsdWU6bnVsbCxwYWdlOnRoaXMuZGF0YS5wYWdlSW5kZXgsdHlwZToic2lnbmF0dXJlIn19fWNsYXNzIFRleHRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTt0aGlzLmRhdGEubm9Sb3RhdGU9ITA7dGhpcy5kYXRhLmhhc093bkNhbnZhcz10aGlzLmRhdGEubm9Sb3RhdGU7dGhpcy5kYXRhLm5vSFRNTD0hMTtjb25zdHtkaWN0OnR9PWU7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uVEVYVDtpZih0aGlzLmRhdGEuaGFzQXBwZWFyYW5jZSl0aGlzLmRhdGEubmFtZT0iTm9JY29uIjtlbHNle3RoaXMuZGF0YS5yZWN0WzFdPXRoaXMuZGF0YS5yZWN0WzNdLTIyO3RoaXMuZGF0YS5yZWN0WzJdPXRoaXMuZGF0YS5yZWN0WzBdKzIyO3RoaXMuZGF0YS5uYW1lPXQuaGFzKCJOYW1lIik/dC5nZXQoIk5hbWUiKS5uYW1lOiJOb3RlIn1pZih0LmhhcygiU3RhdGUiKSl7dGhpcy5kYXRhLnN0YXRlPXQuZ2V0KCJTdGF0ZSIpfHxudWxsO3RoaXMuZGF0YS5zdGF0ZU1vZGVsPXQuZ2V0KCJTdGF0ZU1vZGVsIil8fG51bGx9ZWxzZXt0aGlzLmRhdGEuc3RhdGU9bnVsbDt0aGlzLmRhdGEuc3RhdGVNb2RlbD1udWxsfX19Y2xhc3MgTGlua0Fubm90YXRpb24gZXh0ZW5kcyBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO2NvbnN0e2RpY3Q6dCxhbm5vdGF0aW9uR2xvYmFsczpyfT1lO3RoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZT1NLkxJTks7dGhpcy5kYXRhLm5vSFRNTD0hMTtjb25zdCBhPWdldFF1YWRQb2ludHModCx0aGlzLnJlY3RhbmdsZSk7YSYmKHRoaXMuZGF0YS5xdWFkUG9pbnRzPWEpO3RoaXMuZGF0YS5ib3JkZXJDb2xvcnx8PXRoaXMuZGF0YS5jb2xvcjtDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoe2Rlc3REaWN0OnQscmVzdWx0T2JqOnRoaXMuZGF0YSxkb2NCYXNlVXJsOnIuYmFzZVVybCxkb2NBdHRhY2htZW50czpyLmF0dGFjaG1lbnRzfSl9Z2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKXtyZXR1cm4hMH19Y2xhc3MgUG9wdXBBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTtjb25zdHtkaWN0OnR9PWU7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uUE9QVVA7dGhpcy5kYXRhLm5vSFRNTD0hMTswIT09dGhpcy53aWR0aCYmMCE9PXRoaXMuaGVpZ2h0fHwodGhpcy5kYXRhLnJlY3Q9bnVsbCk7bGV0IHI9dC5nZXQoIlBhcmVudCIpO2lmKCFyKXt3YXJuKCJQb3B1cCBhbm5vdGF0aW9uIGhhcyBhIG1pc3Npbmcgb3IgaW52YWxpZCBwYXJlbnQgYW5ub3RhdGlvbi4iKTtyZXR1cm59dGhpcy5kYXRhLnBhcmVudFJlY3Q9bG9va3VwTm9ybWFsUmVjdChyLmdldEFycmF5KCJSZWN0IiksbnVsbCk7dGhpcy5kYXRhLmNyZWF0aW9uRGF0ZT1yLmdldCgiQ3JlYXRpb25EYXRlIil8fCIiO2lzTmFtZShyLmdldCgiUlQiKSxEKSYmKHI9ci5nZXQoIklSVCIpKTtpZihyLmhhcygiTSIpKXt0aGlzLnNldE1vZGlmaWNhdGlvbkRhdGUoci5nZXQoIk0iKSk7dGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGU9dGhpcy5tb2RpZmljYXRpb25EYXRlfWVsc2UgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGU9bnVsbDtpZihyLmhhcygiQyIpKXt0aGlzLnNldENvbG9yKHIuZ2V0QXJyYXkoIkMiKSk7dGhpcy5kYXRhLmNvbG9yPXRoaXMuY29sb3J9ZWxzZSB0aGlzLmRhdGEuY29sb3I9bnVsbDtpZighdGhpcy52aWV3YWJsZSl7Y29uc3QgZT1yLmdldCgiRiIpO3RoaXMuX2lzVmlld2FibGUoZSkmJnRoaXMuc2V0RmxhZ3MoZSl9dGhpcy5zZXRUaXRsZShyLmdldCgiVCIpKTt0aGlzLmRhdGEudGl0bGVPYmo9dGhpcy5fdGl0bGU7dGhpcy5zZXRDb250ZW50cyhyLmdldCgiQ29udGVudHMiKSk7dGhpcy5kYXRhLmNvbnRlbnRzT2JqPXRoaXMuX2NvbnRlbnRzO3IuaGFzKCJSQyIpJiYodGhpcy5kYXRhLnJpY2hUZXh0PVhGQUZhY3RvcnkuZ2V0UmljaFRleHRBc0h0bWwoci5nZXQoIlJDIikpKTt0aGlzLmRhdGEub3Blbj0hIXQuZ2V0KCJPcGVuIil9c3RhdGljIGNyZWF0ZU5ld0RpY3QoZSx0LHIpe2NvbnN0e29sZEFubm90YXRpb246YSxyZWN0Om4scGFyZW50Oml9PWUscz1hfHxuZXcgRGljdCh0KTtzLnNldElmTm90RXhpc3RzKCJUeXBlIixOYW1lLmdldCgiQW5ub3QiKSk7cy5zZXRJZk5vdEV4aXN0cygiU3VidHlwZSIsTmFtZS5nZXQoIlBvcHVwIikpO3Muc2V0SWZOb3RFeGlzdHMoIk9wZW4iLCExKTtzLnNldElmQXJyYXkoIlJlY3QiLG4pO3Muc2V0KCJQYXJlbnQiLGkpO3JldHVybiBzfXN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGUsdCxyKXtyZXR1cm4gbnVsbH19Y2xhc3MgRnJlZVRleHRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTt0aGlzLmRhdGEuaGFzT3duQ2FudmFzPXRoaXMuZGF0YS5ub1JvdGF0ZTt0aGlzLmRhdGEuaXNFZGl0YWJsZT0hdGhpcy5kYXRhLm5vSFRNTDt0aGlzLmRhdGEubm9IVE1MPSExO2NvbnN0e2Fubm90YXRpb25HbG9iYWxzOnQsZXZhbHVhdG9yT3B0aW9uczpyLHhyZWY6YX09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5GUkVFVEVYVDt0aGlzLnNldERlZmF1bHRBcHBlYXJhbmNlKGUpO3RoaXMuX2hhc0FwcGVhcmFuY2U9ISF0aGlzLmFwcGVhcmFuY2U7aWYodGhpcy5faGFzQXBwZWFyYW5jZSl7Y29uc3R7Zm9udENvbG9yOmUsZm9udFNpemU6bn09ZnVuY3Rpb24gcGFyc2VBcHBlYXJhbmNlU3RyZWFtKGUsdCxyLGEpe3JldHVybiBuZXcgQXBwZWFyYW5jZVN0cmVhbUV2YWx1YXRvcihlLHQscixhKS5wYXJzZSgpfSh0aGlzLmFwcGVhcmFuY2UscixhLHQuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlKTt0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRDb2xvcj1lO3RoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEuZm9udFNpemU9bnx8MTB9ZWxzZXt0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRTaXplfHw9MTA7Y29uc3R7Zm9udENvbG9yOnQsZm9udFNpemU6cn09dGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTtpZih0aGlzLl9jb250ZW50cy5zdHIpe3RoaXMuZGF0YS50ZXh0Q29udGVudD10aGlzLl9jb250ZW50cy5zdHIuc3BsaXQoL1xyXG4/fFxuLykubWFwKGU9PmUudHJpbUVuZCgpKTtjb25zdHtjb29yZHM6ZSxiYm94OnQsbWF0cml4OmF9PUZha2VVbmljb2RlRm9udC5nZXRGaXJzdFBvc2l0aW9uSW5mbyh0aGlzLnJlY3RhbmdsZSx0aGlzLnJvdGF0aW9uLHIpO3RoaXMuZGF0YS50ZXh0UG9zaXRpb249dGhpcy5fdHJhbnNmb3JtUG9pbnQoZSx0LGEpfWlmKHRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKXtjb25zdCBuPWUuZGljdC5nZXQoIkNBIiksaT1uZXcgRmFrZVVuaWNvZGVGb250KGEsInNhbnMtc2VyaWYiKTt0aGlzLmFwcGVhcmFuY2U9aS5jcmVhdGVBcHBlYXJhbmNlKHRoaXMuX2NvbnRlbnRzLnN0cix0aGlzLnJlY3RhbmdsZSx0aGlzLnJvdGF0aW9uLHIsdCxuKTt0aGlzLl9zdHJlYW1zLnB1c2godGhpcy5hcHBlYXJhbmNlKX1lbHNlIHdhcm4oIkZyZWVUZXh0QW5ub3RhdGlvbjogT2Zmc2NyZWVuQ2FudmFzIGlzIG5vdCBzdXBwb3J0ZWQsIGFubm90YXRpb24gbWF5IG5vdCByZW5kZXIgY29ycmVjdGx5LiIpfX1nZXQgaGFzVGV4dENvbnRlbnQoKXtyZXR1cm4gdGhpcy5faGFzQXBwZWFyYW5jZX1zdGF0aWMgY3JlYXRlTmV3RGljdChlLHQse2FwUmVmOnIsYXA6YX0pe2NvbnN0e2NvbG9yOm4sZGF0ZTppLGZvbnRTaXplOnMsb2xkQW5ub3RhdGlvbjpvLHJlY3Q6Yyxyb3RhdGlvbjpsLHVzZXI6aCx2YWx1ZTp1fT1lLGQ9b3x8bmV3IERpY3QodCk7ZC5zZXRJZk5vdEV4aXN0cygiVHlwZSIsTmFtZS5nZXQoIkFubm90IikpO2Quc2V0SWZOb3RFeGlzdHMoIlN1YnR5cGUiLE5hbWUuZ2V0KCJGcmVlVGV4dCIpKTtkLnNldChvPyJNIjoiQ3JlYXRpb25EYXRlIixgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoaSl9YCk7byYmZC5kZWxldGUoIlJDIik7ZC5zZXRJZkFycmF5KCJSZWN0IixjKTtjb25zdCBmPWAvSGVsdiAke3N9IFRmICR7Z2V0UGRmQ29sb3IobiwhMCl9YDtkLnNldCgiREEiLGYpO2Quc2V0SWZEZWZpbmVkKCJDb250ZW50cyIsc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh1KSk7ZC5zZXRJZk5vdEV4aXN0cygiRiIsNCk7ZC5zZXRJZk5vdEV4aXN0cygiQm9yZGVyIixbMCwwLDBdKTtkLnNldElmTnVtYmVyKCJSb3RhdGUiLGwpO2Quc2V0SWZEZWZpbmVkKCJUIixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGgpKTtpZihyfHxhKXtjb25zdCBlPW5ldyBEaWN0KHQpO2Quc2V0KCJBUCIsZSk7ZS5zZXQoIk4iLHJ8fGEpfXJldHVybiBkfXN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGUsdCxyKXtjb25zdHtiYXNlRm9udFJlZjphLGV2YWx1YXRvcjppLHRhc2s6c309cix7Y29sb3I6byxmb250U2l6ZTpjLHJlY3Q6bCxyb3RhdGlvbjpoLHZhbHVlOnV9PWU7aWYoIW8pcmV0dXJuIG51bGw7Y29uc3QgZD1uZXcgRGljdCh0KSxmPW5ldyBEaWN0KHQpO2lmKGEpZi5zZXQoIkhlbHYiLGEpO2Vsc2V7Y29uc3QgZT1uZXcgRGljdCh0KTtlLnNldElmTmFtZSgiQmFzZUZvbnQiLCJIZWx2ZXRpY2EiKTtlLnNldElmTmFtZSgiVHlwZSIsIkZvbnQiKTtlLnNldElmTmFtZSgiU3VidHlwZSIsIlR5cGUxIik7ZS5zZXRJZk5hbWUoIkVuY29kaW5nIiwiV2luQW5zaUVuY29kaW5nIik7Zi5zZXQoIkhlbHYiLGUpfWQuc2V0KCJGb250IixmKTtjb25zdCBnPWF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGkscyx7Zm9udE5hbWU6IkhlbHYiLGZvbnRTaXplOmN9LGQpLFtwLG0sYix5XT1sO2xldCB3PWItcCx4PXktbTtoJTE4MCE9MCYmKFt3LHhdPVt4LHddKTtjb25zdCBTPXUuc3BsaXQoIlxuIiksaz1jLzFlMztsZXQgQz0tMS8wO2NvbnN0IHY9W107Zm9yKGxldCBlIG9mIFMpe2NvbnN0IHQ9Zy5lbmNvZGVTdHJpbmcoZSk7aWYodC5sZW5ndGg+MSlyZXR1cm4gbnVsbDtlPXQuam9pbigiIik7di5wdXNoKGUpO2xldCByPTA7Y29uc3QgYT1nLmNoYXJzVG9HbHlwaHMoZSk7Zm9yKGNvbnN0IGUgb2YgYSlyKz1lLndpZHRoKms7Qz1NYXRoLm1heChDLHIpfWxldCBUPTE7Qz53JiYoVD13L0MpO2xldCBPPTE7Y29uc3QgTT1uKmMsRD0xKmMsUj1NKlMubGVuZ3RoO1I+eCYmKE89eC9SKTtjb25zdCBFPWMqTWF0aC5taW4oVCxPKTtsZXQgTixfLEw7c3dpdGNoKGgpe2Nhc2UgMDpMPVsxLDAsMCwxXTtfPVtsWzBdLGxbMV0sdyx4XTtOPVtsWzBdLGxbM10tRF07YnJlYWs7Y2FzZSA5MDpMPVswLDEsLTEsMF07Xz1bbFsxXSwtbFsyXSx3LHhdO049W2xbMV0sLWxbMF0tRF07YnJlYWs7Y2FzZSAxODA6TD1bLTEsMCwwLC0xXTtfPVstbFsyXSwtbFszXSx3LHhdO049Wy1sWzJdLC1sWzFdLURdO2JyZWFrO2Nhc2UgMjcwOkw9WzAsLTEsMSwwXTtfPVstbFszXSxsWzBdLHcseF07Tj1bLWxbM10sbFsyXS1EXX1jb25zdCBqPVsicSIsYCR7TC5qb2luKCIgIil9IDAgMCBjbWAsYCR7Xy5qb2luKCIgIil9IHJlIFcgbmAsIkJUIixgJHtnZXRQZGZDb2xvcihvLCEwKX1gLGAwIFRjIC9IZWx2ICR7bnVtYmVyVG9TdHJpbmcoRSl9IFRmYF07ai5wdXNoKGAke04uam9pbigiICIpfSBUZCAoJHtlc2NhcGVTdHJpbmcodlswXSl9KSBUamApO2NvbnN0IFU9bnVtYmVyVG9TdHJpbmcoTSk7Zm9yKGxldCBlPTEsdD12Lmxlbmd0aDtlPHQ7ZSsrKXtjb25zdCB0PXZbZV07ai5wdXNoKGAwIC0ke1V9IFRkICgke2VzY2FwZVN0cmluZyh0KX0pIFRqYCl9ai5wdXNoKCJFVCIsIlEiKTtjb25zdCBxPWouam9pbigiXG4iKSxYPW5ldyBEaWN0KHQpO1guc2V0KCJGb3JtVHlwZSIsMSk7WC5zZXRJZk5hbWUoIlN1YnR5cGUiLCJGb3JtIik7WC5zZXRJZk5hbWUoIlR5cGUiLCJYT2JqZWN0Iik7WC5zZXQoIkJCb3giLGwpO1guc2V0KCJSZXNvdXJjZXMiLGQpO1guc2V0KCJNYXRyaXgiLFsxLDAsMCwxLC1sWzBdLC1sWzFdXSk7Y29uc3QgSD1uZXcgU3RyaW5nU3RyZWFtKHEpO0guZGljdD1YO3JldHVybiBIfX1jbGFzcyBMaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5MSU5FO3RoaXMuZGF0YS5oYXNPd25DYW52YXM9dGhpcy5kYXRhLm5vUm90YXRlO3RoaXMuZGF0YS5ub0hUTUw9ITE7Y29uc3QgYT1sb29rdXBSZWN0KHQuZ2V0QXJyYXkoIkwiKSxbMCwwLDAsMF0pO3RoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXM9VXRpbC5ub3JtYWxpemVSZWN0KGEpO3RoaXMuc2V0TGluZUVuZGluZ3ModC5nZXRBcnJheSgiTEUiKSk7dGhpcy5kYXRhLmxpbmVFbmRpbmdzPXRoaXMubGluZUVuZGluZ3M7aWYoIXRoaXMuYXBwZWFyYW5jZSl7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzAsMCwwXSksbj10LmdldCgiQ0EiKSxpPWdldFBkZkNvbG9yQXJyYXkoZ2V0UmdiQ29sb3IodC5nZXRBcnJheSgiSUMiKSxudWxsKSkscz1pP246bnVsbCxvPXRoaXMuYm9yZGVyU3R5bGUud2lkdGh8fDEsYz0yKm8sbD1bdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1swXS1jLHRoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXNbMV0tYyx0aGlzLmRhdGEubGluZUNvb3JkaW5hdGVzWzJdK2MsdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1szXStjXTtVdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSxsKXx8KHRoaXMucmVjdGFuZ2xlPWwpO3RoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHt4cmVmOnIsZXh0cmE6YCR7b30gd2Asc3Ryb2tlQ29sb3I6ZSxmaWxsQ29sb3I6aSxzdHJva2VBbHBoYTpuLGZpbGxBbHBoYTpzLHBvaW50c0NhbGxiYWNrOihlLHQpPT57ZS5wdXNoKGAke2FbMF19ICR7YVsxXX0gbWAsYCR7YVsyXX0gJHthWzNdfSBsYCwiUyIpO3JldHVyblt0WzBdLW8sdFs3XS1vLHRbMl0rbyx0WzNdK29dfX0pfX19Y2xhc3MgU3F1YXJlQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5TUVVBUkU7dGhpcy5kYXRhLmhhc093bkNhbnZhcz10aGlzLmRhdGEubm9Sb3RhdGU7dGhpcy5kYXRhLm5vSFRNTD0hMTtpZighdGhpcy5hcHBlYXJhbmNlKXtjb25zdCBlPWdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvcixbMCwwLDBdKSxhPXQuZ2V0KCJDQSIpLG49Z2V0UGRmQ29sb3JBcnJheShnZXRSZ2JDb2xvcih0LmdldEFycmF5KCJJQyIpLG51bGwpKSxpPW4/YTpudWxsO2lmKDA9PT10aGlzLmJvcmRlclN0eWxlLndpZHRoJiYhbilyZXR1cm47dGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2Uoe3hyZWY6cixleHRyYTpgJHt0aGlzLmJvcmRlclN0eWxlLndpZHRofSB3YCxzdHJva2VDb2xvcjplLGZpbGxDb2xvcjpuLHN0cm9rZUFscGhhOmEsZmlsbEFscGhhOmkscG9pbnRzQ2FsbGJhY2s6KGUsdCk9Pntjb25zdCByPXRbNF0rdGhpcy5ib3JkZXJTdHlsZS53aWR0aC8yLGE9dFs1XSt0aGlzLmJvcmRlclN0eWxlLndpZHRoLzIsaT10WzZdLXRbNF0tdGhpcy5ib3JkZXJTdHlsZS53aWR0aCxzPXRbM10tdFs3XS10aGlzLmJvcmRlclN0eWxlLndpZHRoO2UucHVzaChgJHtyfSAke2F9ICR7aX0gJHtzfSByZWApO24/ZS5wdXNoKCJCIik6ZS5wdXNoKCJTIik7cmV0dXJuW3RbMF0sdFs3XSx0WzJdLHRbM11dfX0pfX19Y2xhc3MgQ2lyY2xlQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5DSVJDTEU7aWYoIXRoaXMuYXBwZWFyYW5jZSl7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzAsMCwwXSksYT10LmdldCgiQ0EiKSxuPWdldFBkZkNvbG9yQXJyYXkoZ2V0UmdiQ29sb3IodC5nZXRBcnJheSgiSUMiKSxudWxsKSksaT1uP2E6bnVsbDtpZigwPT09dGhpcy5ib3JkZXJTdHlsZS53aWR0aCYmIW4pcmV0dXJuO2NvbnN0IHM9NC8zKk1hdGgudGFuKE1hdGguUEkvOCk7dGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2Uoe3hyZWY6cixleHRyYTpgJHt0aGlzLmJvcmRlclN0eWxlLndpZHRofSB3YCxzdHJva2VDb2xvcjplLGZpbGxDb2xvcjpuLHN0cm9rZUFscGhhOmEsZmlsbEFscGhhOmkscG9pbnRzQ2FsbGJhY2s6KGUsdCk9Pntjb25zdCByPXRbMF0rdGhpcy5ib3JkZXJTdHlsZS53aWR0aC8yLGE9dFsxXS10aGlzLmJvcmRlclN0eWxlLndpZHRoLzIsaT10WzZdLXRoaXMuYm9yZGVyU3R5bGUud2lkdGgvMixvPXRbN10rdGhpcy5ib3JkZXJTdHlsZS53aWR0aC8yLGM9cisoaS1yKS8yLGw9YSsoby1hKS8yLGg9KGktcikvMipzLHU9KG8tYSkvMipzO2UucHVzaChgJHtjfSAke299IG1gLGAke2MraH0gJHtvfSAke2l9ICR7bCt1fSAke2l9ICR7bH0gY2AsYCR7aX0gJHtsLXV9ICR7YytofSAke2F9ICR7Y30gJHthfSBjYCxgJHtjLWh9ICR7YX0gJHtyfSAke2wtdX0gJHtyfSAke2x9IGNgLGAke3J9ICR7bCt1fSAke2MtaH0gJHtvfSAke2N9ICR7b30gY2AsImgiKTtuP2UucHVzaCgiQiIpOmUucHVzaCgiUyIpO3JldHVyblt0WzBdLHRbN10sdFsyXSx0WzNdXX19KX19fWNsYXNzIFBvbHlsaW5lQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5QT0xZTElORTt0aGlzLmRhdGEuaGFzT3duQ2FudmFzPXRoaXMuZGF0YS5ub1JvdGF0ZTt0aGlzLmRhdGEubm9IVE1MPSExO3RoaXMuZGF0YS52ZXJ0aWNlcz1udWxsO2lmKCEodGhpcyBpbnN0YW5jZW9mIFBvbHlnb25Bbm5vdGF0aW9uKSl7dGhpcy5zZXRMaW5lRW5kaW5ncyh0LmdldEFycmF5KCJMRSIpKTt0aGlzLmRhdGEubGluZUVuZGluZ3M9dGhpcy5saW5lRW5kaW5nc31jb25zdCBhPXQuZ2V0QXJyYXkoIlZlcnRpY2VzIik7aWYoIWlzTnVtYmVyQXJyYXkoYSxudWxsKSlyZXR1cm47Y29uc3Qgbj10aGlzLmRhdGEudmVydGljZXM9RmxvYXQzMkFycmF5LmZyb20oYSk7aWYoIXRoaXMuYXBwZWFyYW5jZSl7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzAsMCwwXSksYT10LmdldCgiQ0EiKTtsZXQgaSxzPWdldFJnYkNvbG9yKHQuZ2V0QXJyYXkoIklDIiksbnVsbCk7cyYmKHM9Z2V0UGRmQ29sb3JBcnJheShzKSk7aT1zP3RoaXMuY29sb3I/cy5ldmVyeSgodCxyKT0+dD09PWVbcl0pPyJmIjoiQiI6ImYiOiJTIjtjb25zdCBvPXRoaXMuYm9yZGVyU3R5bGUud2lkdGh8fDEsYz0yKm8sbD1bMS8wLDEvMCwtMS8wLC0xLzBdO2ZvcihsZXQgZT0wLHQ9bi5sZW5ndGg7ZTx0O2UrPTIpVXRpbC5yZWN0Qm91bmRpbmdCb3gobltlXS1jLG5bZSsxXS1jLG5bZV0rYyxuW2UrMV0rYyxsKTtVdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSxsKXx8KHRoaXMucmVjdGFuZ2xlPWwpO3RoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHt4cmVmOnIsZXh0cmE6YCR7b30gd2Asc3Ryb2tlQ29sb3I6ZSxzdHJva2VBbHBoYTphLGZpbGxDb2xvcjpzLGZpbGxBbHBoYTpzP2E6bnVsbCxwb2ludHNDYWxsYmFjazooZSx0KT0+e2ZvcihsZXQgdD0wLHI9bi5sZW5ndGg7dDxyO3QrPTIpZS5wdXNoKGAke25bdF19ICR7blt0KzFdfSAkezA9PT10PyJtIjoibCJ9YCk7ZS5wdXNoKGkpO3JldHVyblt0WzBdLHRbN10sdFsyXSx0WzNdXX19KX19fWNsYXNzIFBvbHlnb25Bbm5vdGF0aW9uIGV4dGVuZHMgUG9seWxpbmVBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO3RoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZT1NLlBPTFlHT059fWNsYXNzIENhcmV0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uQ0FSRVR9fWNsYXNzIElua0Fubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO3RoaXMuZGF0YS5oYXNPd25DYW52YXM9dGhpcy5kYXRhLm5vUm90YXRlO3RoaXMuZGF0YS5ub0hUTUw9ITE7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5JTks7dGhpcy5kYXRhLmlua0xpc3RzPVtdO3RoaXMuZGF0YS5pc0VkaXRhYmxlPSF0aGlzLmRhdGEubm9IVE1MO3RoaXMuZGF0YS5ub0hUTUw9ITE7dGhpcy5kYXRhLm9wYWNpdHk9dC5nZXQoIkNBIil8fDE7Y29uc3QgYT10LmdldEFycmF5KCJJbmtMaXN0Iik7aWYoQXJyYXkuaXNBcnJheShhKSl7Zm9yKGxldCBlPTAsdD1hLmxlbmd0aDtlPHQ7KytlKXtpZighQXJyYXkuaXNBcnJheShhW2VdKSljb250aW51ZTtjb25zdCB0PW5ldyBGbG9hdDMyQXJyYXkoYVtlXS5sZW5ndGgpO3RoaXMuZGF0YS5pbmtMaXN0cy5wdXNoKHQpO2ZvcihsZXQgbj0wLGk9YVtlXS5sZW5ndGg7bjxpO24rPTIpe2NvbnN0IGk9ci5mZXRjaElmUmVmKGFbZV1bbl0pLHM9ci5mZXRjaElmUmVmKGFbZV1bbisxXSk7aWYoIm51bWJlciI9PXR5cGVvZiBpJiYibnVtYmVyIj09dHlwZW9mIHMpe3Rbbl09aTt0W24rMV09c319fWlmKCF0aGlzLmFwcGVhcmFuY2Upe2NvbnN0IGU9Z2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLFswLDAsMF0pLGE9dC5nZXQoIkNBIiksbj10aGlzLmJvcmRlclN0eWxlLndpZHRofHwxLGk9MipuLHM9WzEvMCwxLzAsLTEvMCwtMS8wXTtmb3IoY29uc3QgZSBvZiB0aGlzLmRhdGEuaW5rTGlzdHMpZm9yKGxldCB0PTAscj1lLmxlbmd0aDt0PHI7dCs9MilVdGlsLnJlY3RCb3VuZGluZ0JveChlW3RdLWksZVt0KzFdLWksZVt0XStpLGVbdCsxXStpLHMpO1V0aWwuaW50ZXJzZWN0KHRoaXMucmVjdGFuZ2xlLHMpfHwodGhpcy5yZWN0YW5nbGU9cyk7dGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2Uoe3hyZWY6cixleHRyYTpgJHtufSB3YCxzdHJva2VDb2xvcjplLHN0cm9rZUFscGhhOmEscG9pbnRzQ2FsbGJhY2s6KGUsdCk9Pntmb3IoY29uc3QgdCBvZiB0aGlzLmRhdGEuaW5rTGlzdHMpe2ZvcihsZXQgcj0wLGE9dC5sZW5ndGg7cjxhO3IrPTIpZS5wdXNoKGAke3Rbcl19ICR7dFtyKzFdfSAkezA9PT1yPyJtIjoibCJ9YCk7ZS5wdXNoKCJTIil9cmV0dXJuW3RbMF0sdFs3XSx0WzJdLHRbM11dfX0pfX19c3RhdGljIGNyZWF0ZU5ld0RpY3QoZSx0LHthcFJlZjpyLGFwOmF9KXtjb25zdHtvbGRBbm5vdGF0aW9uOm4sY29sb3I6aSxkYXRlOnMsb3BhY2l0eTpvLHBhdGhzOmMsb3V0bGluZXM6bCxyZWN0Omgscm90YXRpb246dSx0aGlja25lc3M6ZCx1c2VyOmZ9PWUsZz1ufHxuZXcgRGljdCh0KTtnLnNldElmTm90RXhpc3RzKCJUeXBlIixOYW1lLmdldCgiQW5ub3QiKSk7Zy5zZXRJZk5vdEV4aXN0cygiU3VidHlwZSIsTmFtZS5nZXQoIkluayIpKTtnLnNldChuPyJNIjoiQ3JlYXRpb25EYXRlIixgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUocyl9YCk7Zy5zZXRJZkFycmF5KCJSZWN0IixoKTtnLnNldElmQXJyYXkoIklua0xpc3QiLGw/LnBvaW50c3x8Yz8ucG9pbnRzKTtnLnNldElmTm90RXhpc3RzKCJGIiw0KTtnLnNldElmTnVtYmVyKCJSb3RhdGUiLHUpO2cuc2V0SWZEZWZpbmVkKCJUIixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGYpKTtsJiZnLnNldElmTmFtZSgiSVQiLCJJbmtIaWdobGlnaHQiKTtpZihkPjApe2NvbnN0IGU9bmV3IERpY3QodCk7Zy5zZXQoIkJTIixlKTtlLnNldCgiVyIsZCl9Zy5zZXRJZkFycmF5KCJDIixnZXRQZGZDb2xvckFycmF5KGkpKTtnLnNldElmTnVtYmVyKCJDQSIsbyk7aWYoYXx8cil7Y29uc3QgZT1uZXcgRGljdCh0KTtnLnNldCgiQVAiLGUpO2Uuc2V0KCJOIixyfHxhKX1yZXR1cm4gZ31zdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShlLHQscil7aWYoZS5vdXRsaW5lcylyZXR1cm4gdGhpcy5jcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtRm9ySGlnaGxpZ2h0KGUsdCxyKTtjb25zdHtjb2xvcjphLHJlY3Q6bixwYXRoczppLHRoaWNrbmVzczpzLG9wYWNpdHk6b309ZTtpZighYSlyZXR1cm4gbnVsbDtjb25zdCBjPVtgJHtzfSB3IDEgSiAxIGpgLGAke2dldFBkZkNvbG9yKGEsITEpfWBdOzEhPT1vJiZjLnB1c2goIi9SMCBncyIpO2Zvcihjb25zdCBlIG9mIGkubGluZXMpe2MucHVzaChgJHtudW1iZXJUb1N0cmluZyhlWzRdKX0gJHtudW1iZXJUb1N0cmluZyhlWzVdKX0gbWApO2ZvcihsZXQgdD02LHI9ZS5sZW5ndGg7dDxyO3QrPTYpaWYoaXNOYU4oZVt0XSkpYy5wdXNoKGAke251bWJlclRvU3RyaW5nKGVbdCs0XSl9ICR7bnVtYmVyVG9TdHJpbmcoZVt0KzVdKX0gbGApO2Vsc2V7Y29uc3RbcixhLG4saSxzLG9dPWUuc2xpY2UodCx0KzYpO2MucHVzaChbcixhLG4saSxzLG9dLm1hcChudW1iZXJUb1N0cmluZykuam9pbigiICIpKyIgYyIpfTY9PT1lLmxlbmd0aCYmYy5wdXNoKGAke251bWJlclRvU3RyaW5nKGVbNF0pfSAke251bWJlclRvU3RyaW5nKGVbNV0pfSBsYCl9Yy5wdXNoKCJTIik7Y29uc3QgbD1jLmpvaW4oIlxuIiksaD1uZXcgRGljdCh0KTtoLnNldCgiRm9ybVR5cGUiLDEpO2guc2V0SWZOYW1lKCJTdWJ0eXBlIiwiRm9ybSIpO2guc2V0SWZOYW1lKCJUeXBlIiwiWE9iamVjdCIpO2guc2V0KCJCQm94IixuKTtoLnNldCgiTGVuZ3RoIixsLmxlbmd0aCk7aWYoMSE9PW8pe2NvbnN0IGU9bmV3IERpY3QodCkscj1uZXcgRGljdCh0KSxhPW5ldyBEaWN0KHQpO2Euc2V0KCJDQSIsbyk7YS5zZXRJZk5hbWUoIlR5cGUiLCJFeHRHU3RhdGUiKTtyLnNldCgiUjAiLGEpO2Uuc2V0KCJFeHRHU3RhdGUiLHIpO2guc2V0KCJSZXNvdXJjZXMiLGUpfWNvbnN0IHU9bmV3IFN0cmluZ1N0cmVhbShsKTt1LmRpY3Q9aDtyZXR1cm4gdX1zdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbUZvckhpZ2hsaWdodChlLHQscil7Y29uc3R7Y29sb3I6YSxyZWN0Om4sb3V0bGluZXM6e291dGxpbmU6aX0sb3BhY2l0eTpzfT1lO2lmKCFhKXJldHVybiBudWxsO2NvbnN0IG89W2Ake2dldFBkZkNvbG9yKGEsITApfWAsIi9SMCBncyJdO28ucHVzaChgJHtudW1iZXJUb1N0cmluZyhpWzRdKX0gJHtudW1iZXJUb1N0cmluZyhpWzVdKX0gbWApO2ZvcihsZXQgZT02LHQ9aS5sZW5ndGg7ZTx0O2UrPTYpaWYoaXNOYU4oaVtlXSkpby5wdXNoKGAke251bWJlclRvU3RyaW5nKGlbZSs0XSl9ICR7bnVtYmVyVG9TdHJpbmcoaVtlKzVdKX0gbGApO2Vsc2V7Y29uc3RbdCxyLGEsbixzLGNdPWkuc2xpY2UoZSxlKzYpO28ucHVzaChbdCxyLGEsbixzLGNdLm1hcChudW1iZXJUb1N0cmluZykuam9pbigiICIpKyIgYyIpfW8ucHVzaCgiaCBmIik7Y29uc3QgYz1vLmpvaW4oIlxuIiksbD1uZXcgRGljdCh0KTtsLnNldCgiRm9ybVR5cGUiLDEpO2wuc2V0SWZOYW1lKCJTdWJ0eXBlIiwiRm9ybSIpO2wuc2V0SWZOYW1lKCJUeXBlIiwiWE9iamVjdCIpO2wuc2V0KCJCQm94IixuKTtsLnNldCgiTGVuZ3RoIixjLmxlbmd0aCk7Y29uc3QgaD1uZXcgRGljdCh0KSx1PW5ldyBEaWN0KHQpO2guc2V0KCJFeHRHU3RhdGUiLHUpO2wuc2V0KCJSZXNvdXJjZXMiLGgpO2NvbnN0IGQ9bmV3IERpY3QodCk7dS5zZXQoIlIwIixkKTtkLnNldElmTmFtZSgiQk0iLCJNdWx0aXBseSIpO2lmKDEhPT1zKXtkLnNldCgiY2EiLHMpO2Quc2V0SWZOYW1lKCJUeXBlIiwiRXh0R1N0YXRlIil9Y29uc3QgZj1uZXcgU3RyaW5nU3RyZWFtKGMpO2YuZGljdD1sO3JldHVybiBmfX1jbGFzcyBIaWdobGlnaHRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbntjb25zdHJ1Y3RvcihlKXtzdXBlcihlKTtjb25zdHtkaWN0OnQseHJlZjpyfT1lO3RoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZT1NLkhJR0hMSUdIVDt0aGlzLmRhdGEuaXNFZGl0YWJsZT0hdGhpcy5kYXRhLm5vSFRNTDt0aGlzLmRhdGEubm9IVE1MPSExO3RoaXMuZGF0YS5vcGFjaXR5PXQuZ2V0KCJDQSIpfHwxO2lmKHRoaXMuZGF0YS5xdWFkUG9pbnRzPWdldFF1YWRQb2ludHModCxudWxsKSl7Y29uc3QgZT10aGlzLmFwcGVhcmFuY2U/LmRpY3QuZ2V0KCJSZXNvdXJjZXMiKTtpZighdGhpcy5hcHBlYXJhbmNlfHwhZT8uaGFzKCJFeHRHU3RhdGUiKSl7dGhpcy5hcHBlYXJhbmNlJiZ3YXJuKCJIaWdobGlnaHRBbm5vdGF0aW9uIC0gaWdub3JpbmcgYnVpbHQtaW4gYXBwZWFyYW5jZSBzdHJlYW0uIik7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzEsMSwwXSksYT10LmdldCgiQ0EiKTt0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7eHJlZjpyLGZpbGxDb2xvcjplLGJsZW5kTW9kZToiTXVsdGlwbHkiLGZpbGxBbHBoYTphLHBvaW50c0NhbGxiYWNrOihlLHQpPT57ZS5wdXNoKGAke3RbMF19ICR7dFsxXX0gbWAsYCR7dFsyXX0gJHt0WzNdfSBsYCxgJHt0WzZdfSAke3RbN119IGxgLGAke3RbNF19ICR7dFs1XX0gbGAsImYiKTtyZXR1cm5bdFswXSx0WzddLHRbMl0sdFszXV19fSl9fWVsc2UgdGhpcy5kYXRhLnBvcHVwUmVmPW51bGx9Z2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKXtyZXR1cm4hMH1zdGF0aWMgY3JlYXRlTmV3RGljdChlLHQse2FwUmVmOnIsYXA6YX0pe2NvbnN0e2NvbG9yOm4sZGF0ZTppLG9sZEFubm90YXRpb246cyxvcGFjaXR5Om8scmVjdDpjLHJvdGF0aW9uOmwsdXNlcjpoLHF1YWRQb2ludHM6dX09ZSxkPXN8fG5ldyBEaWN0KHQpO2Quc2V0SWZOb3RFeGlzdHMoIlR5cGUiLE5hbWUuZ2V0KCJBbm5vdCIpKTtkLnNldElmTm90RXhpc3RzKCJTdWJ0eXBlIixOYW1lLmdldCgiSGlnaGxpZ2h0IikpO2Quc2V0KHM/Ik0iOiJDcmVhdGlvbkRhdGUiLGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZShpKX1gKTtkLnNldElmQXJyYXkoIlJlY3QiLGMpO2Quc2V0SWZOb3RFeGlzdHMoIkYiLDQpO2Quc2V0SWZOb3RFeGlzdHMoIkJvcmRlciIsWzAsMCwwXSk7ZC5zZXRJZk51bWJlcigiUm90YXRlIixsKTtkLnNldElmQXJyYXkoIlF1YWRQb2ludHMiLHUpO2Quc2V0SWZBcnJheSgiQyIsZ2V0UGRmQ29sb3JBcnJheShuKSk7ZC5zZXRJZk51bWJlcigiQ0EiLG8pO2Quc2V0SWZEZWZpbmVkKCJUIixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGgpKTtpZihyfHxhKXtjb25zdCBlPW5ldyBEaWN0KHQpO2Quc2V0KCJBUCIsZSk7ZS5zZXQoIk4iLHJ8fGEpfXJldHVybiBkfXN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGUsdCxyKXtjb25zdHtjb2xvcjphLHJlY3Q6bixvdXRsaW5lczppLG9wYWNpdHk6c309ZTtpZighYSlyZXR1cm4gbnVsbDtjb25zdCBvPVtgJHtnZXRQZGZDb2xvcihhLCEwKX1gLCIvUjAgZ3MiXSxjPVtdO2Zvcihjb25zdCBlIG9mIGkpe2MubGVuZ3RoPTA7Yy5wdXNoKGAke251bWJlclRvU3RyaW5nKGVbMF0pfSAke251bWJlclRvU3RyaW5nKGVbMV0pfSBtYCk7Zm9yKGxldCB0PTIscj1lLmxlbmd0aDt0PHI7dCs9MiljLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcoZVt0XSl9ICR7bnVtYmVyVG9TdHJpbmcoZVt0KzFdKX0gbGApO2MucHVzaCgiaCIpO28ucHVzaChjLmpvaW4oIlxuIikpfW8ucHVzaCgiZioiKTtjb25zdCBsPW8uam9pbigiXG4iKSxoPW5ldyBEaWN0KHQpO2guc2V0KCJGb3JtVHlwZSIsMSk7aC5zZXRJZk5hbWUoIlN1YnR5cGUiLCJGb3JtIik7aC5zZXRJZk5hbWUoIlR5cGUiLCJYT2JqZWN0Iik7aC5zZXQoIkJCb3giLG4pO2guc2V0KCJMZW5ndGgiLGwubGVuZ3RoKTtjb25zdCB1PW5ldyBEaWN0KHQpLGQ9bmV3IERpY3QodCk7dS5zZXQoIkV4dEdTdGF0ZSIsZCk7aC5zZXQoIlJlc291cmNlcyIsdSk7Y29uc3QgZj1uZXcgRGljdCh0KTtkLnNldCgiUjAiLGYpO2Yuc2V0SWZOYW1lKCJCTSIsIk11bHRpcGx5Iik7aWYoMSE9PXMpe2Yuc2V0KCJjYSIscyk7Zi5zZXRJZk5hbWUoIlR5cGUiLCJFeHRHU3RhdGUiKX1jb25zdCBnPW5ldyBTdHJpbmdTdHJlYW0obCk7Zy5kaWN0PWg7cmV0dXJuIGd9fWNsYXNzIFVuZGVybGluZUFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO2NvbnN0e2RpY3Q6dCx4cmVmOnJ9PWU7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uVU5ERVJMSU5FO2lmKHRoaXMuZGF0YS5xdWFkUG9pbnRzPWdldFF1YWRQb2ludHModCxudWxsKSl7aWYoIXRoaXMuYXBwZWFyYW5jZSl7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzAsMCwwXSksYT10LmdldCgiQ0EiKTt0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7eHJlZjpyLGV4dHJhOiJbXSAwIGQgMC41NzEgdyIsc3Ryb2tlQ29sb3I6ZSxzdHJva2VBbHBoYTphLHBvaW50c0NhbGxiYWNrOihlLHQpPT57ZS5wdXNoKGAke3RbNF19ICR7dFs1XSsxLjN9IG1gLGAke3RbNl19ICR7dFs3XSsxLjN9IGxgLCJTIik7cmV0dXJuW3RbMF0sdFs3XSx0WzJdLHRbM11dfX0pfX1lbHNlIHRoaXMuZGF0YS5wb3B1cFJlZj1udWxsfWdldCBvdmVybGF5c1RleHRDb250ZW50KCl7cmV0dXJuITB9fWNsYXNzIFNxdWlnZ2x5QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb257Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3R7ZGljdDp0LHhyZWY6cn09ZTt0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGU9TS5TUVVJR0dMWTtpZih0aGlzLmRhdGEucXVhZFBvaW50cz1nZXRRdWFkUG9pbnRzKHQsbnVsbCkpe2lmKCF0aGlzLmFwcGVhcmFuY2Upe2NvbnN0IGU9Z2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLFswLDAsMF0pLGE9dC5nZXQoIkNBIik7dGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2Uoe3hyZWY6cixleHRyYToiW10gMCBkIDEgdyIsc3Ryb2tlQ29sb3I6ZSxzdHJva2VBbHBoYTphLHBvaW50c0NhbGxiYWNrOihlLHQpPT57Y29uc3Qgcj0odFsxXS10WzVdKS82O2xldCBhPXIsbj10WzRdO2NvbnN0IGk9dFs1XSxzPXRbNl07ZS5wdXNoKGAke259ICR7aSthfSBtYCk7ZG97bis9MjthPTA9PT1hP3I6MDtlLnB1c2goYCR7bn0gJHtpK2F9IGxgKX13aGlsZShuPHMpO2UucHVzaCgiUyIpO3JldHVyblt0WzRdLGktMipyLHMsaSsyKnJdfX0pfX1lbHNlIHRoaXMuZGF0YS5wb3B1cFJlZj1udWxsfWdldCBvdmVybGF5c1RleHRDb250ZW50KCl7cmV0dXJuITB9fWNsYXNzIFN0cmlrZU91dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO2NvbnN0e2RpY3Q6dCx4cmVmOnJ9PWU7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uU1RSSUtFT1VUO2lmKHRoaXMuZGF0YS5xdWFkUG9pbnRzPWdldFF1YWRQb2ludHModCxudWxsKSl7aWYoIXRoaXMuYXBwZWFyYW5jZSl7Y29uc3QgZT1nZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsWzAsMCwwXSksYT10LmdldCgiQ0EiKTt0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7eHJlZjpyLGV4dHJhOiJbXSAwIGQgMSB3IixzdHJva2VDb2xvcjplLHN0cm9rZUFscGhhOmEscG9pbnRzQ2FsbGJhY2s6KGUsdCk9PntlLnB1c2goKHRbMF0rdFs0XSkvMisiICIrKHRbMV0rdFs1XSkvMisiIG0iLCh0WzJdK3RbNl0pLzIrIiAiKyh0WzNdK3RbN10pLzIrIiBsIiwiUyIpO3JldHVyblt0WzBdLHRbN10sdFsyXSx0WzNdXX19KX19ZWxzZSB0aGlzLmRhdGEucG9wdXBSZWY9bnVsbH1nZXQgb3ZlcmxheXNUZXh0Q29udGVudCgpe3JldHVybiEwfX1jbGFzcyBTdGFtcEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9ueyN2ZT1udWxsO2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO3RoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZT1NLlNUQU1QO3RoaXMuZGF0YS5oYXNPd25DYW52YXM9dGhpcy5kYXRhLm5vUm90YXRlO3RoaXMuZGF0YS5pc0VkaXRhYmxlPSF0aGlzLmRhdGEubm9IVE1MO3RoaXMuZGF0YS5ub0hUTUw9ITF9bXVzdEJlVmlld2VkV2hlbkVkaXRpbmcoZSx0PW51bGwpe2lmKGUpe2lmKCF0aGlzLmRhdGEuaXNFZGl0YWJsZSlyZXR1cm4hMDt0aGlzLiN2ZT8/PXRoaXMuZGF0YS5oYXNPd25DYW52YXM7dGhpcy5kYXRhLmhhc093bkNhbnZhcz0hMDtyZXR1cm4hMH1pZihudWxsIT09dGhpcy4jdmUpe3RoaXMuZGF0YS5oYXNPd25DYW52YXM9dGhpcy4jdmU7dGhpcy4jdmU9bnVsbH1yZXR1cm4hdD8uaGFzKHRoaXMuZGF0YS5pZCl9c3RhdGljIGFzeW5jIGNyZWF0ZUltYWdlKGUsdCl7Y29uc3R7d2lkdGg6cixoZWlnaHQ6YX09ZSxuPW5ldyBPZmZzY3JlZW5DYW52YXMocixhKSxpPW4uZ2V0Q29udGV4dCgiMmQiLHthbHBoYTohMH0pO2kuZHJhd0ltYWdlKGUsMCwwKTtjb25zdCBzPWkuZ2V0SW1hZ2VEYXRhKDAsMCxyLGEpLmRhdGEsbz1uZXcgVWludDMyQXJyYXkocy5idWZmZXIpLGM9by5zb21lKEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuP2U9PmU+Pj4yNCE9MjU1OmU9PiEhKDI1NSZ+ZSkpO2lmKGMpe2kuZmlsbFN0eWxlPSJ3aGl0ZSI7aS5maWxsUmVjdCgwLDAscixhKTtpLmRyYXdJbWFnZShlLDAsMCl9Y29uc3QgbD1uLmNvbnZlcnRUb0Jsb2Ioe3R5cGU6ImltYWdlL2pwZWciLHF1YWxpdHk6MX0pLnRoZW4oZT0+ZS5hcnJheUJ1ZmZlcigpKSxoPU5hbWUuZ2V0KCJYT2JqZWN0IiksdT1OYW1lLmdldCgiSW1hZ2UiKSxkPW5ldyBEaWN0KHQpO2Quc2V0KCJUeXBlIixoKTtkLnNldCgiU3VidHlwZSIsdSk7ZC5zZXQoIkJpdHNQZXJDb21wb25lbnQiLDgpO2Quc2V0SWZOYW1lKCJDb2xvclNwYWNlIiwiRGV2aWNlUkdCIik7ZC5zZXRJZk5hbWUoIkZpbHRlciIsIkRDVERlY29kZSIpO2Quc2V0KCJCQm94IixbMCwwLHIsYV0pO2Quc2V0KCJXaWR0aCIscik7ZC5zZXQoIkhlaWdodCIsYSk7bGV0IGY9bnVsbDtpZihjKXtjb25zdCBlPW5ldyBVaW50OEFycmF5KG8ubGVuZ3RoKTtpZihGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbilmb3IobGV0IHQ9MCxyPW8ubGVuZ3RoO3Q8cjt0KyspZVt0XT1vW3RdPj4+MjQ7ZWxzZSBmb3IobGV0IHQ9MCxyPW8ubGVuZ3RoO3Q8cjt0KyspZVt0XT0yNTUmb1t0XTtjb25zdCBuPW5ldyBEaWN0KHQpO24uc2V0KCJUeXBlIixoKTtuLnNldCgiU3VidHlwZSIsdSk7bi5zZXQoIkJpdHNQZXJDb21wb25lbnQiLDgpO24uc2V0SWZOYW1lKCJDb2xvclNwYWNlIiwiRGV2aWNlR3JheSIpO24uc2V0KCJXaWR0aCIscik7bi5zZXQoIkhlaWdodCIsYSk7Zj1uZXcgU3RyZWFtKGUsMCwwLG4pfXJldHVybntpbWFnZVN0cmVhbTpuZXcgU3RyZWFtKGF3YWl0IGwsMCwwLGQpLHNtYXNrU3RyZWFtOmYsd2lkdGg6cixoZWlnaHQ6YX19c3RhdGljIGNyZWF0ZU5ld0RpY3QoZSx0LHthcFJlZjpyLGFwOmF9KXtjb25zdHtkYXRlOm4sb2xkQW5ub3RhdGlvbjppLHJlY3Q6cyxyb3RhdGlvbjpvLHVzZXI6Y309ZSxsPWl8fG5ldyBEaWN0KHQpO2wuc2V0SWZOb3RFeGlzdHMoIlR5cGUiLE5hbWUuZ2V0KCJBbm5vdCIpKTtsLnNldElmTm90RXhpc3RzKCJTdWJ0eXBlIixOYW1lLmdldCgiU3RhbXAiKSk7bC5zZXQoaT8iTSI6IkNyZWF0aW9uRGF0ZSIsYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKG4pfWApO2wuc2V0SWZBcnJheSgiUmVjdCIscyk7bC5zZXRJZk5vdEV4aXN0cygiRiIsNCk7bC5zZXRJZk5vdEV4aXN0cygiQm9yZGVyIixbMCwwLDBdKTtsLnNldElmTnVtYmVyKCJSb3RhdGUiLG8pO2wuc2V0SWZEZWZpbmVkKCJUIixzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGMpKTtpZihyfHxhKXtjb25zdCBlPW5ldyBEaWN0KHQpO2wuc2V0KCJBUCIsZSk7ZS5zZXQoIk4iLHJ8fGEpfXJldHVybiBsfXN0YXRpYyBhc3luYyNGZShlLHQpe2NvbnN0e2FyZUNvbnRvdXJzOnIsY29sb3I6YSxyZWN0Om4sbGluZXM6aSx0aGlja25lc3M6c309ZTtpZighYSlyZXR1cm4gbnVsbDtjb25zdCBvPVtgJHtzfSB3IDEgSiAxIGpgLGAke2dldFBkZkNvbG9yKGEscil9YF07Zm9yKGNvbnN0IGUgb2YgaSl7by5wdXNoKGAke251bWJlclRvU3RyaW5nKGVbNF0pfSAke251bWJlclRvU3RyaW5nKGVbNV0pfSBtYCk7Zm9yKGxldCB0PTYscj1lLmxlbmd0aDt0PHI7dCs9NilpZihpc05hTihlW3RdKSlvLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcoZVt0KzRdKX0gJHtudW1iZXJUb1N0cmluZyhlW3QrNV0pfSBsYCk7ZWxzZXtjb25zdFtyLGEsbixpLHMsY109ZS5zbGljZSh0LHQrNik7by5wdXNoKFtyLGEsbixpLHMsY10ubWFwKG51bWJlclRvU3RyaW5nKS5qb2luKCIgIikrIiBjIil9Nj09PWUubGVuZ3RoJiZvLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcoZVs0XSl9ICR7bnVtYmVyVG9TdHJpbmcoZVs1XSl9IGxgKX1vLnB1c2gocj8iRiI6IlMiKTtjb25zdCBjPW8uam9pbigiXG4iKSxsPW5ldyBEaWN0KHQpO2wuc2V0KCJGb3JtVHlwZSIsMSk7bC5zZXRJZk5hbWUoIlN1YnR5cGUiLCJGb3JtIik7bC5zZXRJZk5hbWUoIlR5cGUiLCJYT2JqZWN0Iik7bC5zZXQoIkJCb3giLG4pO2wuc2V0KCJMZW5ndGgiLGMubGVuZ3RoKTtjb25zdCBoPW5ldyBTdHJpbmdTdHJlYW0oYyk7aC5kaWN0PWw7cmV0dXJuIGh9c3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oZSx0LHIpe2lmKGUub2xkQW5ub3RhdGlvbilyZXR1cm4gbnVsbDtpZihlLmlzU2lnbmF0dXJlKXJldHVybiB0aGlzLiNGZShlLHQpO2NvbnN0e3JvdGF0aW9uOmF9PWUse2ltYWdlUmVmOm4sd2lkdGg6aSxoZWlnaHQ6c309ci5pbWFnZSxvPW5ldyBEaWN0KHQpLGM9bmV3IERpY3QodCk7by5zZXQoIlhPYmplY3QiLGMpO2Muc2V0KCJJbTAiLG4pO2NvbnN0IGw9YHEgJHtpfSAwIDAgJHtzfSAwIDAgY20gL0ltMCBEbyBRYCxoPW5ldyBEaWN0KHQpO2guc2V0KCJGb3JtVHlwZSIsMSk7aC5zZXRJZk5hbWUoIlN1YnR5cGUiLCJGb3JtIik7aC5zZXRJZk5hbWUoIlR5cGUiLCJYT2JqZWN0Iik7aC5zZXQoIkJCb3giLFswLDAsaSxzXSk7aC5zZXQoIlJlc291cmNlcyIsbyk7aWYoYSl7Y29uc3QgZT1nZXRSb3RhdGlvbk1hdHJpeChhLGkscyk7aC5zZXQoIk1hdHJpeCIsZSl9Y29uc3QgdT1uZXcgU3RyaW5nU3RyZWFtKGwpO3UuZGljdD1oO3JldHVybiB1fX1jbGFzcyBGaWxlQXR0YWNobWVudEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9ue2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpO2NvbnN0e2RpY3Q6dCx4cmVmOnJ9PWUsYT1uZXcgRmlsZVNwZWModC5nZXQoIkZTIikscik7dGhpcy5kYXRhLmFubm90YXRpb25UeXBlPU0uRklMRUFUVEFDSE1FTlQ7dGhpcy5kYXRhLmhhc093bkNhbnZhcz10aGlzLmRhdGEubm9Sb3RhdGU7dGhpcy5kYXRhLm5vSFRNTD0hMTt0aGlzLmRhdGEuZmlsZT1hLnNlcmlhbGl6YWJsZTtjb25zdCBuPXQuZ2V0KCJOYW1lIik7dGhpcy5kYXRhLm5hbWU9biBpbnN0YW5jZW9mIE5hbWU/c3RyaW5nVG9QREZTdHJpbmcobi5uYW1lKToiUHVzaFBpbiI7Y29uc3QgaT10LmdldCgiY2EiKTt0aGlzLmRhdGEuZmlsbEFscGhhPSJudW1iZXIiPT10eXBlb2YgaSYmaT49MCYmaTw9MT9pOm51bGx9fWNvbnN0IHJjPXtnZXQgcigpe3JldHVybiBzaGFkb3codGhpcywiciIsbmV3IFVpbnQ4QXJyYXkoWzcsMTIsMTcsMjIsNywxMiwxNywyMiw3LDEyLDE3LDIyLDcsMTIsMTcsMjIsNSw5LDE0LDIwLDUsOSwxNCwyMCw1LDksMTQsMjAsNSw5LDE0LDIwLDQsMTEsMTYsMjMsNCwxMSwxNiwyMyw0LDExLDE2LDIzLDQsMTEsMTYsMjMsNiwxMCwxNSwyMSw2LDEwLDE1LDIxLDYsMTAsMTUsMjEsNiwxMCwxNSwyMV0pKX0sZ2V0IGsoKXtyZXR1cm4gc2hhZG93KHRoaXMsImsiLG5ldyBJbnQzMkFycmF5KFstNjgwODc2OTM2LC0zODk1NjQ1ODYsNjA2MTA1ODE5LC0xMDQ0NTI1MzMwLC0xNzY0MTg4OTcsMTIwMDA4MDQyNiwtMTQ3MzIzMTM0MSwtNDU3MDU5ODMsMTc3MDAzNTQxNiwtMTk1ODQxNDQxNywtNDIwNjMsLTE5OTA0MDQxNjIsMTgwNDYwMzY4MiwtNDAzNDExMDEsLTE1MDIwMDIyOTAsMTIzNjUzNTMyOSwtMTY1Nzk2NTEwLC0xMDY5NTAxNjMyLDY0MzcxNzcxMywtMzczODk3MzAyLC03MDE1NTg2OTEsMzgwMTYwODMsLTY2MDQ3ODMzNSwtNDA1NTM3ODQ4LDU2ODQ0NjQzOCwtMTAxOTgwMzY5MCwtMTg3MzYzOTYxLDExNjM1MzE1MDEsLTE0NDQ2ODE0NjcsLTUxNDAzNzg0LDE3MzUzMjg0NzMsLTE5MjY2MDc3MzQsLTM3ODU1OCwtMjAyMjU3NDQ2MywxODM5MDMwNTYyLC0zNTMwOTU1NiwtMTUzMDk5MjA2MCwxMjcyODkzMzUzLC0xNTU0OTc2MzIsLTEwOTQ3MzA2NDAsNjgxMjc5MTc0LC0zNTg1MzcyMjIsLTcyMjUyMTk3OSw3NjAyOTE4OSwtNjQwMzY0NDg3LC00MjE4MTU4MzUsNTMwNzQyNTIwLC05OTUzMzg2NTEsLTE5ODYzMDg0NCwxMTI2ODkxNDE1LC0xNDE2MzU0OTA1LC01NzQzNDA1NSwxNzAwNDg1NTcxLC0xODk0OTg2NjA2LC0xMDUxNTIzLC0yMDU0OTIyNzk5LDE4NzMzMTMzNTksLTMwNjExNzQ0LC0xNTYwMTk4MzgwLDEzMDkxNTE2NDksLTE0NTUyMzA3MCwtMTEyMDIxMDM3OSw3MTg3ODcyNTksLTM0MzQ4NTU1MV0pKX19O2Z1bmN0aW9uIGNhbGN1bGF0ZU1ENShlLHQscil7bGV0IGE9MTczMjU4NDE5MyxuPS0yNzE3MzM4NzksaT0tMTczMjU4NDE5NCxzPTI3MTczMzg3ODtjb25zdCBvPXIrNzImLTY0LGM9bmV3IFVpbnQ4QXJyYXkobyk7bGV0IGwsaDtmb3IobD0wO2w8cjsrK2wpY1tsXT1lW3QrK107Y1tsKytdPTEyODtjb25zdCB1PW8tODtsPHUmJihsPXUpO2NbbCsrXT1yPDwzJjI1NTtjW2wrK109cj4+NSYyNTU7Y1tsKytdPXI+PjEzJjI1NTtjW2wrK109cj4+MjEmMjU1O2NbbCsrXT1yPj4+MjkmMjU1O2wrPTM7Y29uc3QgZD1uZXcgSW50MzJBcnJheSgxNikse2s6ZixyOmd9PXJjO2ZvcihsPTA7bDxvOyl7Zm9yKGg9MDtoPDE2OysraCxsKz00KWRbaF09Y1tsXXxjW2wrMV08PDh8Y1tsKzJdPDwxNnxjW2wrM108PDI0O2xldCBlLHQscj1hLG89bix1PWkscD1zO2ZvcihoPTA7aDw2NDsrK2gpe2lmKGg8MTYpe2U9byZ1fH5vJnA7dD1ofWVsc2UgaWYoaDwzMil7ZT1wJm98fnAmdTt0PTUqaCsxJjE1fWVsc2UgaWYoaDw0OCl7ZT1vXnVecDt0PTMqaCs1JjE1fWVsc2V7ZT11XihvfH5wKTt0PTcqaCYxNX1jb25zdCBhPXAsbj1yK2UrZltoXStkW3RdfDAsaT1nW2hdO3A9dTt1PW87bz1vKyhuPDxpfG4+Pj4zMi1pKXwwO3I9YX1hPWErcnwwO249bitvfDA7aT1pK3V8MDtzPXMrcHwwfXJldHVybiBuZXcgVWludDhBcnJheShbMjU1JmEsYT4+OCYyNTUsYT4+MTYmMjU1LGE+Pj4yNCYyNTUsMjU1Jm4sbj4+OCYyNTUsbj4+MTYmMjU1LG4+Pj4yNCYyNTUsMjU1JmksaT4+OCYyNTUsaT4+MTYmMjU1LGk+Pj4yNCYyNTUsMjU1JnMscz4+OCYyNTUscz4+MTYmMjU1LHM+Pj4yNCYyNTVdKX1mdW5jdGlvbiBkZWNvZGVTdHJpbmcoZSl7dHJ5e3JldHVybiBzdHJpbmdUb1VURjhTdHJpbmcoZSl9Y2F0Y2godCl7d2FybihgVVRGLTggZGVjb2RpbmcgZmFpbGVkOiAiJHt0fSIuYCk7cmV0dXJuIGV9fWNsYXNzIERhdGFzZXRYTUxQYXJzZXIgZXh0ZW5kcyBTaW1wbGVYTUxQYXJzZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7dGhpcy5ub2RlPW51bGx9b25FbmRFbGVtZW50KGUpe2NvbnN0IHQ9c3VwZXIub25FbmRFbGVtZW50KGUpO2lmKHQmJiJ4ZmE6ZGF0YXNldHMiPT09ZSl7dGhpcy5ub2RlPXQ7dGhyb3cgbmV3IEVycm9yKCJBYm9ydGluZyBEYXRhc2V0WE1MUGFyc2VyLiIpfX19Y2xhc3MgRGF0YXNldFJlYWRlcntjb25zdHJ1Y3RvcihlKXtpZihlLmRhdGFzZXRzKXRoaXMubm9kZT1uZXcgU2ltcGxlWE1MUGFyc2VyKHtoYXNBdHRyaWJ1dGVzOiEwfSkucGFyc2VGcm9tU3RyaW5nKGUuZGF0YXNldHMpLmRvY3VtZW50RWxlbWVudDtlbHNle2NvbnN0IHQ9bmV3IERhdGFzZXRYTUxQYXJzZXIoe2hhc0F0dHJpYnV0ZXM6ITB9KTt0cnl7dC5wYXJzZUZyb21TdHJpbmcoZVsieGRwOnhkcCJdKX1jYXRjaHt9dGhpcy5ub2RlPXQubm9kZX19Z2V0VmFsdWUoZSl7aWYoIXRoaXMubm9kZXx8IWUpcmV0dXJuIiI7Y29uc3QgdD10aGlzLm5vZGUuc2VhcmNoTm9kZShwYXJzZVhGQVBhdGgoZSksMCk7aWYoIXQpcmV0dXJuIiI7Y29uc3Qgcj10LmZpcnN0Q2hpbGQ7cmV0dXJuInZhbHVlIj09PXI/Lm5vZGVOYW1lP3QuY2hpbGRyZW4ubWFwKGU9PmRlY29kZVN0cmluZyhlLnRleHRDb250ZW50KSk6ZGVjb2RlU3RyaW5nKHQudGV4dENvbnRlbnQpfX1jbGFzcyBTaW5nbGVJbnRlcnNlY3RvcnsjSWU7I1RlPTEvMDsjT2U9MS8wOyNNZT0tMS8wOyNEZT0tMS8wOyNCZT1udWxsOyNSZT1bXTsjRWU9W107I05lPS0xOyNQZT0hMTtjb25zdHJ1Y3RvcihlKXt0aGlzLiNJZT1lO2NvbnN0IHQ9ZS5kYXRhLnF1YWRQb2ludHM7aWYodCl7Zm9yKGxldCBlPTAscj10Lmxlbmd0aDtlPHI7ZSs9OCl7dGhpcy4jVGU9TWF0aC5taW4odGhpcy4jVGUsdFtlXSk7dGhpcy4jTWU9TWF0aC5tYXgodGhpcy4jTWUsdFtlKzJdKTt0aGlzLiNPZT1NYXRoLm1pbih0aGlzLiNPZSx0W2UrNV0pO3RoaXMuI0RlPU1hdGgubWF4KHRoaXMuI0RlLHRbZSsxXSl9dC5sZW5ndGg+OCYmKHRoaXMuI0JlPXQpfWVsc2VbdGhpcy4jVGUsdGhpcy4jT2UsdGhpcy4jTWUsdGhpcy4jRGVdPWUuZGF0YS5yZWN0fW92ZXJsYXBzKGUpe3JldHVybiEodGhpcy4jVGU+PWUuI01lfHx0aGlzLiNNZTw9ZS4jVGV8fHRoaXMuI09lPj1lLiNEZXx8dGhpcy4jRGU8PWUuI09lKX0jX2UoZSx0KXtpZih0aGlzLiNUZT49ZXx8dGhpcy4jTWU8PWV8fHRoaXMuI09lPj10fHx0aGlzLiNEZTw9dClyZXR1cm4hMTtjb25zdCByPXRoaXMuI0JlO2lmKCFyKXJldHVybiEwO2lmKHRoaXMuI05lPj0wKXtjb25zdCBhPXRoaXMuI05lO2lmKCEoclthXT49ZXx8clthKzJdPD1lfHxyW2ErNV0+PXR8fHJbYSsxXTw9dCkpcmV0dXJuITA7dGhpcy4jTmU9LTF9Zm9yKGxldCBhPTAsbj1yLmxlbmd0aDthPG47YSs9OClpZighKHJbYV0+PWV8fHJbYSsyXTw9ZXx8clthKzVdPj10fHxyW2ErMV08PXQpKXt0aGlzLiNOZT1hO3JldHVybiEwfXJldHVybiExfWFkZEdseXBoKGUsdCxyKXtpZighdGhpcy4jX2UoZSx0KSl7dGhpcy5kaXNhYmxlRXh0cmFDaGFycygpO3JldHVybiExfWlmKHRoaXMuI0VlLmxlbmd0aD4wKXt0aGlzLiNSZS5wdXNoKHRoaXMuI0VlLmpvaW4oIiIpKTt0aGlzLiNFZS5sZW5ndGg9MH10aGlzLiNSZS5wdXNoKHIpO3RoaXMuI1BlPSEwO3JldHVybiEwfWFkZEV4dHJhQ2hhcihlKXt0aGlzLiNQZSYmdGhpcy4jRWUucHVzaChlKX1kaXNhYmxlRXh0cmFDaGFycygpe2lmKHRoaXMuI1BlKXt0aGlzLiNQZT0hMTt0aGlzLiNFZS5sZW5ndGg9MH19c2V0VGV4dCgpe3RoaXMuI0llLmRhdGEub3ZlcmxhaWRUZXh0PXRoaXMuI1JlLmpvaW4oIiIpfX1jbGFzcyBJbnRlcnNlY3RvcnsjTGU9bmV3IE1hcDtjb25zdHJ1Y3RvcihlKXtmb3IoY29uc3QgdCBvZiBlKXtpZighdC5kYXRhLnF1YWRQb2ludHMmJiF0LmRhdGEucmVjdCljb250aW51ZTtjb25zdCBlPW5ldyBTaW5nbGVJbnRlcnNlY3Rvcih0KTtmb3IoY29uc3RbdCxyXW9mIHRoaXMuI0xlKXQub3ZlcmxhcHMoZSkmJihyP3IuYWRkKGUpOnRoaXMuI0xlLnNldCh0LG5ldyBTZXQoW2VdKSkpO3RoaXMuI0xlLnNldChlLG51bGwpfX1hZGRHbHlwaChlLHQscixhKXtjb25zdCBuPWVbNF0rdC8yLGk9ZVs1XStyLzI7bGV0IHM7Zm9yKGNvbnN0W2UsdF1vZiB0aGlzLiNMZSlzP3MuaGFzKGUpP2UuYWRkR2x5cGgobixpLGEpOmUuZGlzYWJsZUV4dHJhQ2hhcnMoKTplLmFkZEdseXBoKG4saSxhKSYmKHM9dCl9YWRkRXh0cmFDaGFyKGUpe2Zvcihjb25zdCB0IG9mIHRoaXMuI0xlLmtleXMoKSl0LmFkZEV4dHJhQ2hhcihlKX1zZXRUZXh0KCl7Zm9yKGNvbnN0IGUgb2YgdGhpcy4jTGUua2V5cygpKWUuc2V0VGV4dCgpfX1jbGFzcyBXb3JkNjR7Y29uc3RydWN0b3IoZSx0KXt0aGlzLmhpZ2g9MHxlO3RoaXMubG93PTB8dH1hbmQoZSl7dGhpcy5oaWdoJj1lLmhpZ2g7dGhpcy5sb3cmPWUubG93fXhvcihlKXt0aGlzLmhpZ2hePWUuaGlnaDt0aGlzLmxvd149ZS5sb3d9c2hpZnRSaWdodChlKXtpZihlPj0zMil7dGhpcy5sb3c9dGhpcy5oaWdoPj4+ZS0zMnwwO3RoaXMuaGlnaD0wfWVsc2V7dGhpcy5sb3c9dGhpcy5sb3c+Pj5lfHRoaXMuaGlnaDw8MzItZTt0aGlzLmhpZ2g9dGhpcy5oaWdoPj4+ZXwwfX1yb3RhdGVSaWdodChlKXtsZXQgdCxyO2lmKDMyJmUpe3I9dGhpcy5sb3c7dD10aGlzLmhpZ2h9ZWxzZXt0PXRoaXMubG93O3I9dGhpcy5oaWdofWUmPTMxO3RoaXMubG93PXQ+Pj5lfHI8PDMyLWU7dGhpcy5oaWdoPXI+Pj5lfHQ8PDMyLWV9bm90KCl7dGhpcy5oaWdoPX50aGlzLmhpZ2g7dGhpcy5sb3c9fnRoaXMubG93fWFkZChlKXtjb25zdCB0PSh0aGlzLmxvdz4+PjApKyhlLmxvdz4+PjApO2xldCByPSh0aGlzLmhpZ2g+Pj4wKSsoZS5oaWdoPj4+MCk7dD40Mjk0OTY3Mjk1JiYocis9MSk7dGhpcy5sb3c9MHx0O3RoaXMuaGlnaD0wfHJ9Y29weVRvKGUsdCl7ZVt0XT10aGlzLmhpZ2g+Pj4yNCYyNTU7ZVt0KzFdPXRoaXMuaGlnaD4+MTYmMjU1O2VbdCsyXT10aGlzLmhpZ2g+PjgmMjU1O2VbdCszXT0yNTUmdGhpcy5oaWdoO2VbdCs0XT10aGlzLmxvdz4+PjI0JjI1NTtlW3QrNV09dGhpcy5sb3c+PjE2JjI1NTtlW3QrNl09dGhpcy5sb3c+PjgmMjU1O2VbdCs3XT0yNTUmdGhpcy5sb3d9YXNzaWduKGUpe3RoaXMuaGlnaD1lLmhpZ2g7dGhpcy5sb3c9ZS5sb3d9fWNvbnN0IGFjPXtnZXQgaygpe3JldHVybiBzaGFkb3codGhpcywiayIsW25ldyBXb3JkNjQoMTExNjM1MjQwOCwzNjA5NzY3NDU4KSxuZXcgV29yZDY0KDE4OTk0NDc0NDEsNjAyODkxNzI1KSxuZXcgV29yZDY0KDMwNDkzMjM0NzEsMzk2NDQ4NDM5OSksbmV3IFdvcmQ2NCgzOTIxMDA5NTczLDIxNzMyOTU1NDgpLG5ldyBXb3JkNjQoOTYxOTg3MTYzLDQwODE2Mjg0NzIpLG5ldyBXb3JkNjQoMTUwODk3MDk5MywzMDUzODM0MjY1KSxuZXcgV29yZDY0KDI0NTM2MzU3NDgsMjkzNzY3MTU3OSksbmV3IFdvcmQ2NCgyODcwNzYzMjIxLDM2NjQ2MDk1NjApLG5ldyBXb3JkNjQoMzYyNDM4MTA4MCwyNzM0ODgzMzk0KSxuZXcgV29yZDY0KDMxMDU5ODQwMSwxMTY0OTk2NTQyKSxuZXcgV29yZDY0KDYwNzIyNTI3OCwxMzIzNjEwNzY0KSxuZXcgV29yZDY0KDE0MjY4ODE5ODcsMzU5MDMwNDk5NCksbmV3IFdvcmQ2NCgxOTI1MDc4Mzg4LDQwNjgxODIzODMpLG5ldyBXb3JkNjQoMjE2MjA3ODIwNiw5OTEzMzYxMTMpLG5ldyBXb3JkNjQoMjYxNDg4ODEwMyw2MzM4MDMzMTcpLG5ldyBXb3JkNjQoMzI0ODIyMjU4MCwzNDc5Nzc0ODY4KSxuZXcgV29yZDY0KDM4MzUzOTA0MDEsMjY2NjYxMzQ1OCksbmV3IFdvcmQ2NCg0MDIyMjI0Nzc0LDk0NDcxMTEzOSksbmV3IFdvcmQ2NCgyNjQzNDcwNzgsMjM0MTI2Mjc3MyksbmV3IFdvcmQ2NCg2MDQ4MDc2MjgsMjAwNzgwMDkzMyksbmV3IFdvcmQ2NCg3NzAyNTU5ODMsMTQ5NTk5MDkwMSksbmV3IFdvcmQ2NCgxMjQ5MTUwMTIyLDE4NTY0MzEyMzUpLG5ldyBXb3JkNjQoMTU1NTA4MTY5MiwzMTc1MjE4MTMyKSxuZXcgV29yZDY0KDE5OTYwNjQ5ODYsMjE5ODk1MDgzNyksbmV3IFdvcmQ2NCgyNTU0MjIwODgyLDM5OTk3MTkzMzkpLG5ldyBXb3JkNjQoMjgyMTgzNDM0OSw3NjY3ODQwMTYpLG5ldyBXb3JkNjQoMjk1Mjk5NjgwOCwyNTY2NTk0ODc5KSxuZXcgV29yZDY0KDMyMTAzMTM2NzEsMzIwMzMzNzk1NiksbmV3IFdvcmQ2NCgzMzM2NTcxODkxLDEwMzQ0NTcwMjYpLG5ldyBXb3JkNjQoMzU4NDUyODcxMSwyNDY2OTQ4OTAxKSxuZXcgV29yZDY0KDExMzkyNjk5MywzNzU4MzI2MzgzKSxuZXcgV29yZDY0KDMzODI0MTg5NSwxNjg3MTc5MzYpLG5ldyBXb3JkNjQoNjY2MzA3MjA1LDExODgxNzk5NjQpLG5ldyBXb3JkNjQoNzczNTI5OTEyLDE1NDYwNDU3MzQpLG5ldyBXb3JkNjQoMTI5NDc1NzM3MiwxNTIyODA1NDg1KSxuZXcgV29yZDY0KDEzOTYxODIyOTEsMjY0MzgzMzgyMyksbmV3IFdvcmQ2NCgxNjk1MTgzNzAwLDIzNDM1MjczOTApLG5ldyBXb3JkNjQoMTk4NjY2MTA1MSwxMDE0NDc3NDgwKSxuZXcgV29yZDY0KDIxNzcwMjYzNTAsMTIwNjc1OTE0MiksbmV3IFdvcmQ2NCgyNDU2OTU2MDM3LDM0NDA3NzYyNyksbmV3IFdvcmQ2NCgyNzMwNDg1OTIxLDEyOTA4NjM0NjApLG5ldyBXb3JkNjQoMjgyMDMwMjQxMSwzMTU4NDU0MjczKSxuZXcgV29yZDY0KDMyNTk3MzA4MDAsMzUwNTk1MjY1NyksbmV3IFdvcmQ2NCgzMzQ1NzY0NzcxLDEwNjIxNzAwOCksbmV3IFdvcmQ2NCgzNTE2MDY1ODE3LDM2MDYwMDgzNDQpLG5ldyBXb3JkNjQoMzYwMDM1MjgwNCwxNDMyNzI1Nzc2KSxuZXcgV29yZDY0KDQwOTQ1NzE5MDksMTQ2NzAzMTU5NCksbmV3IFdvcmQ2NCgyNzU0MjMzNDQsODUxMTY5NzIwKSxuZXcgV29yZDY0KDQzMDIyNzczNCwzMTAwODIzNzUyKSxuZXcgV29yZDY0KDUwNjk0ODYxNiwxMzYzMjU4MTk1KSxuZXcgV29yZDY0KDY1OTA2MDU1NiwzNzUwNjg1NTkzKSxuZXcgV29yZDY0KDg4Mzk5Nzg3NywzNzg1MDUwMjgwKSxuZXcgV29yZDY0KDk1ODEzOTU3MSwzMzE4MzA3NDI3KSxuZXcgV29yZDY0KDEzMjI4MjIyMTgsMzgxMjcyMzQwMyksbmV3IFdvcmQ2NCgxNTM3MDAyMDYzLDIwMDMwMzQ5OTUpLG5ldyBXb3JkNjQoMTc0Nzg3Mzc3OSwzNjAyMDM2ODk5KSxuZXcgV29yZDY0KDE5NTU1NjIyMjIsMTU3NTk5MDAxMiksbmV3IFdvcmQ2NCgyMDI0MTA0ODE1LDExMjU1OTI5MjgpLG5ldyBXb3JkNjQoMjIyNzczMDQ1MiwyNzE2OTA0MzA2KSxuZXcgV29yZDY0KDIzNjE4NTI0MjQsNDQyNzc2MDQ0KSxuZXcgV29yZDY0KDI0Mjg0MzY0NzQsNTkzNjk4MzQ0KSxuZXcgV29yZDY0KDI3NTY3MzQxODcsMzczMzExMDI0OSksbmV3IFdvcmQ2NCgzMjA0MDMxNDc5LDI5OTkzNTE1NzMpLG5ldyBXb3JkNjQoMzMyOTMyNTI5OCwzODE1OTIwNDI3KSxuZXcgV29yZDY0KDMzOTE1Njk2MTQsMzkyODM4MzkwMCksbmV3IFdvcmQ2NCgzNTE1MjY3MjcxLDU2NjI4MDcxMSksbmV3IFdvcmQ2NCgzOTQwMTg3NjA2LDM0NTQwNjk1MzQpLG5ldyBXb3JkNjQoNDExODYzMDI3MSw0MDAwMjM5OTkyKSxuZXcgV29yZDY0KDExNjQxODQ3NCwxOTE0MTM4NTU0KSxuZXcgV29yZDY0KDE3NDI5MjQyMSwyNzMxMDU1MjcwKSxuZXcgV29yZDY0KDI4OTM4MDM1NiwzMjAzOTkzMDA2KSxuZXcgV29yZDY0KDQ2MDM5MzI2OSwzMjA2MjAzMTUpLG5ldyBXb3JkNjQoNjg1NDcxNzMzLDU4NzQ5NjgzNiksbmV3IFdvcmQ2NCg4NTIxNDI5NzEsMTA4Njc5Mjg1MSksbmV3IFdvcmQ2NCgxMDE3MDM2Mjk4LDM2NTU0MzEwMCksbmV3IFdvcmQ2NCgxMTI2MDAwNTgwLDI2MTgyOTc2NzYpLG5ldyBXb3JkNjQoMTI4ODAzMzQ3MCwzNDA5ODU1MTU4KSxuZXcgV29yZDY0KDE1MDE1MDU5NDgsNDIzNDUwOTg2NiksbmV3IFdvcmQ2NCgxNjA3MTY3OTE1LDk4NzE2NzQ2OCksbmV3IFdvcmQ2NCgxODE2NDAyMzE2LDEyNDYxODk1OTEpXSl9fTtmdW5jdGlvbiBjaChlLHQscixhLG4pe2UuYXNzaWduKHQpO2UuYW5kKHIpO24uYXNzaWduKHQpO24ubm90KCk7bi5hbmQoYSk7ZS54b3Iobil9ZnVuY3Rpb24gbWFqKGUsdCxyLGEsbil7ZS5hc3NpZ24odCk7ZS5hbmQocik7bi5hc3NpZ24odCk7bi5hbmQoYSk7ZS54b3Iobik7bi5hc3NpZ24ocik7bi5hbmQoYSk7ZS54b3Iobil9ZnVuY3Rpb24gc2lnbWEoZSx0LHIpe2UuYXNzaWduKHQpO2Uucm90YXRlUmlnaHQoMjgpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoMzQpO2UueG9yKHIpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoMzkpO2UueG9yKHIpfWZ1bmN0aW9uIHNpZ21hUHJpbWUoZSx0LHIpe2UuYXNzaWduKHQpO2Uucm90YXRlUmlnaHQoMTQpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoMTgpO2UueG9yKHIpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoNDEpO2UueG9yKHIpfWZ1bmN0aW9uIGxpdHRsZVNpZ21hKGUsdCxyKXtlLmFzc2lnbih0KTtlLnJvdGF0ZVJpZ2h0KDEpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoOCk7ZS54b3Iocik7ci5hc3NpZ24odCk7ci5zaGlmdFJpZ2h0KDcpO2UueG9yKHIpfWZ1bmN0aW9uIGxpdHRsZVNpZ21hUHJpbWUoZSx0LHIpe2UuYXNzaWduKHQpO2Uucm90YXRlUmlnaHQoMTkpO3IuYXNzaWduKHQpO3Iucm90YXRlUmlnaHQoNjEpO2UueG9yKHIpO3IuYXNzaWduKHQpO3Iuc2hpZnRSaWdodCg2KTtlLnhvcihyKX1mdW5jdGlvbiBjYWxjdWxhdGVTSEE1MTIoZSx0LHIsYT0hMSl7bGV0IG4saSxzLG8sYyxsLGgsdTtpZihhKXtuPW5ldyBXb3JkNjQoMzQxODA3MDM2NSwzMjM4MzcxMDMyKTtpPW5ldyBXb3JkNjQoMTY1NDI3MDI1MCw5MTQxNTA2NjMpO3M9bmV3IFdvcmQ2NCgyNDM4NTI5MzcwLDgxMjcwMjk5OSk7bz1uZXcgV29yZDY0KDM1NTQ2MjM2MCw0MTQ0OTEyNjk3KTtjPW5ldyBXb3JkNjQoMTczMTQwNTQxNSw0MjkwNzc1ODU3KTtsPW5ldyBXb3JkNjQoMjM5NDE4MDIzMSwxNzUwNjAzMDI1KTtoPW5ldyBXb3JkNjQoMzY3NTAwODUyNSwxNjk0MDc2ODM5KTt1PW5ldyBXb3JkNjQoMTIwMzA2MjgxMywzMjA0MDc1NDI4KX1lbHNle249bmV3IFdvcmQ2NCgxNzc5MDMzNzAzLDQwODkyMzU3MjApO2k9bmV3IFdvcmQ2NCgzMTQ0MTM0Mjc3LDIyMjc4NzM1OTUpO3M9bmV3IFdvcmQ2NCgxMDEzOTA0MjQyLDQyNzExNzU3MjMpO289bmV3IFdvcmQ2NCgyNzczNDgwNzYyLDE1OTU3NTAxMjkpO2M9bmV3IFdvcmQ2NCgxMzU5ODkzMTE5LDI5MTc1NjUxMzcpO2w9bmV3IFdvcmQ2NCgyNjAwODIyOTI0LDcyNTUxMTE5OSk7aD1uZXcgV29yZDY0KDUyODczNDYzNSw0MjE1Mzg5NTQ3KTt1PW5ldyBXb3JkNjQoMTU0MTQ1OTIyNSwzMjcwMzMyMDkpfWNvbnN0IGQ9MTI4Kk1hdGguY2VpbCgocisxNykvMTI4KSxmPW5ldyBVaW50OEFycmF5KGQpO2xldCBnLHA7Zm9yKGc9MDtnPHI7KytnKWZbZ109ZVt0KytdO2ZbZysrXT0xMjg7Y29uc3QgbT1kLTE2O2c8bSYmKGc9bSk7Zys9MTE7ZltnKytdPXI+Pj4yOSYyNTU7ZltnKytdPXI+PjIxJjI1NTtmW2crK109cj4+MTMmMjU1O2ZbZysrXT1yPj41JjI1NTtmW2crK109cjw8MyYyNTU7Y29uc3QgYj1uZXcgQXJyYXkoODApO2ZvcihnPTA7Zzw4MDtnKyspYltnXT1uZXcgV29yZDY0KDAsMCk7Y29uc3R7azp5fT1hYztsZXQgdz1uZXcgV29yZDY0KDAsMCkseD1uZXcgV29yZDY0KDAsMCksUz1uZXcgV29yZDY0KDAsMCksaz1uZXcgV29yZDY0KDAsMCksQz1uZXcgV29yZDY0KDAsMCksdj1uZXcgV29yZDY0KDAsMCksVD1uZXcgV29yZDY0KDAsMCksTz1uZXcgV29yZDY0KDAsMCk7Y29uc3QgTT1uZXcgV29yZDY0KDAsMCksRD1uZXcgV29yZDY0KDAsMCksUj1uZXcgV29yZDY0KDAsMCksRT1uZXcgV29yZDY0KDAsMCk7bGV0IE4sXztmb3IoZz0wO2c8ZDspe2ZvcihwPTA7cDwxNjsrK3Ape2JbcF0uaGlnaD1mW2ddPDwyNHxmW2crMV08PDE2fGZbZysyXTw8OHxmW2crM107YltwXS5sb3c9ZltnKzRdPDwyNHxmW2crNV08PDE2fGZbZys2XTw8OHxmW2crN107Zys9OH1mb3IocD0xNjtwPDgwOysrcCl7Tj1iW3BdO2xpdHRsZVNpZ21hUHJpbWUoTixiW3AtMl0sRSk7Ti5hZGQoYltwLTddKTtsaXR0bGVTaWdtYShSLGJbcC0xNV0sRSk7Ti5hZGQoUik7Ti5hZGQoYltwLTE2XSl9dy5hc3NpZ24obik7eC5hc3NpZ24oaSk7Uy5hc3NpZ24ocyk7ay5hc3NpZ24obyk7Qy5hc3NpZ24oYyk7di5hc3NpZ24obCk7VC5hc3NpZ24oaCk7Ty5hc3NpZ24odSk7Zm9yKHA9MDtwPDgwOysrcCl7TS5hc3NpZ24oTyk7c2lnbWFQcmltZShSLEMsRSk7TS5hZGQoUik7Y2goUixDLHYsVCxFKTtNLmFkZChSKTtNLmFkZCh5W3BdKTtNLmFkZChiW3BdKTtzaWdtYShELHcsRSk7bWFqKFIsdyx4LFMsRSk7RC5hZGQoUik7Tj1PO089VDtUPXY7dj1DO2suYWRkKE0pO0M9aztrPVM7Uz14O3g9dztOLmFzc2lnbihNKTtOLmFkZChEKTt3PU59bi5hZGQodyk7aS5hZGQoeCk7cy5hZGQoUyk7by5hZGQoayk7Yy5hZGQoQyk7bC5hZGQodik7aC5hZGQoVCk7dS5hZGQoTyl9aWYoYSl7Xz1uZXcgVWludDhBcnJheSg0OCk7bi5jb3B5VG8oXywwKTtpLmNvcHlUbyhfLDgpO3MuY29weVRvKF8sMTYpO28uY29weVRvKF8sMjQpO2MuY29weVRvKF8sMzIpO2wuY29weVRvKF8sNDApfWVsc2V7Xz1uZXcgVWludDhBcnJheSg2NCk7bi5jb3B5VG8oXywwKTtpLmNvcHlUbyhfLDgpO3MuY29weVRvKF8sMTYpO28uY29weVRvKF8sMjQpO2MuY29weVRvKF8sMzIpO2wuY29weVRvKF8sNDApO2guY29weVRvKF8sNDgpO3UuY29weVRvKF8sNTYpfXJldHVybiBffWZ1bmN0aW9uIGNhbGN1bGF0ZVNIQTM4NChlLHQscil7cmV0dXJuIGNhbGN1bGF0ZVNIQTUxMihlLHQsciwhMCl9Y29uc3QgbmM9e2dldCBrKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJrIixbMTExNjM1MjQwOCwxODk5NDQ3NDQxLDMwNDkzMjM0NzEsMzkyMTAwOTU3Myw5NjE5ODcxNjMsMTUwODk3MDk5MywyNDUzNjM1NzQ4LDI4NzA3NjMyMjEsMzYyNDM4MTA4MCwzMTA1OTg0MDEsNjA3MjI1Mjc4LDE0MjY4ODE5ODcsMTkyNTA3ODM4OCwyMTYyMDc4MjA2LDI2MTQ4ODgxMDMsMzI0ODIyMjU4MCwzODM1MzkwNDAxLDQwMjIyMjQ3NzQsMjY0MzQ3MDc4LDYwNDgwNzYyOCw3NzAyNTU5ODMsMTI0OTE1MDEyMiwxNTU1MDgxNjkyLDE5OTYwNjQ5ODYsMjU1NDIyMDg4MiwyODIxODM0MzQ5LDI5NTI5OTY4MDgsMzIxMDMxMzY3MSwzMzM2NTcxODkxLDM1ODQ1Mjg3MTEsMTEzOTI2OTkzLDMzODI0MTg5NSw2NjYzMDcyMDUsNzczNTI5OTEyLDEyOTQ3NTczNzIsMTM5NjE4MjI5MSwxNjk1MTgzNzAwLDE5ODY2NjEwNTEsMjE3NzAyNjM1MCwyNDU2OTU2MDM3LDI3MzA0ODU5MjEsMjgyMDMwMjQxMSwzMjU5NzMwODAwLDMzNDU3NjQ3NzEsMzUxNjA2NTgxNywzNjAwMzUyODA0LDQwOTQ1NzE5MDksMjc1NDIzMzQ0LDQzMDIyNzczNCw1MDY5NDg2MTYsNjU5MDYwNTU2LDg4Mzk5Nzg3Nyw5NTgxMzk1NzEsMTMyMjgyMjIxOCwxNTM3MDAyMDYzLDE3NDc4NzM3NzksMTk1NTU2MjIyMiwyMDI0MTA0ODE1LDIyMjc3MzA0NTIsMjM2MTg1MjQyNCwyNDI4NDM2NDc0LDI3NTY3MzQxODcsMzIwNDAzMTQ3OSwzMzI5MzI1Mjk4XSl9fTtmdW5jdGlvbiByb3RyKGUsdCl7cmV0dXJuIGU+Pj50fGU8PDMyLXR9ZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9jaChlLHQscil7cmV0dXJuIGUmdF5+ZSZyfWZ1bmN0aW9uIGNhbGN1bGF0ZV9zaGEyNTZfbWFqKGUsdCxyKXtyZXR1cm4gZSZ0XmUmcl50JnJ9ZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9zaWdtYShlKXtyZXR1cm4gcm90cihlLDIpXnJvdHIoZSwxMylecm90cihlLDIyKX1mdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X3NpZ21hUHJpbWUoZSl7cmV0dXJuIHJvdHIoZSw2KV5yb3RyKGUsMTEpXnJvdHIoZSwyNSl9ZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYShlKXtyZXR1cm4gcm90cihlLDcpXnJvdHIoZSwxOCleZT4+PjN9ZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYVByaW1lKGUpe3JldHVybiByb3RyKGUsMTcpXnJvdHIoZSwxOSleZT4+PjEwfWZ1bmN0aW9uIGNhbGN1bGF0ZVNIQTI1NihlLHQscil7bGV0IGE9MTc3OTAzMzcwMyxuPTMxNDQxMzQyNzcsaT0xMDEzOTA0MjQyLHM9Mjc3MzQ4MDc2MixvPTEzNTk4OTMxMTksYz0yNjAwODIyOTI0LGw9NTI4NzM0NjM1LGg9MTU0MTQ1OTIyNTtjb25zdCB1PTY0Kk1hdGguY2VpbCgocis5KS82NCksZD1uZXcgVWludDhBcnJheSh1KTtsZXQgZixnO2ZvcihmPTA7ZjxyOysrZilkW2ZdPWVbdCsrXTtkW2YrK109MTI4O2NvbnN0IHA9dS04O2Y8cCYmKGY9cCk7Zis9MztkW2YrK109cj4+PjI5JjI1NTtkW2YrK109cj4+MjEmMjU1O2RbZisrXT1yPj4xMyYyNTU7ZFtmKytdPXI+PjUmMjU1O2RbZisrXT1yPDwzJjI1NTtjb25zdCBtPW5ldyBVaW50MzJBcnJheSg2NCkse2s6Yn09bmM7Zm9yKGY9MDtmPHU7KXtmb3IoZz0wO2c8MTY7KytnKXttW2ddPWRbZl08PDI0fGRbZisxXTw8MTZ8ZFtmKzJdPDw4fGRbZiszXTtmKz00fWZvcihnPTE2O2c8NjQ7KytnKW1bZ109Y2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYVByaW1lKG1bZy0yXSkrbVtnLTddK2NhbGN1bGF0ZV9zaGEyNTZfbGl0dGxlU2lnbWEobVtnLTE1XSkrbVtnLTE2XXwwO2xldCBlLHQscj1hLHU9bixwPWkseT1zLHc9byx4PWMsUz1sLGs9aDtmb3IoZz0wO2c8NjQ7KytnKXtlPWsrY2FsY3VsYXRlX3NoYTI1Nl9zaWdtYVByaW1lKHcpK2NhbGN1bGF0ZV9zaGEyNTZfY2godyx4LFMpK2JbZ10rbVtnXTt0PWNhbGN1bGF0ZV9zaGEyNTZfc2lnbWEocikrY2FsY3VsYXRlX3NoYTI1Nl9tYWoocix1LHApO2s9UztTPXg7eD13O3c9eStlfDA7eT1wO3A9dTt1PXI7cj1lK3R8MH1hPWErcnwwO249bit1fDA7aT1pK3B8MDtzPXMreXwwO289byt3fDA7Yz1jK3h8MDtsPWwrU3wwO2g9aCtrfDB9cmV0dXJuIG5ldyBVaW50OEFycmF5KFthPj4yNCYyNTUsYT4+MTYmMjU1LGE+PjgmMjU1LDI1NSZhLG4+PjI0JjI1NSxuPj4xNiYyNTUsbj4+OCYyNTUsMjU1Jm4saT4+MjQmMjU1LGk+PjE2JjI1NSxpPj44JjI1NSwyNTUmaSxzPj4yNCYyNTUscz4+MTYmMjU1LHM+PjgmMjU1LDI1NSZzLG8+PjI0JjI1NSxvPj4xNiYyNTUsbz4+OCYyNTUsMjU1Jm8sYz4+MjQmMjU1LGM+PjE2JjI1NSxjPj44JjI1NSwyNTUmYyxsPj4yNCYyNTUsbD4+MTYmMjU1LGw+PjgmMjU1LDI1NSZsLGg+PjI0JjI1NSxoPj4xNiYyNTUsaD4+OCYyNTUsMjU1JmhdKX1jbGFzcyBEZWNyeXB0U3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFte2NvbnN0cnVjdG9yKGUsdCxyKXtzdXBlcih0KTt0aGlzLnN0cj1lO3RoaXMuZGljdD1lLmRpY3Q7dGhpcy5kZWNyeXB0PXI7dGhpcy5uZXh0Q2h1bms9bnVsbDt0aGlzLmluaXRpYWxpemVkPSExfXJlYWRCbG9jaygpe2xldCBlO2lmKHRoaXMuaW5pdGlhbGl6ZWQpZT10aGlzLm5leHRDaHVuaztlbHNle2U9dGhpcy5zdHIuZ2V0Qnl0ZXMoNTEyKTt0aGlzLmluaXRpYWxpemVkPSEwfWlmKCFlPy5sZW5ndGgpe3RoaXMuZW9mPSEwO3JldHVybn10aGlzLm5leHRDaHVuaz10aGlzLnN0ci5nZXRCeXRlcyg1MTIpO2NvbnN0IHQ9dGhpcy5uZXh0Q2h1bms/Lmxlbmd0aD4wO2U9KDAsdGhpcy5kZWNyeXB0KShlLCF0KTtjb25zdCByPXRoaXMuYnVmZmVyTGVuZ3RoLGE9citlLmxlbmd0aDt0aGlzLmVuc3VyZUJ1ZmZlcihhKS5zZXQoZSxyKTt0aGlzLmJ1ZmZlckxlbmd0aD1hfX1jbGFzcyBBUkNGb3VyQ2lwaGVye2NvbnN0cnVjdG9yKGUpe3RoaXMuYT0wO3RoaXMuYj0wO2NvbnN0IHQ9bmV3IFVpbnQ4QXJyYXkoMjU2KSxyPWUubGVuZ3RoO2ZvcihsZXQgZT0wO2U8MjU2OysrZSl0W2VdPWU7Zm9yKGxldCBhPTAsbj0wO2E8MjU2OysrYSl7Y29uc3QgaT10W2FdO249bitpK2VbYSVyXSYyNTU7dFthXT10W25dO3Rbbl09aX10aGlzLnM9dH1lbmNyeXB0QmxvY2soZSl7bGV0IHQ9dGhpcy5hLHI9dGhpcy5iO2NvbnN0IGE9dGhpcy5zLG49ZS5sZW5ndGgsaT1uZXcgVWludDhBcnJheShuKTtmb3IobGV0IHM9MDtzPG47KytzKXt0PXQrMSYyNTU7Y29uc3Qgbj1hW3RdO3I9cituJjI1NTtjb25zdCBvPWFbcl07YVt0XT1vO2Fbcl09bjtpW3NdPWVbc11eYVtuK28mMjU1XX10aGlzLmE9dDt0aGlzLmI9cjtyZXR1cm4gaX1kZWNyeXB0QmxvY2soZSl7cmV0dXJuIHRoaXMuZW5jcnlwdEJsb2NrKGUpfWVuY3J5cHQoZSl7cmV0dXJuIHRoaXMuZW5jcnlwdEJsb2NrKGUpfX1jbGFzcyBOdWxsQ2lwaGVye2RlY3J5cHRCbG9jayhlKXtyZXR1cm4gZX1lbmNyeXB0KGUpe3JldHVybiBlfX1jbGFzcyBBRVNCYXNlQ2lwaGVye19zPW5ldyBVaW50OEFycmF5KFs5OSwxMjQsMTE5LDEyMywyNDIsMTA3LDExMSwxOTcsNDgsMSwxMDMsNDMsMjU0LDIxNSwxNzEsMTE4LDIwMiwxMzAsMjAxLDEyNSwyNTAsODksNzEsMjQwLDE3MywyMTIsMTYyLDE3NSwxNTYsMTY0LDExNCwxOTIsMTgzLDI1MywxNDcsMzgsNTQsNjMsMjQ3LDIwNCw1MiwxNjUsMjI5LDI0MSwxMTMsMjE2LDQ5LDIxLDQsMTk5LDM1LDE5NSwyNCwxNTAsNSwxNTQsNywxOCwxMjgsMjI2LDIzNSwzOSwxNzgsMTE3LDksMTMxLDQ0LDI2LDI3LDExMCw5MCwxNjAsODIsNTksMjE0LDE3OSw0MSwyMjcsNDcsMTMyLDgzLDIwOSwwLDIzNywzMiwyNTIsMTc3LDkxLDEwNiwyMDMsMTkwLDU3LDc0LDc2LDg4LDIwNywyMDgsMjM5LDE3MCwyNTEsNjcsNzcsNTEsMTMzLDY5LDI0OSwyLDEyNyw4MCw2MCwxNTksMTY4LDgxLDE2Myw2NCwxNDMsMTQ2LDE1Nyw1NiwyNDUsMTg4LDE4MiwyMTgsMzMsMTYsMjU1LDI0MywyMTAsMjA1LDEyLDE5LDIzNiw5NSwxNTEsNjgsMjMsMTk2LDE2NywxMjYsNjEsMTAwLDkzLDI1LDExNSw5NiwxMjksNzksMjIwLDM0LDQyLDE0NCwxMzYsNzAsMjM4LDE4NCwyMCwyMjIsOTQsMTEsMjE5LDIyNCw1MCw1OCwxMCw3Myw2LDM2LDkyLDE5NCwyMTEsMTcyLDk4LDE0NSwxNDksMjI4LDEyMSwyMzEsMjAwLDU1LDEwOSwxNDEsMjEzLDc4LDE2OSwxMDgsODYsMjQ0LDIzNCwxMDEsMTIyLDE3NCw4LDE4NiwxMjAsMzcsNDYsMjgsMTY2LDE4MCwxOTgsMjMyLDIyMSwxMTYsMzEsNzUsMTg5LDEzOSwxMzgsMTEyLDYyLDE4MSwxMDIsNzIsMywyNDYsMTQsOTcsNTMsODcsMTg1LDEzNCwxOTMsMjksMTU4LDIyNSwyNDgsMTUyLDE3LDEwNSwyMTcsMTQyLDE0OCwxNTUsMzAsMTM1LDIzMywyMDYsODUsNDAsMjIzLDE0MCwxNjEsMTM3LDEzLDE5MSwyMzAsNjYsMTA0LDY1LDE1Myw0NSwxNSwxNzYsODQsMTg3LDIyXSk7X2ludl9zPW5ldyBVaW50OEFycmF5KFs4Miw5LDEwNiwyMTMsNDgsNTQsMTY1LDU2LDE5MSw2NCwxNjMsMTU4LDEyOSwyNDMsMjE1LDI1MSwxMjQsMjI3LDU3LDEzMCwxNTUsNDcsMjU1LDEzNSw1MiwxNDIsNjcsNjgsMTk2LDIyMiwyMzMsMjAzLDg0LDEyMywxNDgsNTAsMTY2LDE5NCwzNSw2MSwyMzgsNzYsMTQ5LDExLDY2LDI1MCwxOTUsNzgsOCw0NiwxNjEsMTAyLDQwLDIxNywzNiwxNzgsMTE4LDkxLDE2Miw3MywxMDksMTM5LDIwOSwzNywxMTQsMjQ4LDI0NiwxMDAsMTM0LDEwNCwxNTIsMjIsMjEyLDE2NCw5MiwyMDQsOTMsMTAxLDE4MiwxNDYsMTA4LDExMiw3Miw4MCwyNTMsMjM3LDE4NSwyMTgsOTQsMjEsNzAsODcsMTY3LDE0MSwxNTcsMTMyLDE0NCwyMTYsMTcxLDAsMTQwLDE4OCwyMTEsMTAsMjQ3LDIyOCw4OCw1LDE4NCwxNzksNjksNiwyMDgsNDQsMzAsMTQzLDIwMiw2MywxNSwyLDE5MywxNzUsMTg5LDMsMSwxOSwxMzgsMTA3LDU4LDE0NSwxNyw2NSw3OSwxMDMsMjIwLDIzNCwxNTEsMjQyLDIwNywyMDYsMjQwLDE4MCwyMzAsMTE1LDE1MCwxNzIsMTE2LDM0LDIzMSwxNzMsNTMsMTMzLDIyNiwyNDksNTUsMjMyLDI4LDExNywyMjMsMTEwLDcxLDI0MSwyNiwxMTMsMjksNDEsMTk3LDEzNywxMTEsMTgzLDk4LDE0LDE3MCwyNCwxOTAsMjcsMjUyLDg2LDYyLDc1LDE5OCwyMTAsMTIxLDMyLDE1NCwyMTksMTkyLDI1NCwxMjAsMjA1LDkwLDI0NCwzMSwyMjEsMTY4LDUxLDEzNiw3LDE5OSw0OSwxNzcsMTgsMTYsODksMzksMTI4LDIzNiw5NSw5Niw4MSwxMjcsMTY5LDI1LDE4MSw3NCwxMyw0NSwyMjksMTIyLDE1OSwxNDcsMjAxLDE1NiwyMzksMTYwLDIyNCw1OSw3NywxNzQsNDIsMjQ1LDE3NiwyMDAsMjM1LDE4Nyw2MCwxMzEsODMsMTUzLDk3LDIzLDQzLDQsMTI2LDE4NiwxMTksMjE0LDM4LDIyNSwxMDUsMjAsOTksODUsMzMsMTIsMTI1XSk7X21peD1uZXcgVWludDMyQXJyYXkoWzAsMjM1NDc0MTg3LDQ3MDk0ODM3NCwzMDM3NjUyNzcsOTQxODk2NzQ4LDkwODkzMzQxNSw2MDc1MzA1NTQsNzA4NzgwODQ5LDE4ODM3OTM0OTYsMjExODIxNDk5NSwxODE3ODY2ODMwLDE2NDk2MzkyMzcsMTIxNTA2MTEwOCwxMTgxMDQ1MTE5LDE0MTc1NjE2OTgsMTUxNzc2NzUyOSwzNzY3NTg2OTkyLDQwMDMwNjExNzksNDIzNjQyOTk5MCw0MDY5MjQ2ODkzLDM2MzU3MzM2NjAsMzYwMjc3MDMyNywzMjk5Mjc4NDc0LDM0MDA1Mjg3NjksMjQzMDEyMjIxNiwyNjY0NTQzNzE1LDIzNjIwOTAyMzgsMjE5Mzg2MjY0NSwyODM1MTIzMzk2LDI4MDExMDc0MDcsMzAzNTUzNTA1OCwzMTM1NzQwODg5LDM2NzgxMjQ5MjMsMzU3Njg3MDUxMiwzMzQxMzk0Mjg1LDMzNzQzNjE3MDIsMzgxMDQ5NjM0MywzOTc3Njc1MzU2LDQyNzkwODAyNTcsNDA0MzYxMDE4NiwyODc2NDk0NjI3LDI3NzYyOTI5MDQsMzA3NjYzOTAyOSwzMTEwNjUwOTQyLDI0NzIwMTE1MzUsMjY0MDI0MzIwNCwyNDAzNzI4NjY1LDIxNjkzMDMwNTgsMTAwMTA4OTk5NSw4OTk4MzU1ODQsNjY2NDY0NzMzLDY5OTQzMjE1MCw1OTcyNzg0NywyMjY5MDY4NjAsNTMwNDAwNzUzLDI5NDkzMDY4MiwxMjczMTY4Nzg3LDExNzI5NjcwNjQsMTQ3NTQxODUwMSwxNTA5NDMwNDE0LDE5NDI0MzU3NzUsMjExMDY2NzQ0NCwxODc2MjQxODMzLDE2NDE4MTYyMjYsMjkxMDIxOTc2NiwyNzQzMDM0MTA5LDI5NzYxNTE1MjAsMzIxMTYyMzE0NywyNTA1MjAyMTM4LDI2MDY0NTM5NjksMjMwMjY5MDI1MiwyMjY5NzI4NDU1LDM3MTE4Mjk0MjIsMzU0MzU5OTI2OSwzMjQwODk0MzkyLDM0NzUzMTMzMzEsMzg0MzY5OTA3NCwzOTQzOTA2NDQxLDQxNzgwNjIyMjgsNDE0NDA0Nzc3NSwxMzA2OTY3MzY2LDExMzk3ODE3MDksMTM3NDk4ODExMiwxNjEwNDU5NzM5LDE5NzU2ODM0MzQsMjA3NjkzNTI2NSwxNzc1Mjc2OTI0LDE3NDIzMTUxMjcsMTAzNDg2Nzk5OCw4NjY2Mzc4NDUsNTY2MDIxODk2LDgwMDQ0MDgzNSw5Mjk4NzY5OCwxOTMxOTUwNjUsNDI5NDU2MTY0LDM5NTQ0MTcxMSwxOTg0ODEyNjg1LDIwMTc3Nzg1NjYsMTc4NDY2MzE5NSwxNjgzNDA3MjQ4LDEzMTU1NjIxNDUsMTA4MDA5NDYzNCwxMzgzODU2MzExLDE1NTEwMzc4ODQsMTAxMDM5ODI5LDEzNTA1MDIwNiw0Mzc3NTcxMjMsMzM3NTUzODY0LDEwNDIzODU2NTcsODA3OTYyNjEwLDU3MzgwNDc4Myw3NDIwMzkwMTIsMjUzMTA2NzQ1MywyNTY0MDMzMzM0LDIzMjg4Mjg5NzEsMjIyNzU3MzAyNCwyOTM1NTY2ODY1LDI3MDAwOTkzNTQsMzAwMTc1NTY1NSwzMTY4OTM3MjI4LDM4Njg1NTI4MDUsMzkwMjU2MzE4Miw0MjAzMTgxMTcxLDQxMDI5Nzc5MTIsMzczNjE2NDkzNywzNTAxNzQxODkwLDMyNjU0Nzg3NTEsMzQzMzcxMjk4MCwxMTA2MDQxNTkxLDEzNDA0NjMxMDAsMTU3Njk3NjYwOSwxNDA4NzQ5MDM0LDIwNDMyMTE0ODMsMjAwOTE5NTQ3MiwxNzA4ODQ4MzMzLDE4MDkwNTQxNTAsODMyODc3MjMxLDEwNjgzNTEzOTYsNzY2OTQ1NDY1LDU5OTc2MjM1NCwxNTk0MTc5ODcsMTI2NDU0NjY0LDM2MTkyOTg3Nyw0NjMxODAxOTAsMjcwOTI2MDg3MSwyOTQzNjgyMzgwLDMxNzgxMDY5NjEsMzAwOTg3OTM4NiwyNTcyNjk3MTk1LDI1Mzg2ODExODQsMjIzNjIyODczMywyMzM2NDM0NTUwLDM1MDk4NzExMzUsMzc0NTM0NTMwMCwzNDQxODUwMzc3LDMyNzQ2NjcyNjYsMzkxMDE2MTk3MSwzODc3MTk4NjQ4LDQxMTA1Njg0ODUsNDIxMTgxODc5OCwyNTk3ODA2NDc2LDI0OTc2MDQ3NDMsMjI2MTA4OTE3OCwyMjk1MTAxMDczLDI3MzM4NTYxNjAsMjkwMjA4Nzg1MSwzMjAyNDM3MDQ2LDI5NjgwMTE0NTMsMzkzNjI5MTI4NCwzODM1MDM2ODk1LDQxMzY0NDA3NzAsNDE2OTQwODIwMSwzNTM1NDg2NDU2LDM3MDI2NjU0NTksMzQ2NzE5MjMwMiwzMjMxNzIyMjEzLDIwNTE1MTg3ODAsMTk1MTMxNzA0NywxNzE2ODkwNDEwLDE3NTA5MDIzMDUsMTExMzgxODM4NCwxMjgyMDUwMDc1LDE1ODQ1MDQ1ODIsMTM1MDA3ODk4OSwxNjg4MTA4NTIsNjc1NTY0NjMsMzcxMDQ5MzMwLDQwNDAxNjc2MSw4NDE3Mzk1OTIsMTAwODkxODU5NSw3NzU1NTA4MTQsNTQwMDgwNzI1LDM5Njk1NjIzNjksMzgwMTMzMjIzNCw0MDM1NDg5MDQ3LDQyNjk5MDc5OTYsMzU2OTI1NTIxMywzNjY5NDYyNTY2LDMzNjY3NTQ2MTksMzMzMjc0MDE0NCwyNjMxMDY1NDMzLDI0NjM4Nzk3NjIsMjE2MDExNzA3MSwyMzk1NTg4Njc2LDI3Njc2NDU1NTcsMjg2ODg5NzQwNiwzMTAyMDExNzQ3LDMwNjkwNDk5NjAsMjAyMDA4NDk3LDMzNzc4MzYyLDI3MDA0MDQ4Nyw1MDQ0NTk0MzYsODc1NDUxMjkzLDk3NTY1ODY0Niw2NzUwMzk2MjcsNjQxMDI1MTUyLDIwODQ3MDQyMzMsMTkxNzUxODU2MiwxNjE1ODYxMjQ3LDE4NTEzMzI4NTIsMTE0NzU1MDY2MSwxMjQ4ODAyNTEwLDE0ODQwMDU4NDMsMTQ1MTA0NDA1Niw5MzMzMDEzNzAsOTY3MzExNzI5LDczMzE1Njk3Miw2MzI5NTM3MDMsMjYwMzg4OTUwLDI1OTY1OTE3LDMyODY3MTgwOCw0OTY5MDYwNTksMTIwNjQ3Nzg1OCwxMjM5NDQzNzUzLDE1NDMyMDg1MDAsMTQ0MTk1MjU3NSwyMTQ0MTYxODA2LDE5MDg2OTQyNzcsMTY3NTU3Nzg4MCwxODQyNzU5NDQzLDM2MTAzNjkyMjYsMzY0NDM3OTU4NSwzNDA4MTE5NTE2LDMzMDc5MTYyNDcsNDAxMTE5MDUwMiwzNzc2NzY3NDY5LDQwNzczODQ0MzIsNDI0NTYxODY4MywyODA5NzcxMTU0LDI4NDI3MzcwNDksMzE0NDM5NjQyMCwzMDQzMTQwNDk1LDI2NzM3MDUxNTAsMjQzODIzNzYyMSwyMjAzMDMyMjMyLDIzNzAyMTM3OTVdKTtfbWl4Q29sPW5ldyBVaW50OEFycmF5KDI1NikubWFwKChlLHQpPT50PDEyOD90PDwxOnQ8PDFeMjcpO2NvbnN0cnVjdG9yKCl7dGhpcy5idWZmZXI9bmV3IFVpbnQ4QXJyYXkoMTYpO3RoaXMuYnVmZmVyUG9zaXRpb249MH1fZXhwYW5kS2V5KGUpe3VucmVhY2hhYmxlKCJDYW5ub3QgY2FsbCBgX2V4cGFuZEtleWAgb24gdGhlIGJhc2UgY2xhc3MiKX1fZGVjcnlwdChlLHQpe2xldCByLGEsbjtjb25zdCBpPW5ldyBVaW50OEFycmF5KDE2KTtpLnNldChlKTtmb3IobGV0IGU9MCxyPXRoaXMuX2tleVNpemU7ZTwxNjsrK2UsKytyKWlbZV1ePXRbcl07Zm9yKGxldCBlPXRoaXMuX2N5Y2xlc09mUmVwZXRpdGlvbi0xO2U+PTE7LS1lKXtyPWlbMTNdO2lbMTNdPWlbOV07aVs5XT1pWzVdO2lbNV09aVsxXTtpWzFdPXI7cj1pWzE0XTthPWlbMTBdO2lbMTRdPWlbNl07aVsxMF09aVsyXTtpWzZdPXI7aVsyXT1hO3I9aVsxNV07YT1pWzExXTtuPWlbN107aVsxNV09aVszXTtpWzExXT1yO2lbN109YTtpWzNdPW47Zm9yKGxldCBlPTA7ZTwxNjsrK2UpaVtlXT10aGlzLl9pbnZfc1tpW2VdXTtmb3IobGV0IHI9MCxhPTE2KmU7cjwxNjsrK3IsKythKWlbcl1ePXRbYV07Zm9yKGxldCBlPTA7ZTwxNjtlKz00KXtjb25zdCB0PXRoaXMuX21peFtpW2VdXSxhPXRoaXMuX21peFtpW2UrMV1dLG49dGhpcy5fbWl4W2lbZSsyXV0scz10aGlzLl9taXhbaVtlKzNdXTtyPXReYT4+PjheYTw8MjRebj4+PjE2Xm48PDE2XnM+Pj4yNF5zPDw4O2lbZV09cj4+PjI0JjI1NTtpW2UrMV09cj4+MTYmMjU1O2lbZSsyXT1yPj44JjI1NTtpW2UrM109MjU1JnJ9fXI9aVsxM107aVsxM109aVs5XTtpWzldPWlbNV07aVs1XT1pWzFdO2lbMV09cjtyPWlbMTRdO2E9aVsxMF07aVsxNF09aVs2XTtpWzEwXT1pWzJdO2lbNl09cjtpWzJdPWE7cj1pWzE1XTthPWlbMTFdO249aVs3XTtpWzE1XT1pWzNdO2lbMTFdPXI7aVs3XT1hO2lbM109bjtmb3IobGV0IGU9MDtlPDE2OysrZSl7aVtlXT10aGlzLl9pbnZfc1tpW2VdXTtpW2VdXj10W2VdfXJldHVybiBpfV9lbmNyeXB0KGUsdCl7Y29uc3Qgcj10aGlzLl9zO2xldCBhLG4saTtjb25zdCBzPW5ldyBVaW50OEFycmF5KDE2KTtzLnNldChlKTtmb3IobGV0IGU9MDtlPDE2OysrZSlzW2VdXj10W2VdO2ZvcihsZXQgZT0xO2U8dGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uO2UrKyl7Zm9yKGxldCBlPTA7ZTwxNjsrK2Upc1tlXT1yW3NbZV1dO2k9c1sxXTtzWzFdPXNbNV07c1s1XT1zWzldO3NbOV09c1sxM107c1sxM109aTtpPXNbMl07bj1zWzZdO3NbMl09c1sxMF07c1s2XT1zWzE0XTtzWzEwXT1pO3NbMTRdPW47aT1zWzNdO249c1s3XTthPXNbMTFdO3NbM109c1sxNV07c1s3XT1pO3NbMTFdPW47c1sxNV09YTtmb3IobGV0IGU9MDtlPDE2O2UrPTQpe2NvbnN0IHQ9c1tlXSxyPXNbZSsxXSxuPXNbZSsyXSxpPXNbZSszXTthPXRecl5uXmk7c1tlXV49YV50aGlzLl9taXhDb2xbdF5yXTtzW2UrMV1ePWFedGhpcy5fbWl4Q29sW3Jebl07c1tlKzJdXj1hXnRoaXMuX21peENvbFtuXmldO3NbZSszXV49YV50aGlzLl9taXhDb2xbaV50XX1mb3IobGV0IHI9MCxhPTE2KmU7cjwxNjsrK3IsKythKXNbcl1ePXRbYV19Zm9yKGxldCBlPTA7ZTwxNjsrK2Upc1tlXT1yW3NbZV1dO2k9c1sxXTtzWzFdPXNbNV07c1s1XT1zWzldO3NbOV09c1sxM107c1sxM109aTtpPXNbMl07bj1zWzZdO3NbMl09c1sxMF07c1s2XT1zWzE0XTtzWzEwXT1pO3NbMTRdPW47aT1zWzNdO249c1s3XTthPXNbMTFdO3NbM109c1sxNV07c1s3XT1pO3NbMTFdPW47c1sxNV09YTtmb3IobGV0IGU9MCxyPXRoaXMuX2tleVNpemU7ZTwxNjsrK2UsKytyKXNbZV1ePXRbcl07cmV0dXJuIHN9X2RlY3J5cHRCbG9jazIoZSx0KXtjb25zdCByPWUubGVuZ3RoO2xldCBhPXRoaXMuYnVmZmVyLG49dGhpcy5idWZmZXJQb3NpdGlvbjtjb25zdCBpPVtdO2xldCBzPXRoaXMuaXY7Zm9yKGxldCB0PTA7dDxyOysrdCl7YVtuXT1lW3RdOysrbjtpZihuPDE2KWNvbnRpbnVlO2NvbnN0IHI9dGhpcy5fZGVjcnlwdChhLHRoaXMuX2tleSk7Zm9yKGxldCBlPTA7ZTwxNjsrK2UpcltlXV49c1tlXTtzPWE7aS5wdXNoKHIpO2E9bmV3IFVpbnQ4QXJyYXkoMTYpO249MH10aGlzLmJ1ZmZlcj1hO3RoaXMuYnVmZmVyTGVuZ3RoPW47dGhpcy5pdj1zO2lmKDA9PT1pLmxlbmd0aClyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7bGV0IG89MTYqaS5sZW5ndGg7aWYodCl7Y29uc3QgZT1pLmF0KC0xKTtsZXQgdD1lWzE1XTtpZih0PD0xNil7Zm9yKGxldCByPTE1LGE9MTYtdDtyPj1hOy0tcilpZihlW3JdIT09dCl7dD0wO2JyZWFrfW8tPXQ7aVtpLmxlbmd0aC0xXT1lLnN1YmFycmF5KDAsMTYtdCl9fWNvbnN0IGM9bmV3IFVpbnQ4QXJyYXkobyk7Zm9yKGxldCBlPTAsdD0wLHI9aS5sZW5ndGg7ZTxyOysrZSx0Kz0xNiljLnNldChpW2VdLHQpO3JldHVybiBjfWRlY3J5cHRCbG9jayhlLHQscj1udWxsKXtjb25zdCBhPWUubGVuZ3RoLG49dGhpcy5idWZmZXI7bGV0IGk9dGhpcy5idWZmZXJQb3NpdGlvbjtpZihyKXRoaXMuaXY9cjtlbHNle2ZvcihsZXQgdD0wO2k8MTYmJnQ8YTsrK3QsKytpKW5baV09ZVt0XTtpZihpPDE2KXt0aGlzLmJ1ZmZlckxlbmd0aD1pO3JldHVybiBuZXcgVWludDhBcnJheSgwKX10aGlzLml2PW47ZT1lLnN1YmFycmF5KDE2KX10aGlzLmJ1ZmZlcj1uZXcgVWludDhBcnJheSgxNik7dGhpcy5idWZmZXJMZW5ndGg9MDt0aGlzLmRlY3J5cHRCbG9jaz10aGlzLl9kZWNyeXB0QmxvY2syO3JldHVybiB0aGlzLmRlY3J5cHRCbG9jayhlLHQpfWVuY3J5cHQoZSx0KXtjb25zdCByPWUubGVuZ3RoO2xldCBhPXRoaXMuYnVmZmVyLG49dGhpcy5idWZmZXJQb3NpdGlvbjtjb25zdCBpPVtdO3R8fD1uZXcgVWludDhBcnJheSgxNik7Zm9yKGxldCBzPTA7czxyOysrcyl7YVtuXT1lW3NdOysrbjtpZihuPDE2KWNvbnRpbnVlO2ZvcihsZXQgZT0wO2U8MTY7KytlKWFbZV1ePXRbZV07Y29uc3Qgcj10aGlzLl9lbmNyeXB0KGEsdGhpcy5fa2V5KTt0PXI7aS5wdXNoKHIpO2E9bmV3IFVpbnQ4QXJyYXkoMTYpO249MH10aGlzLmJ1ZmZlcj1hO3RoaXMuYnVmZmVyTGVuZ3RoPW47dGhpcy5pdj10O2lmKDA9PT1pLmxlbmd0aClyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7Y29uc3Qgcz0xNippLmxlbmd0aCxvPW5ldyBVaW50OEFycmF5KHMpO2ZvcihsZXQgZT0wLHQ9MCxyPWkubGVuZ3RoO2U8cjsrK2UsdCs9MTYpby5zZXQoaVtlXSx0KTtyZXR1cm4gb319Y2xhc3MgQUVTMTI4Q2lwaGVyIGV4dGVuZHMgQUVTQmFzZUNpcGhlcntfcmNvbj1uZXcgVWludDhBcnJheShbMTQxLDEsMiw0LDgsMTYsMzIsNjQsMTI4LDI3LDU0LDEwOCwyMTYsMTcxLDc3LDE1NCw0Nyw5NCwxODgsOTksMTk4LDE1MSw1MywxMDYsMjEyLDE3OSwxMjUsMjUwLDIzOSwxOTcsMTQ1LDU3LDExNCwyMjgsMjExLDE4OSw5NywxOTQsMTU5LDM3LDc0LDE0OCw1MSwxMDIsMjA0LDEzMSwyOSw1OCwxMTYsMjMyLDIwMywxNDEsMSwyLDQsOCwxNiwzMiw2NCwxMjgsMjcsNTQsMTA4LDIxNiwxNzEsNzcsMTU0LDQ3LDk0LDE4OCw5OSwxOTgsMTUxLDUzLDEwNiwyMTIsMTc5LDEyNSwyNTAsMjM5LDE5NywxNDUsNTcsMTE0LDIyOCwyMTEsMTg5LDk3LDE5NCwxNTksMzcsNzQsMTQ4LDUxLDEwMiwyMDQsMTMxLDI5LDU4LDExNiwyMzIsMjAzLDE0MSwxLDIsNCw4LDE2LDMyLDY0LDEyOCwyNyw1NCwxMDgsMjE2LDE3MSw3NywxNTQsNDcsOTQsMTg4LDk5LDE5OCwxNTEsNTMsMTA2LDIxMiwxNzksMTI1LDI1MCwyMzksMTk3LDE0NSw1NywxMTQsMjI4LDIxMSwxODksOTcsMTk0LDE1OSwzNyw3NCwxNDgsNTEsMTAyLDIwNCwxMzEsMjksNTgsMTE2LDIzMiwyMDMsMTQxLDEsMiw0LDgsMTYsMzIsNjQsMTI4LDI3LDU0LDEwOCwyMTYsMTcxLDc3LDE1NCw0Nyw5NCwxODgsOTksMTk4LDE1MSw1MywxMDYsMjEyLDE3OSwxMjUsMjUwLDIzOSwxOTcsMTQ1LDU3LDExNCwyMjgsMjExLDE4OSw5NywxOTQsMTU5LDM3LDc0LDE0OCw1MSwxMDIsMjA0LDEzMSwyOSw1OCwxMTYsMjMyLDIwMywxNDEsMSwyLDQsOCwxNiwzMiw2NCwxMjgsMjcsNTQsMTA4LDIxNiwxNzEsNzcsMTU0LDQ3LDk0LDE4OCw5OSwxOTgsMTUxLDUzLDEwNiwyMTIsMTc5LDEyNSwyNTAsMjM5LDE5NywxNDUsNTcsMTE0LDIyOCwyMTEsMTg5LDk3LDE5NCwxNTksMzcsNzQsMTQ4LDUxLDEwMiwyMDQsMTMxLDI5LDU4LDExNiwyMzIsMjAzLDE0MV0pO2NvbnN0cnVjdG9yKGUpe3N1cGVyKCk7dGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uPTEwO3RoaXMuX2tleVNpemU9MTYwO3RoaXMuX2tleT10aGlzLl9leHBhbmRLZXkoZSl9X2V4cGFuZEtleShlKXtjb25zdCB0PXRoaXMuX3Mscj10aGlzLl9yY29uLGE9bmV3IFVpbnQ4QXJyYXkoMTc2KTthLnNldChlKTtmb3IobGV0IGU9MTYsbj0xO2U8MTc2Oysrbil7bGV0IGk9YVtlLTNdLHM9YVtlLTJdLG89YVtlLTFdLGM9YVtlLTRdO2k9dFtpXTtzPXRbc107bz10W29dO2M9dFtjXTtpXj1yW25dO2ZvcihsZXQgdD0wO3Q8NDsrK3Qpe2FbZV09aV49YVtlLTE2XTtlKys7YVtlXT1zXj1hW2UtMTZdO2UrKzthW2VdPW9ePWFbZS0xNl07ZSsrO2FbZV09Y149YVtlLTE2XTtlKyt9fXJldHVybiBhfX1jbGFzcyBBRVMyNTZDaXBoZXIgZXh0ZW5kcyBBRVNCYXNlQ2lwaGVye2NvbnN0cnVjdG9yKGUpe3N1cGVyKCk7dGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uPTE0O3RoaXMuX2tleVNpemU9MjI0O3RoaXMuX2tleT10aGlzLl9leHBhbmRLZXkoZSl9X2V4cGFuZEtleShlKXtjb25zdCB0PXRoaXMuX3Mscj1uZXcgVWludDhBcnJheSgyNDApO3Iuc2V0KGUpO2xldCBhLG4saSxzLG89MTtmb3IobGV0IGU9MzIsYz0xO2U8MjQwOysrYyl7aWYoZSUzMj09MTYpe2E9dFthXTtuPXRbbl07aT10W2ldO3M9dFtzXX1lbHNlIGlmKGUlMzI9PTApe2E9cltlLTNdO249cltlLTJdO2k9cltlLTFdO3M9cltlLTRdO2E9dFthXTtuPXRbbl07aT10W2ldO3M9dFtzXTthXj1vOyhvPDw9MSk+PTI1NiYmKG89MjU1JigyN15vKSl9Zm9yKGxldCB0PTA7dDw0OysrdCl7cltlXT1hXj1yW2UtMzJdO2UrKztyW2VdPW5ePXJbZS0zMl07ZSsrO3JbZV09aV49cltlLTMyXTtlKys7cltlXT1zXj1yW2UtMzJdO2UrK319cmV0dXJuIHJ9fWNsYXNzIFBERkJhc2V7X2hhc2goZSx0LHIpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYF9oYXNoYCBjYWxsZWQiKX1jaGVja093bmVyUGFzc3dvcmQoZSx0LHIsYSl7Y29uc3Qgbj1uZXcgVWludDhBcnJheShlLmxlbmd0aCs1Nik7bi5zZXQoZSwwKTtuLnNldCh0LGUubGVuZ3RoKTtuLnNldChyLGUubGVuZ3RoK3QubGVuZ3RoKTtyZXR1cm4gaXNBcnJheUVxdWFsKHRoaXMuX2hhc2goZSxuLHIpLGEpfWNoZWNrVXNlclBhc3N3b3JkKGUsdCxyKXtjb25zdCBhPW5ldyBVaW50OEFycmF5KGUubGVuZ3RoKzgpO2Euc2V0KGUsMCk7YS5zZXQodCxlLmxlbmd0aCk7cmV0dXJuIGlzQXJyYXlFcXVhbCh0aGlzLl9oYXNoKGUsYSxbXSkscil9Z2V0T3duZXJLZXkoZSx0LHIsYSl7Y29uc3Qgbj1uZXcgVWludDhBcnJheShlLmxlbmd0aCs1Nik7bi5zZXQoZSwwKTtuLnNldCh0LGUubGVuZ3RoKTtuLnNldChyLGUubGVuZ3RoK3QubGVuZ3RoKTtjb25zdCBpPXRoaXMuX2hhc2goZSxuLHIpO3JldHVybiBuZXcgQUVTMjU2Q2lwaGVyKGkpLmRlY3J5cHRCbG9jayhhLCExLG5ldyBVaW50OEFycmF5KDE2KSl9Z2V0VXNlcktleShlLHQscil7Y29uc3QgYT1uZXcgVWludDhBcnJheShlLmxlbmd0aCs4KTthLnNldChlLDApO2Euc2V0KHQsZS5sZW5ndGgpO2NvbnN0IG49dGhpcy5faGFzaChlLGEsW10pO3JldHVybiBuZXcgQUVTMjU2Q2lwaGVyKG4pLmRlY3J5cHRCbG9jayhyLCExLG5ldyBVaW50OEFycmF5KDE2KSl9fWNsYXNzIFBERjE3IGV4dGVuZHMgUERGQmFzZXtfaGFzaChlLHQscil7cmV0dXJuIGNhbGN1bGF0ZVNIQTI1Nih0LDAsdC5sZW5ndGgpfX1jbGFzcyBQREYyMCBleHRlbmRzIFBERkJhc2V7X2hhc2goZSx0LHIpe2xldCBhPWNhbGN1bGF0ZVNIQTI1Nih0LDAsdC5sZW5ndGgpLnN1YmFycmF5KDAsMzIpLG49WzBdLGk9MDtmb3IoO2k8NjR8fG4uYXQoLTEpPmktMzI7KXtjb25zdCB0PWUubGVuZ3RoK2EubGVuZ3RoK3IubGVuZ3RoLHM9bmV3IFVpbnQ4QXJyYXkodCk7bGV0IG89MDtzLnNldChlLG8pO28rPWUubGVuZ3RoO3Muc2V0KGEsbyk7bys9YS5sZW5ndGg7cy5zZXQocixvKTtjb25zdCBjPW5ldyBVaW50OEFycmF5KDY0KnQpO2ZvcihsZXQgZT0wLHI9MDtlPDY0O2UrKyxyKz10KWMuc2V0KHMscik7bj1uZXcgQUVTMTI4Q2lwaGVyKGEuc3ViYXJyYXkoMCwxNikpLmVuY3J5cHQoYyxhLnN1YmFycmF5KDE2LDMyKSk7Y29uc3QgbD1NYXRoLnN1bVByZWNpc2Uobi5zbGljZSgwLDE2KSklMzswPT09bD9hPWNhbGN1bGF0ZVNIQTI1NihuLDAsbi5sZW5ndGgpOjE9PT1sP2E9Y2FsY3VsYXRlU0hBMzg0KG4sMCxuLmxlbmd0aCk6Mj09PWwmJihhPWNhbGN1bGF0ZVNIQTUxMihuLDAsbi5sZW5ndGgpKTtpKyt9cmV0dXJuIGEuc3ViYXJyYXkoMCwzMil9fWNsYXNzIENpcGhlclRyYW5zZm9ybXtjb25zdHJ1Y3RvcihlLHQpe3RoaXMuU3RyaW5nQ2lwaGVyQ29uc3RydWN0b3I9ZTt0aGlzLlN0cmVhbUNpcGhlckNvbnN0cnVjdG9yPXR9Y3JlYXRlU3RyZWFtKGUsdCl7Y29uc3Qgcj1uZXcgdGhpcy5TdHJlYW1DaXBoZXJDb25zdHJ1Y3RvcjtyZXR1cm4gbmV3IERlY3J5cHRTdHJlYW0oZSx0LGZ1bmN0aW9uIGNpcGhlclRyYW5zZm9ybURlY3J5cHRTdHJlYW0oZSx0KXtyZXR1cm4gci5kZWNyeXB0QmxvY2soZSx0KX0pfWRlY3J5cHRTdHJpbmcoZSl7Y29uc3QgdD1uZXcgdGhpcy5TdHJpbmdDaXBoZXJDb25zdHJ1Y3RvcjtsZXQgcj1zdHJpbmdUb0J5dGVzKGUpO3I9dC5kZWNyeXB0QmxvY2sociwhMCk7cmV0dXJuIGJ5dGVzVG9TdHJpbmcocil9ZW5jcnlwdFN0cmluZyhlKXtjb25zdCB0PW5ldyB0aGlzLlN0cmluZ0NpcGhlckNvbnN0cnVjdG9yO2lmKHQgaW5zdGFuY2VvZiBBRVNCYXNlQ2lwaGVyKXtjb25zdCByPTE2LWUubGVuZ3RoJTE2O2UrPVN0cmluZy5mcm9tQ2hhckNvZGUocikucmVwZWF0KHIpO2NvbnN0IGE9bmV3IFVpbnQ4QXJyYXkoMTYpO2NyeXB0by5nZXRSYW5kb21WYWx1ZXMoYSk7bGV0IG49c3RyaW5nVG9CeXRlcyhlKTtuPXQuZW5jcnlwdChuLGEpO2NvbnN0IGk9bmV3IFVpbnQ4QXJyYXkoMTYrbi5sZW5ndGgpO2kuc2V0KGEpO2kuc2V0KG4sMTYpO3JldHVybiBieXRlc1RvU3RyaW5nKGkpfWxldCByPXN0cmluZ1RvQnl0ZXMoZSk7cj10LmVuY3J5cHQocik7cmV0dXJuIGJ5dGVzVG9TdHJpbmcocil9fWNsYXNzIENpcGhlclRyYW5zZm9ybUZhY3Rvcnl7c3RhdGljIGdldCBfZGVmYXVsdFBhc3N3b3JkQnl0ZXMoKXtyZXR1cm4gc2hhZG93KHRoaXMsIl9kZWZhdWx0UGFzc3dvcmRCeXRlcyIsbmV3IFVpbnQ4QXJyYXkoWzQwLDE5MSw3OCw5NCw3OCwxMTcsMTM4LDY1LDEwMCwwLDc4LDg2LDI1NSwyNTAsMSw4LDQ2LDQ2LDAsMTgyLDIwOCwxMDQsNjIsMTI4LDQ3LDEyLDE2OSwyNTQsMTAwLDgzLDEwNSwxMjJdKSl9I2plKGUsdCxyLGEsbixpLHMsbyxjLGwsaCx1KXtpZih0KXtjb25zdCBlPU1hdGgubWluKDEyNyx0Lmxlbmd0aCk7dD10LnN1YmFycmF5KDAsZSl9ZWxzZSB0PVtdO2NvbnN0IGQ9Nj09PWU/bmV3IFBERjIwOm5ldyBQREYxNztyZXR1cm4gZC5jaGVja1VzZXJQYXNzd29yZCh0LG8scyk/ZC5nZXRVc2VyS2V5KHQsYyxoKTp0Lmxlbmd0aCYmZC5jaGVja093bmVyUGFzc3dvcmQodCxhLGkscik/ZC5nZXRPd25lcktleSh0LG4saSxsKTpudWxsfSNVZShlLHQscixhLG4saSxzLG8pe2NvbnN0IGM9NDArci5sZW5ndGgrZS5sZW5ndGgsbD1uZXcgVWludDhBcnJheShjKTtsZXQgaCx1LGQ9MDtpZih0KXt1PU1hdGgubWluKDMyLHQubGVuZ3RoKTtmb3IoO2Q8dTsrK2QpbFtkXT10W2RdfWg9MDtmb3IoO2Q8MzI7KWxbZCsrXT1DaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Ll9kZWZhdWx0UGFzc3dvcmRCeXRlc1toKytdO2wuc2V0KHIsZCk7ZCs9ci5sZW5ndGg7bFtkKytdPTI1NSZuO2xbZCsrXT1uPj44JjI1NTtsW2QrK109bj4+MTYmMjU1O2xbZCsrXT1uPj4+MjQmMjU1O2wuc2V0KGUsZCk7ZCs9ZS5sZW5ndGg7aWYoaT49NCYmIW8pe2wuZmlsbCgyNTUsZCxkKzQpO2QrPTR9bGV0IGY9Y2FsY3VsYXRlTUQ1KGwsMCxkKTtjb25zdCBnPXM+PjM7aWYoaT49Mylmb3IoaD0wO2g8NTA7KytoKWY9Y2FsY3VsYXRlTUQ1KGYsMCxnKTtjb25zdCBwPWYuc3ViYXJyYXkoMCxnKTtsZXQgbSxiO2lmKGk+PTMpe2Q9MDtsLnNldChDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Ll9kZWZhdWx0UGFzc3dvcmRCeXRlcyxkKTtkKz0zMjtsLnNldChlLGQpO2QrPWUubGVuZ3RoO209bmV3IEFSQ0ZvdXJDaXBoZXIocCk7Yj1tLmVuY3J5cHRCbG9jayhjYWxjdWxhdGVNRDUobCwwLGQpKTt1PXAubGVuZ3RoO2NvbnN0IHQ9bmV3IFVpbnQ4QXJyYXkodSk7Zm9yKGg9MTtoPD0xOTsrK2gpe2ZvcihsZXQgZT0wO2U8dTsrK2UpdFtlXT1wW2VdXmg7bT1uZXcgQVJDRm91ckNpcGhlcih0KTtiPW0uZW5jcnlwdEJsb2NrKGIpfX1lbHNle209bmV3IEFSQ0ZvdXJDaXBoZXIocCk7Yj1tLmVuY3J5cHRCbG9jayhDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Ll9kZWZhdWx0UGFzc3dvcmRCeXRlcyl9cmV0dXJuIGIuZXZlcnkoKGUsdCk9PmFbdF09PT1lKT9wOm51bGx9I3FlKGUsdCxyLGEpe2NvbnN0IG49bmV3IFVpbnQ4QXJyYXkoMzIpO2xldCBpPTA7Y29uc3Qgcz1NYXRoLm1pbigzMixlLmxlbmd0aCk7Zm9yKDtpPHM7KytpKW5baV09ZVtpXTtsZXQgbz0wO2Zvcig7aTwzMjspbltpKytdPUNpcGhlclRyYW5zZm9ybUZhY3RvcnkuX2RlZmF1bHRQYXNzd29yZEJ5dGVzW28rK107bGV0IGM9Y2FsY3VsYXRlTUQ1KG4sMCxpKTtjb25zdCBsPWE+PjM7aWYocj49Mylmb3Iobz0wO288NTA7KytvKWM9Y2FsY3VsYXRlTUQ1KGMsMCxjLmxlbmd0aCk7bGV0IGgsdTtpZihyPj0zKXt1PXQ7Y29uc3QgZT1uZXcgVWludDhBcnJheShsKTtmb3Iobz0xOTtvPj0wO28tLSl7Zm9yKGxldCB0PTA7dDxsOysrdCllW3RdPWNbdF1ebztoPW5ldyBBUkNGb3VyQ2lwaGVyKGUpO3U9aC5lbmNyeXB0QmxvY2sodSl9fWVsc2V7aD1uZXcgQVJDRm91ckNpcGhlcihjLnN1YmFycmF5KDAsbCkpO3U9aC5lbmNyeXB0QmxvY2sodCl9cmV0dXJuIHV9I1hlKGUsdCxyLGE9ITEpe2NvbnN0IG49ci5sZW5ndGgsaT1uZXcgVWludDhBcnJheShuKzkpO2kuc2V0KHIpO2xldCBzPW47aVtzKytdPTI1NSZlO2lbcysrXT1lPj44JjI1NTtpW3MrK109ZT4+MTYmMjU1O2lbcysrXT0yNTUmdDtpW3MrK109dD4+OCYyNTU7aWYoYSl7aVtzKytdPTExNTtpW3MrK109NjU7aVtzKytdPTEwODtpW3MrK109ODR9cmV0dXJuIGNhbGN1bGF0ZU1ENShpLDAscykuc3ViYXJyYXkoMCxNYXRoLm1pbihuKzUsMTYpKX0jSGUoZSx0LHIsYSxuKXtpZighKHQgaW5zdGFuY2VvZiBOYW1lKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgY3J5cHQgZmlsdGVyIG5hbWUuIik7Y29uc3QgaT10aGlzLHM9ZS5nZXQodC5uYW1lKSxvPXM/LmdldCgiQ0ZNIik7aWYoIW98fCJOb25lIj09PW8ubmFtZSlyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE51bGxDaXBoZXJ9O2lmKCJWMiI9PT1vLm5hbWUpcmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBBUkNGb3VyQ2lwaGVyKGkuI1hlKHIsYSxuLCExKSl9O2lmKCJBRVNWMiI9PT1vLm5hbWUpcmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBBRVMxMjhDaXBoZXIoaS4jWGUocixhLG4sITApKX07aWYoIkFFU1YzIj09PW8ubmFtZSlyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEFFUzI1NkNpcGhlcihuKX07dGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbmtub3duIGNyeXB0byBtZXRob2QiKX1jb25zdHJ1Y3RvcihlLHQscil7Y29uc3QgYT1lLmdldCgiRmlsdGVyIik7aWYoIWlzTmFtZShhLCJTdGFuZGFyZCIpKXRocm93IG5ldyBGb3JtYXRFcnJvcigidW5rbm93biBlbmNyeXB0aW9uIG1ldGhvZCIpO3RoaXMuZmlsdGVyTmFtZT1hLm5hbWU7dGhpcy5kaWN0PWU7Y29uc3Qgbj1lLmdldCgiViIpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKG4pfHwxIT09biYmMiE9PW4mJjQhPT1uJiY1IT09bil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoInVuc3VwcG9ydGVkIGVuY3J5cHRpb24gYWxnb3JpdGhtIik7dGhpcy5hbGdvcml0aG09bjtsZXQgaT1lLmdldCgiTGVuZ3RoIik7aWYoIWkpaWYobjw9MylpPTQwO2Vsc2V7Y29uc3QgdD1lLmdldCgiQ0YiKSxyPWUuZ2V0KCJTdG1GIik7aWYodCBpbnN0YW5jZW9mIERpY3QmJnIgaW5zdGFuY2VvZiBOYW1lKXt0LnN1cHByZXNzRW5jcnlwdGlvbj0hMDtjb25zdCBlPXQuZ2V0KHIubmFtZSk7aT1lPy5nZXQoIkxlbmd0aCIpfHwxMjg7aTw0MCYmKGk8PD0zKX19aWYoIU51bWJlci5pc0ludGVnZXIoaSl8fGk8NDB8fGklOCE9MCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImludmFsaWQga2V5IGxlbmd0aCIpO2NvbnN0IHM9c3RyaW5nVG9CeXRlcyhlLmdldCgiTyIpKSxvPXN0cmluZ1RvQnl0ZXMoZS5nZXQoIlUiKSksYz1zLnN1YmFycmF5KDAsMzIpLGw9by5zdWJhcnJheSgwLDMyKSxoPWUuZ2V0KCJQIiksdT1lLmdldCgiUiIpLGQ9KDQ9PT1ufHw1PT09bikmJiExIT09ZS5nZXQoIkVuY3J5cHRNZXRhZGF0YSIpO3RoaXMuZW5jcnlwdE1ldGFkYXRhPWQ7Y29uc3QgZj1zdHJpbmdUb0J5dGVzKHQpO2xldCBnLHA7aWYocil7aWYoNj09PXUpdHJ5e3I9dXRmOFN0cmluZ1RvU3RyaW5nKHIpfWNhdGNoe3dhcm4oIkNpcGhlclRyYW5zZm9ybUZhY3Rvcnk6IFVuYWJsZSB0byBjb252ZXJ0IFVURjggZW5jb2RlZCBwYXNzd29yZC4iKX1nPXN0cmluZ1RvQnl0ZXMocil9aWYoNSE9PW4pcD10aGlzLiNVZShmLGcsYyxsLGgsdSxpLGQpO2Vsc2V7Y29uc3QgdD1zLnN1YmFycmF5KDMyLDQwKSxyPXMuc3ViYXJyYXkoNDAsNDgpLGE9by5zdWJhcnJheSgwLDQ4KSxuPW8uc3ViYXJyYXkoMzIsNDApLGk9by5zdWJhcnJheSg0MCw0OCksaD1zdHJpbmdUb0J5dGVzKGUuZ2V0KCJPRSIpKSxkPXN0cmluZ1RvQnl0ZXMoZS5nZXQoIlVFIikpLGY9c3RyaW5nVG9CeXRlcyhlLmdldCgiUGVybXMiKSk7cD10aGlzLiNqZSh1LGcsYyx0LHIsYSxsLG4saSxoLGQsZil9aWYoIXApe2lmKCFyKXRocm93IG5ldyBQYXNzd29yZEV4Y2VwdGlvbigiTm8gcGFzc3dvcmQgZ2l2ZW4iLFl0KTtjb25zdCBlPXRoaXMuI3FlKGcsYyx1LGkpO3A9dGhpcy4jVWUoZixlLGMsbCxoLHUsaSxkKX1pZighcCl0aHJvdyBuZXcgUGFzc3dvcmRFeGNlcHRpb24oIkluY29ycmVjdCBQYXNzd29yZCIsWnQpO2lmKDQ9PT1uJiZwLmxlbmd0aDwxNil7dGhpcy5lbmNyeXB0aW9uS2V5PW5ldyBVaW50OEFycmF5KDE2KTt0aGlzLmVuY3J5cHRpb25LZXkuc2V0KHApfWVsc2UgdGhpcy5lbmNyeXB0aW9uS2V5PXA7aWYobj49NCl7Y29uc3QgdD1lLmdldCgiQ0YiKTt0IGluc3RhbmNlb2YgRGljdCYmKHQuc3VwcHJlc3NFbmNyeXB0aW9uPSEwKTt0aGlzLmNmPXQ7dGhpcy5zdG1mPWUuZ2V0KCJTdG1GIil8fE5hbWUuZ2V0KCJJZGVudGl0eSIpO3RoaXMuc3RyZj1lLmdldCgiU3RyRiIpfHxOYW1lLmdldCgiSWRlbnRpdHkiKTt0aGlzLmVmZj1lLmdldCgiRUZGIil8fHRoaXMuc3RtZn19Y3JlYXRlQ2lwaGVyVHJhbnNmb3JtKGUsdCl7aWYoND09PXRoaXMuYWxnb3JpdGhtfHw1PT09dGhpcy5hbGdvcml0aG0pcmV0dXJuIG5ldyBDaXBoZXJUcmFuc2Zvcm0odGhpcy4jSGUodGhpcy5jZix0aGlzLnN0cmYsZSx0LHRoaXMuZW5jcnlwdGlvbktleSksdGhpcy4jSGUodGhpcy5jZix0aGlzLnN0bWYsZSx0LHRoaXMuZW5jcnlwdGlvbktleSkpO2NvbnN0IHI9dGhpcy4jWGUoZSx0LHRoaXMuZW5jcnlwdGlvbktleSwhMSksY2lwaGVyQ29uc3RydWN0b3I9ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEFSQ0ZvdXJDaXBoZXIocil9O3JldHVybiBuZXcgQ2lwaGVyVHJhbnNmb3JtKGNpcGhlckNvbnN0cnVjdG9yLGNpcGhlckNvbnN0cnVjdG9yKX19Y2xhc3MgWFJlZntjb25zdHJ1Y3RvcihlLHQpe3RoaXMuc3RyZWFtPWU7dGhpcy5wZGZNYW5hZ2VyPXQ7dGhpcy5lbnRyaWVzPVtdO3RoaXMuX3hyZWZTdG1zPW5ldyBTZXQ7dGhpcy5fY2FjaGVNYXA9bmV3IE1hcDt0aGlzLl9wZW5kaW5nUmVmcz1uZXcgUmVmU2V0O3RoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW09bnVsbDt0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW09bnVsbDt0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlPW51bGx9Z2V0TmV3UGVyc2lzdGVudFJlZihlKXtudWxsPT09dGhpcy5fbmV3UGVyc2lzdGVudFJlZk51bSYmKHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW09dGhpcy5lbnRyaWVzLmxlbmd0aHx8MSk7Y29uc3QgdD10aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtKys7dGhpcy5fY2FjaGVNYXAuc2V0KHQsZSk7cmV0dXJuIFJlZi5nZXQodCwwKX1nZXROZXdUZW1wb3JhcnlSZWYoKXtpZihudWxsPT09dGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtKXt0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW09dGhpcy5lbnRyaWVzLmxlbmd0aHx8MTtpZih0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtKXt0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlPW5ldyBNYXA7Zm9yKGxldCBlPXRoaXMuX25ld1RlbXBvcmFyeVJlZk51bTtlPHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW07ZSsrKXt0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlLnNldChlLHRoaXMuX2NhY2hlTWFwLmdldChlKSk7dGhpcy5fY2FjaGVNYXAuZGVsZXRlKGUpfX19cmV0dXJuIFJlZi5nZXQodGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtKyssMCl9cmVzZXROZXdUZW1wb3JhcnlSZWYoKXt0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW09bnVsbDtpZih0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlKWZvcihjb25zdFtlLHRdb2YgdGhpcy5fcGVyc2lzdGVudFJlZnNDYWNoZSl0aGlzLl9jYWNoZU1hcC5zZXQoZSx0KTt0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlPW51bGx9c2V0U3RhcnRYUmVmKGUpe3RoaXMuc3RhcnRYUmVmUXVldWU9W2VdfXBhcnNlKGU9ITEpe2xldCB0LHIsYTtpZihlKXt3YXJuKCJJbmRleGluZyBhbGwgUERGIG9iamVjdHMiKTt0PXRoaXMuaW5kZXhPYmplY3RzKCl9ZWxzZSB0PXRoaXMucmVhZFhSZWYoKTt0LmFzc2lnblhyZWYodGhpcyk7dGhpcy50cmFpbGVyPXQ7dHJ5e3I9dC5nZXQoIkVuY3J5cHQiKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiRW5jcnlwdCIgcmVmZXJlbmNlOiAiJHtlfSIuYCl9aWYociBpbnN0YW5jZW9mIERpY3Qpe2NvbnN0IGU9dC5nZXQoIklEIiksYT1lPy5sZW5ndGg/ZVswXToiIjtyLnN1cHByZXNzRW5jcnlwdGlvbj0hMDt0aGlzLmVuY3J5cHQ9bmV3IENpcGhlclRyYW5zZm9ybUZhY3RvcnkocixhLHRoaXMucGRmTWFuYWdlci5wYXNzd29yZCl9dHJ5e2E9dC5nZXQoIlJvb3QiKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTt3YXJuKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiUm9vdCIgcmVmZXJlbmNlOiAiJHtlfSIuYCl9aWYoYSBpbnN0YW5jZW9mIERpY3QpdHJ5e2lmKGEuZ2V0KCJQYWdlcyIpaW5zdGFuY2VvZiBEaWN0KXt0aGlzLnJvb3Q9YTtyZXR1cm59fWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO3dhcm4oYFhSZWYucGFyc2UgLSBJbnZhbGlkICJQYWdlcyIgcmVmZXJlbmNlOiAiJHtlfSIuYCl9aWYoIWUpdGhyb3cgbmV3IFhSZWZQYXJzZUV4Y2VwdGlvbjt0aHJvdyBuZXcgSW52YWxpZFBERkV4Y2VwdGlvbigiSW52YWxpZCBSb290IHJlZmVyZW5jZS4iKX1wcm9jZXNzWFJlZlRhYmxlKGUpeyJ0YWJsZVN0YXRlImluIHRoaXN8fCh0aGlzLnRhYmxlU3RhdGU9e2VudHJ5TnVtOjAsc3RyZWFtUG9zOmUubGV4ZXIuc3RyZWFtLnBvcyxwYXJzZXJCdWYxOmUuYnVmMSxwYXJzZXJCdWYyOmUuYnVmMn0pO2lmKCFpc0NtZCh0aGlzLnJlYWRYUmVmVGFibGUoZSksInRyYWlsZXIiKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogY291bGQgbm90IGZpbmQgdHJhaWxlciBkaWN0aW9uYXJ5Iik7bGV0IHQ9ZS5nZXRPYmooKTt0IGluc3RhbmNlb2YgRGljdHx8IXQuZGljdHx8KHQ9dC5kaWN0KTtpZighKHQgaW5zdGFuY2VvZiBEaWN0KSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiB0YWJsZTogY291bGQgbm90IHBhcnNlIHRyYWlsZXIgZGljdGlvbmFyeSIpO2RlbGV0ZSB0aGlzLnRhYmxlU3RhdGU7cmV0dXJuIHR9cmVhZFhSZWZUYWJsZShlKXtjb25zdCB0PWUubGV4ZXIuc3RyZWFtLHI9dGhpcy50YWJsZVN0YXRlO3QucG9zPXIuc3RyZWFtUG9zO2UuYnVmMT1yLnBhcnNlckJ1ZjE7ZS5idWYyPXIucGFyc2VyQnVmMjtsZXQgYTtmb3IoOzspe2lmKCEoImZpcnN0RW50cnlOdW0iaW4gcil8fCEoImVudHJ5Q291bnQiaW4gcikpe2lmKGlzQ21kKGE9ZS5nZXRPYmooKSwidHJhaWxlciIpKWJyZWFrO3IuZmlyc3RFbnRyeU51bT1hO3IuZW50cnlDb3VudD1lLmdldE9iaigpfWxldCBuPXIuZmlyc3RFbnRyeU51bTtjb25zdCBpPXIuZW50cnlDb3VudDtpZighTnVtYmVyLmlzSW50ZWdlcihuKXx8IU51bWJlci5pc0ludGVnZXIoaSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgdGFibGU6IHdyb25nIHR5cGVzIGluIHN1YnNlY3Rpb24gaGVhZGVyIik7Zm9yKGxldCBhPXIuZW50cnlOdW07YTxpO2ErKyl7ci5zdHJlYW1Qb3M9dC5wb3M7ci5lbnRyeU51bT1hO3IucGFyc2VyQnVmMT1lLmJ1ZjE7ci5wYXJzZXJCdWYyPWUuYnVmMjtjb25zdCBzPXt9O3Mub2Zmc2V0PWUuZ2V0T2JqKCk7cy5nZW49ZS5nZXRPYmooKTtjb25zdCBvPWUuZ2V0T2JqKCk7aWYobyBpbnN0YW5jZW9mIENtZClzd2l0Y2goby5jbWQpe2Nhc2UiZiI6cy5mcmVlPSEwO2JyZWFrO2Nhc2UibiI6cy51bmNvbXByZXNzZWQ9ITB9aWYoIU51bWJlci5pc0ludGVnZXIocy5vZmZzZXQpfHwhTnVtYmVyLmlzSW50ZWdlcihzLmdlbil8fCFzLmZyZWUmJiFzLnVuY29tcHJlc3NlZCl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZW50cnkgaW4gWFJlZiBzdWJzZWN0aW9uOiAke259LCAke2l9YCk7MD09PWEmJnMuZnJlZSYmMT09PW4mJihuPTApO3RoaXMuZW50cmllc1thK25dfHwodGhpcy5lbnRyaWVzW2Erbl09cyl9ci5lbnRyeU51bT0wO3Iuc3RyZWFtUG9zPXQucG9zO3IucGFyc2VyQnVmMT1lLmJ1ZjE7ci5wYXJzZXJCdWYyPWUuYnVmMjtkZWxldGUgci5maXJzdEVudHJ5TnVtO2RlbGV0ZSByLmVudHJ5Q291bnR9aWYodGhpcy5lbnRyaWVzWzBdJiYhdGhpcy5lbnRyaWVzWzBdLmZyZWUpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgdGFibGU6IHVuZXhwZWN0ZWQgZmlyc3Qgb2JqZWN0Iik7cmV0dXJuIGF9cHJvY2Vzc1hSZWZTdHJlYW0oZSl7aWYoISgic3RyZWFtU3RhdGUiaW4gdGhpcykpe2NvbnN0e2RpY3Q6dCxwb3M6cn09ZSxhPXQuZ2V0KCJXIiksbj10LmdldCgiSW5kZXgiKXx8WzAsdC5nZXQoIlNpemUiKV07dGhpcy5zdHJlYW1TdGF0ZT17ZW50cnlSYW5nZXM6bixieXRlV2lkdGhzOmEsZW50cnlOdW06MCxzdHJlYW1Qb3M6cn19dGhpcy5yZWFkWFJlZlN0cmVhbShlKTtkZWxldGUgdGhpcy5zdHJlYW1TdGF0ZTtyZXR1cm4gZS5kaWN0fXJlYWRYUmVmU3RyZWFtKGUpe2NvbnN0IHQ9dGhpcy5zdHJlYW1TdGF0ZTtlLnBvcz10LnN0cmVhbVBvcztjb25zdFtyLGEsbl09dC5ieXRlV2lkdGhzLGk9dC5lbnRyeVJhbmdlcztmb3IoO2kubGVuZ3RoPjA7KXtjb25zdFtzLG9dPWk7aWYoIU51bWJlci5pc0ludGVnZXIocyl8fCFOdW1iZXIuaXNJbnRlZ2VyKG8pKXRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBYUmVmIHJhbmdlIGZpZWxkczogJHtzfSwgJHtvfWApO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHIpfHwhTnVtYmVyLmlzSW50ZWdlcihhKXx8IU51bWJlci5pc0ludGVnZXIobikpdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgZW50cnkgZmllbGRzIGxlbmd0aDogJHtzfSwgJHtvfWApO2ZvcihsZXQgaT10LmVudHJ5TnVtO2k8bzsrK2kpe3QuZW50cnlOdW09aTt0LnN0cmVhbVBvcz1lLnBvcztsZXQgbz0wLGM9MCxsPTA7Zm9yKGxldCB0PTA7dDxyOysrdCl7Y29uc3QgdD1lLmdldEJ5dGUoKTtpZigtMT09PXQpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAndHlwZScuIik7bz1vPDw4fHR9MD09PXImJihvPTEpO2ZvcihsZXQgdD0wO3Q8YTsrK3Qpe2NvbnN0IHQ9ZS5nZXRCeXRlKCk7aWYoLTE9PT10KXRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIGJ5dGVXaWR0aHMgJ29mZnNldCcuIik7Yz1jPDw4fHR9Zm9yKGxldCB0PTA7dDxuOysrdCl7Y29uc3QgdD1lLmdldEJ5dGUoKTtpZigtMT09PXQpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAnZ2VuZXJhdGlvbicuIik7bD1sPDw4fHR9Y29uc3QgaD17fTtoLm9mZnNldD1jO2guZ2VuPWw7c3dpdGNoKG8pe2Nhc2UgMDpoLmZyZWU9ITA7YnJlYWs7Y2FzZSAxOmgudW5jb21wcmVzc2VkPSEwO2JyZWFrO2Nhc2UgMjpicmVhaztkZWZhdWx0OnRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBYUmVmIGVudHJ5IHR5cGU6ICR7b31gKX10aGlzLmVudHJpZXNbcytpXXx8KHRoaXMuZW50cmllc1tzK2ldPWgpfXQuZW50cnlOdW09MDt0LnN0cmVhbVBvcz1lLnBvcztpLnNwbGljZSgwLDIpfX1pbmRleE9iamVjdHMoKXtmdW5jdGlvbiByZWFkVG9rZW4oZSx0KXtsZXQgcj0iIixhPWVbdF07Zm9yKDsxMCE9PWEmJjEzIT09YSYmNjAhPT1hJiYhKCsrdD49ZS5sZW5ndGgpOyl7cis9U3RyaW5nLmZyb21DaGFyQ29kZShhKTthPWVbdF19cmV0dXJuIHJ9ZnVuY3Rpb24gc2tpcFVudGlsKGUsdCxyKXtjb25zdCBhPXIubGVuZ3RoLG49ZS5sZW5ndGg7bGV0IGk9MDtmb3IoO3Q8bjspe2xldCBuPTA7Zm9yKDtuPGEmJmVbdCtuXT09PXJbbl07KSsrbjtpZihuPj1hKWJyZWFrO3QrKztpKyt9cmV0dXJuIGl9Y29uc3QgZT0vXGIoZW5kb2JqfFxkK1xzK1xkK1xzK29ianx4cmVmfHRyYWlsZXJccyo8PClcYi9nLHQ9L1xiKHN0YXJ0eHJlZnxcZCtccytcZCtccytvYmopXGIvZyxyPS9eKFxkKylccysoXGQrKVxzK29ialxiLyxhPW5ldyBVaW50OEFycmF5KFsxMTYsMTE0LDk3LDEwNSwxMDgsMTAxLDExNF0pLG49bmV3IFVpbnQ4QXJyYXkoWzExNSwxMTYsOTcsMTE0LDExNiwxMjAsMTE0LDEwMSwxMDJdKSxpPW5ldyBVaW50OEFycmF5KFs0Nyw4OCw4MiwxMDEsMTAyXSk7dGhpcy5lbnRyaWVzLmxlbmd0aD0wO3RoaXMuX2NhY2hlTWFwLmNsZWFyKCk7Y29uc3Qgcz10aGlzLnN0cmVhbTtzLnBvcz0wO2NvbnN0IG89cy5nZXRCeXRlcygpLGM9Ynl0ZXNUb1N0cmluZyhvKSxsPW8ubGVuZ3RoO2xldCBoPXMuc3RhcnQ7Y29uc3QgdT1bXSxkPVtdO2Zvcig7aDxsOyl7bGV0IGY9b1toXTtpZig5PT09Znx8MTA9PT1mfHwxMz09PWZ8fDMyPT09Zil7KytoO2NvbnRpbnVlfWlmKDM3PT09Zil7ZG97KytoO2lmKGg+PWwpYnJlYWs7Zj1vW2hdfXdoaWxlKDEwIT09ZiYmMTMhPT1mKTtjb250aW51ZX1jb25zdCBnPXJlYWRUb2tlbihvLGgpO2xldCBwO2lmKGcuc3RhcnRzV2l0aCgieHJlZiIpJiYoND09PWcubGVuZ3RofHwvXHMvLnRlc3QoZ1s0XSkpKXtoKz1za2lwVW50aWwobyxoLGEpO3UucHVzaChoKTtoKz1za2lwVW50aWwobyxoLG4pfWVsc2UgaWYocD1yLmV4ZWMoZykpe2NvbnN0IHQ9MHxwWzFdLHI9MHxwWzJdLGE9aCtnLmxlbmd0aDtsZXQgbix1PSExO2lmKHRoaXMuZW50cmllc1t0XSl7aWYodGhpcy5lbnRyaWVzW3RdLmdlbj09PXIpdHJ5e25ldyBQYXJzZXIoe2xleGVyOm5ldyBMZXhlcihzLm1ha2VTdWJTdHJlYW0oYSkpfSkuZ2V0T2JqKCk7dT0hMH1jYXRjaChlKXtlIGluc3RhbmNlb2YgUGFyc2VyRU9GRXhjZXB0aW9uP3dhcm4oYGluZGV4T2JqZWN0cyAtLSBjaGVja2luZyBvYmplY3QgKCR7Z30pOiAiJHtlfSIuYCk6dT0hMH19ZWxzZSB1PSEwO3UmJih0aGlzLmVudHJpZXNbdF09e29mZnNldDpoLXMuc3RhcnQsZ2VuOnIsdW5jb21wcmVzc2VkOiEwfSk7ZS5sYXN0SW5kZXg9YTtjb25zdCBmPWUuZXhlYyhjKTtpZihmKXtuPWUubGFzdEluZGV4KzEtaDtpZigiZW5kb2JqIiE9PWZbMV0pe3dhcm4oYGluZGV4T2JqZWN0czogRm91bmQgIiR7ZlsxXX0iIGluc2lkZSBvZiBhbm90aGVyICJvYmoiLCBjYXVzZWQgYnkgbWlzc2luZyAiZW5kb2JqIiAtLSB0cnlpbmcgdG8gcmVjb3Zlci5gKTtuLT1mWzFdLmxlbmd0aCsxfX1lbHNlIG49bC1oO2NvbnN0IG09by5zdWJhcnJheShoLGgrbiksYj1za2lwVW50aWwobSwwLGkpO2lmKGI8biYmbVtiKzVdPDY0KXtkLnB1c2goaC1zLnN0YXJ0KTt0aGlzLl94cmVmU3Rtcy5hZGQoaC1zLnN0YXJ0KX1oKz1ufWVsc2UgaWYoZy5zdGFydHNXaXRoKCJ0cmFpbGVyIikmJig3PT09Zy5sZW5ndGh8fC9ccy8udGVzdChnWzddKSkpe3UucHVzaChoKTtjb25zdCBlPWgrZy5sZW5ndGg7bGV0IHI7dC5sYXN0SW5kZXg9ZTtjb25zdCBhPXQuZXhlYyhjKTtpZihhKXtyPXQubGFzdEluZGV4KzEtaDtpZigic3RhcnR4cmVmIiE9PWFbMV0pe3dhcm4oYGluZGV4T2JqZWN0czogRm91bmQgIiR7YVsxXX0iIGFmdGVyICJ0cmFpbGVyIiwgY2F1c2VkIGJ5IG1pc3NpbmcgInN0YXJ0eHJlZiIgLS0gdHJ5aW5nIHRvIHJlY292ZXIuYCk7ci09YVsxXS5sZW5ndGgrMX19ZWxzZSByPWwtaDtoKz1yfWVsc2UgaCs9Zy5sZW5ndGgrMX1mb3IoY29uc3QgZSBvZiBkKXt0aGlzLnN0YXJ0WFJlZlF1ZXVlLnB1c2goZSk7dGhpcy5yZWFkWFJlZighMCl9Y29uc3QgZj1bXTtsZXQgZyxwLG09ITE7Zm9yKGNvbnN0IGUgb2YgdSl7cy5wb3M9ZTtjb25zdCB0PW5ldyBQYXJzZXIoe2xleGVyOm5ldyBMZXhlcihzKSx4cmVmOnRoaXMsYWxsb3dTdHJlYW1zOiEwLHJlY292ZXJ5TW9kZTohMH0pO2lmKCFpc0NtZCh0LmdldE9iaigpLCJ0cmFpbGVyIikpY29udGludWU7Y29uc3Qgcj10LmdldE9iaigpO2lmKHIgaW5zdGFuY2VvZiBEaWN0KXtmLnB1c2gocik7ci5oYXMoIkVuY3J5cHQiKSYmKG09ITApfX1mb3IoY29uc3QgZSBvZlsuLi5mLCJnZW5GYWxsYmFjayIsLi4uZl0pe2lmKCJnZW5GYWxsYmFjayI9PT1lKXtpZighcClicmVhazt0aGlzLl9nZW5lcmF0aW9uRmFsbGJhY2s9ITA7Y29udGludWV9bGV0IHQ9ITE7dHJ5e2NvbnN0IHI9ZS5nZXQoIlJvb3QiKTtpZighKHIgaW5zdGFuY2VvZiBEaWN0KSljb250aW51ZTtjb25zdCBhPXIuZ2V0KCJQYWdlcyIpO2lmKCEoYSBpbnN0YW5jZW9mIERpY3QpKWNvbnRpbnVlO2NvbnN0IG49YS5nZXQoIkNvdW50Iik7TnVtYmVyLmlzSW50ZWdlcihuKSYmKHQ9ITApfWNhdGNoKGUpe3A9ZTtjb250aW51ZX1pZih0JiYoIW18fGUuaGFzKCJFbmNyeXB0IikpJiZlLmhhcygiSUQiKSlyZXR1cm4gZTtnPWV9aWYoZylyZXR1cm4gZztpZih0aGlzLnRvcERpY3QpcmV0dXJuIHRoaXMudG9wRGljdDtpZighZi5sZW5ndGgpZm9yKGNvbnN0IGUgaW4gdGhpcy5lbnRyaWVzKXtpZighT2JqZWN0Lmhhc093bih0aGlzLmVudHJpZXMsZSkpY29udGludWU7Y29uc3QgdD10aGlzLmVudHJpZXNbZV0scj1SZWYuZ2V0KHBhcnNlSW50KGUpLHQuZ2VuKTtsZXQgYTt0cnl7YT10aGlzLmZldGNoKHIpfWNhdGNoe2NvbnRpbnVlfWEgaW5zdGFuY2VvZiBCYXNlU3RyZWFtJiYoYT1hLmRpY3QpO2lmKGEgaW5zdGFuY2VvZiBEaWN0JiZhLmhhcygiUm9vdCIpKXJldHVybiBhfXRocm93IG5ldyBJbnZhbGlkUERGRXhjZXB0aW9uKCJJbnZhbGlkIFBERiBzdHJ1Y3R1cmUuIil9cmVhZFhSZWYoZT0hMSl7Y29uc3QgdD10aGlzLnN0cmVhbSxyPW5ldyBTZXQ7Zm9yKDt0aGlzLnN0YXJ0WFJlZlF1ZXVlLmxlbmd0aDspe3RyeXtjb25zdCBlPXRoaXMuc3RhcnRYUmVmUXVldWVbMF07aWYoci5oYXMoZSkpe3dhcm4oInJlYWRYUmVmIC0gc2tpcHBpbmcgWFJlZiB0YWJsZSBzaW5jZSBpdCB3YXMgYWxyZWFkeSBwYXJzZWQuIik7dGhpcy5zdGFydFhSZWZRdWV1ZS5zaGlmdCgpO2NvbnRpbnVlfXIuYWRkKGUpO3QucG9zPWUrdC5zdGFydDtjb25zdCBhPW5ldyBQYXJzZXIoe2xleGVyOm5ldyBMZXhlcih0KSx4cmVmOnRoaXMsYWxsb3dTdHJlYW1zOiEwfSk7bGV0IG4saT1hLmdldE9iaigpO2lmKGlzQ21kKGksInhyZWYiKSl7bj10aGlzLnByb2Nlc3NYUmVmVGFibGUoYSk7dGhpcy50b3BEaWN0fHwodGhpcy50b3BEaWN0PW4pO2k9bi5nZXQoIlhSZWZTdG0iKTtpZihOdW1iZXIuaXNJbnRlZ2VyKGkpJiYhdGhpcy5feHJlZlN0bXMuaGFzKGkpKXt0aGlzLl94cmVmU3Rtcy5hZGQoaSk7dGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKGkpfX1lbHNle2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGkpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHN0cmVhbSBoZWFkZXIiKTtpZighKE51bWJlci5pc0ludGVnZXIoYS5nZXRPYmooKSkmJmlzQ21kKGEuZ2V0T2JqKCksIm9iaiIpJiYoaT1hLmdldE9iaigpKWluc3RhbmNlb2YgQmFzZVN0cmVhbSkpdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgc3RyZWFtIik7bj10aGlzLnByb2Nlc3NYUmVmU3RyZWFtKGkpO3RoaXMudG9wRGljdHx8KHRoaXMudG9wRGljdD1uKTtpZighbil0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkZhaWxlZCB0byByZWFkIFhSZWYgc3RyZWFtIil9aT1uLmdldCgiUHJldiIpO051bWJlci5pc0ludGVnZXIoaSk/dGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKGkpOmkgaW5zdGFuY2VvZiBSZWYmJnRoaXMuc3RhcnRYUmVmUXVldWUucHVzaChpLm51bSl9Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKXRocm93IGU7aW5mbygiKHdoaWxlIHJlYWRpbmcgWFJlZik6ICIrZSl9dGhpcy5zdGFydFhSZWZRdWV1ZS5zaGlmdCgpfWlmKHRoaXMudG9wRGljdClyZXR1cm4gdGhpcy50b3BEaWN0O2lmKCFlKXRocm93IG5ldyBYUmVmUGFyc2VFeGNlcHRpb259Z2V0RW50cnkoZSl7Y29uc3QgdD10aGlzLmVudHJpZXNbZV07cmV0dXJuIHQmJiF0LmZyZWUmJnQub2Zmc2V0P3Q6bnVsbH1mZXRjaElmUmVmKGUsdD0hMSl7cmV0dXJuIGUgaW5zdGFuY2VvZiBSZWY/dGhpcy5mZXRjaChlLHQpOmV9ZmV0Y2goZSx0PSExKXtpZighKGUgaW5zdGFuY2VvZiBSZWYpKXRocm93IG5ldyBFcnJvcigicmVmIG9iamVjdCBpcyBub3QgYSByZWZlcmVuY2UiKTtjb25zdCByPWUubnVtLGE9dGhpcy5fY2FjaGVNYXAuZ2V0KHIpO2lmKHZvaWQgMCE9PWEpe2EgaW5zdGFuY2VvZiBEaWN0JiYhYS5vYmpJZCYmKGEub2JqSWQ9ZS50b1N0cmluZygpKTtyZXR1cm4gYX1sZXQgbj10aGlzLmdldEVudHJ5KHIpO2lmKG51bGw9PT1uKXJldHVybiBuO2lmKHRoaXMuX3BlbmRpbmdSZWZzLmhhcyhlKSl7dGhpcy5fcGVuZGluZ1JlZnMucmVtb3ZlKGUpO3dhcm4oYElnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtlfS5gKTtyZXR1cm4gaXJ9dGhpcy5fcGVuZGluZ1JlZnMucHV0KGUpO3RyeXtuPW4udW5jb21wcmVzc2VkP3RoaXMuZmV0Y2hVbmNvbXByZXNzZWQoZSxuLHQpOnRoaXMuZmV0Y2hDb21wcmVzc2VkKGUsbix0KTt0aGlzLl9wZW5kaW5nUmVmcy5yZW1vdmUoZSl9Y2F0Y2godCl7dGhpcy5fcGVuZGluZ1JlZnMucmVtb3ZlKGUpO3Rocm93IHR9biBpbnN0YW5jZW9mIERpY3Q/bi5vYmpJZD1lLnRvU3RyaW5nKCk6biBpbnN0YW5jZW9mIEJhc2VTdHJlYW0mJihuLmRpY3Qub2JqSWQ9ZS50b1N0cmluZygpKTtyZXR1cm4gbn1mZXRjaFVuY29tcHJlc3NlZChlLHQscj0hMSl7Y29uc3QgYT1lLmdlbjtsZXQgbj1lLm51bTtpZih0LmdlbiE9PWEpe2NvbnN0IGk9YEluY29uc2lzdGVudCBnZW5lcmF0aW9uIGluIFhSZWY6ICR7ZX1gO2lmKHRoaXMuX2dlbmVyYXRpb25GYWxsYmFjayYmdC5nZW48YSl7d2FybihpKTtyZXR1cm4gdGhpcy5mZXRjaFVuY29tcHJlc3NlZChSZWYuZ2V0KG4sdC5nZW4pLHQscil9dGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihpKX1jb25zdCBpPXRoaXMuc3RyZWFtLm1ha2VTdWJTdHJlYW0odC5vZmZzZXQrdGhpcy5zdHJlYW0uc3RhcnQpLHM9bmV3IFBhcnNlcih7bGV4ZXI6bmV3IExleGVyKGkpLHhyZWY6dGhpcyxhbGxvd1N0cmVhbXM6ITB9KSxvPXMuZ2V0T2JqKCksYz1zLmdldE9iaigpLGw9cy5nZXRPYmooKTtpZihvIT09bnx8YyE9PWF8fCEobCBpbnN0YW5jZW9mIENtZCkpdGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihgQmFkICh1bmNvbXByZXNzZWQpIFhSZWYgZW50cnk6ICR7ZX1gKTtpZigib2JqIiE9PWwuY21kKXtpZihsLmNtZC5zdGFydHNXaXRoKCJvYmoiKSl7bj1wYXJzZUludChsLmNtZC5zdWJzdHJpbmcoMyksMTApO2lmKCFOdW1iZXIuaXNOYU4obikpcmV0dXJuIG59dGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihgQmFkICh1bmNvbXByZXNzZWQpIFhSZWYgZW50cnk6ICR7ZX1gKX0odD10aGlzLmVuY3J5cHQmJiFyP3MuZ2V0T2JqKHRoaXMuZW5jcnlwdC5jcmVhdGVDaXBoZXJUcmFuc2Zvcm0obixhKSk6cy5nZXRPYmooKSlpbnN0YW5jZW9mIEJhc2VTdHJlYW18fHRoaXMuX2NhY2hlTWFwLnNldChuLHQpO3JldHVybiB0fWZldGNoQ29tcHJlc3NlZChlLHQscj0hMSl7Y29uc3QgYT10Lm9mZnNldCxuPXRoaXMuZmV0Y2goUmVmLmdldChhLDApKTtpZighKG4gaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImJhZCBPYmpTdG0gc3RyZWFtIik7Y29uc3QgaT1uLmRpY3QuZ2V0KCJGaXJzdCIpLHM9bi5kaWN0LmdldCgiTiIpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGkpfHwhTnVtYmVyLmlzSW50ZWdlcihzKSl0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImludmFsaWQgZmlyc3QgYW5kIG4gcGFyYW1ldGVycyBmb3IgT2JqU3RtIHN0cmVhbSIpO2xldCBvPW5ldyBQYXJzZXIoe2xleGVyOm5ldyBMZXhlcihuKSx4cmVmOnRoaXMsYWxsb3dTdHJlYW1zOiEwfSk7Y29uc3QgYz1uZXcgQXJyYXkocyksbD1uZXcgQXJyYXkocyk7Zm9yKGxldCBlPTA7ZTxzOysrZSl7Y29uc3QgdD1vLmdldE9iaigpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHQpKXRocm93IG5ldyBGb3JtYXRFcnJvcihgaW52YWxpZCBvYmplY3QgbnVtYmVyIGluIHRoZSBPYmpTdG0gc3RyZWFtOiAke3R9YCk7Y29uc3Qgcj1vLmdldE9iaigpO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHIpKXRocm93IG5ldyBGb3JtYXRFcnJvcihgaW52YWxpZCBvYmplY3Qgb2Zmc2V0IGluIHRoZSBPYmpTdG0gc3RyZWFtOiAke3J9YCk7Y1tlXT10O2NvbnN0IG49dGhpcy5nZXRFbnRyeSh0KTtuPy5vZmZzZXQ9PT1hJiZuLmdlbiE9PWUmJihuLmdlbj1lKTtsW2VdPXJ9Y29uc3QgaD0obi5zdGFydHx8MCkraSx1PW5ldyBBcnJheShzKTtmb3IobGV0IGU9MDtlPHM7KytlKXtjb25zdCB0PWU8cy0xP2xbZSsxXS1sW2VdOnZvaWQgMDtpZih0PDApdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIG9mZnNldCBpbiB0aGUgT2JqU3RtIHN0cmVhbS4iKTtvPW5ldyBQYXJzZXIoe2xleGVyOm5ldyBMZXhlcihuLm1ha2VTdWJTdHJlYW0oaCtsW2VdLHQsbi5kaWN0KSkseHJlZjp0aGlzLGFsbG93U3RyZWFtczohMH0pO2NvbnN0IHI9by5nZXRPYmooKTt1W2VdPXI7aWYociBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pY29udGludWU7Y29uc3QgaT1jW2VdLGQ9dGhpcy5lbnRyaWVzW2ldO2QmJmQub2Zmc2V0PT09YSYmZC5nZW49PT1lJiZ0aGlzLl9jYWNoZU1hcC5zZXQoaSxyKX1pZih2b2lkIDA9PT0odD11W3QuZ2VuXSkpdGhyb3cgbmV3IFhSZWZFbnRyeUV4Y2VwdGlvbihgQmFkIChjb21wcmVzc2VkKSBYUmVmIGVudHJ5OiAke2V9YCk7cmV0dXJuIHR9YXN5bmMgZmV0Y2hJZlJlZkFzeW5jKGUsdCl7cmV0dXJuIGUgaW5zdGFuY2VvZiBSZWY/dGhpcy5mZXRjaEFzeW5jKGUsdCk6ZX1hc3luYyBmZXRjaEFzeW5jKGUsdCl7dHJ5e3JldHVybiB0aGlzLmZldGNoKGUsdCl9Y2F0Y2gocil7aWYoIShyIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKXRocm93IHI7YXdhaXQgdGhpcy5wZGZNYW5hZ2VyLnJlcXVlc3RSYW5nZShyLmJlZ2luLHIuZW5kKTtyZXR1cm4gdGhpcy5mZXRjaEFzeW5jKGUsdCl9fWdldENhdGFsb2dPYmooKXtyZXR1cm4gdGhpcy5yb290fX1jb25zdCBpYz1bMCwwLDYxMiw3OTJdO2NsYXNzIFBhZ2V7I1dlPSExOyN6ZT1udWxsO2NvbnN0cnVjdG9yKHtwZGZNYW5hZ2VyOmUseHJlZjp0LHBhZ2VJbmRleDpyLHBhZ2VEaWN0OmEscmVmOm4sZ2xvYmFsSWRGYWN0b3J5OmksZm9udENhY2hlOnMsYnVpbHRJbkNNYXBDYWNoZTpvLHN0YW5kYXJkRm9udERhdGFDYWNoZTpjLGdsb2JhbENvbG9yU3BhY2VDYWNoZTpsLGdsb2JhbEltYWdlQ2FjaGU6aCxzeXN0ZW1Gb250Q2FjaGU6dSxub25CbGVuZE1vZGVzU2V0OmQseGZhRmFjdG9yeTpmfSl7dGhpcy5wZGZNYW5hZ2VyPWU7dGhpcy5wYWdlSW5kZXg9cjt0aGlzLnBhZ2VEaWN0PWE7dGhpcy54cmVmPXQ7dGhpcy5yZWY9bjt0aGlzLmZvbnRDYWNoZT1zO3RoaXMuYnVpbHRJbkNNYXBDYWNoZT1vO3RoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlPWM7dGhpcy5nbG9iYWxDb2xvclNwYWNlQ2FjaGU9bDt0aGlzLmdsb2JhbEltYWdlQ2FjaGU9aDt0aGlzLnN5c3RlbUZvbnRDYWNoZT11O3RoaXMubm9uQmxlbmRNb2Rlc1NldD1kO3RoaXMuZXZhbHVhdG9yT3B0aW9ucz1lLmV2YWx1YXRvck9wdGlvbnM7dGhpcy54ZmFGYWN0b3J5PWY7Y29uc3QgZz17b2JqOjB9O3RoaXMuX2xvY2FsSWRGYWN0b3J5PWNsYXNzIGV4dGVuZHMgaXtzdGF0aWMgY3JlYXRlT2JqSWQoKXtyZXR1cm5gcCR7cn1fJHsrK2cub2JqfWB9c3RhdGljIGdldFBhZ2VPYmpJZCgpe3JldHVybmBwJHtuLnRvU3RyaW5nKCl9YH19fSNHZShlKXtyZXR1cm4gbmV3IFBhcnRpYWxFdmFsdWF0b3Ioe3hyZWY6dGhpcy54cmVmLGhhbmRsZXI6ZSxwYWdlSW5kZXg6dGhpcy5wYWdlSW5kZXgsaWRGYWN0b3J5OnRoaXMuX2xvY2FsSWRGYWN0b3J5LGZvbnRDYWNoZTp0aGlzLmZvbnRDYWNoZSxidWlsdEluQ01hcENhY2hlOnRoaXMuYnVpbHRJbkNNYXBDYWNoZSxzdGFuZGFyZEZvbnREYXRhQ2FjaGU6dGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUsZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOnRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLGdsb2JhbEltYWdlQ2FjaGU6dGhpcy5nbG9iYWxJbWFnZUNhY2hlLHN5c3RlbUZvbnRDYWNoZTp0aGlzLnN5c3RlbUZvbnRDYWNoZSxvcHRpb25zOnRoaXMuZXZhbHVhdG9yT3B0aW9uc30pfSMkZShlLHQ9ITEpe2NvbnN0IHI9Z2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7ZGljdDp0aGlzLnBhZ2VEaWN0LGtleTplLGdldEFycmF5OnQsc3RvcFdoZW5Gb3VuZDohMX0pO3JldHVybiBBcnJheS5pc0FycmF5KHIpPzEhPT1yLmxlbmd0aCYmclswXWluc3RhbmNlb2YgRGljdD9EaWN0Lm1lcmdlKHt4cmVmOnRoaXMueHJlZixkaWN0QXJyYXk6cn0pOnJbMF06cn1nZXQgY29udGVudCgpe3JldHVybiB0aGlzLnBhZ2VEaWN0LmdldEFycmF5KCJDb250ZW50cyIpfWdldCByZXNvdXJjZXMoKXtjb25zdCBlPXRoaXMuIyRlKCJSZXNvdXJjZXMiKTtyZXR1cm4gc2hhZG93KHRoaXMsInJlc291cmNlcyIsZSBpbnN0YW5jZW9mIERpY3Q/ZTpEaWN0LmVtcHR5KX0jVmUoZSl7aWYodGhpcy54ZmFEYXRhKXJldHVybiB0aGlzLnhmYURhdGEuYmJveDtjb25zdCB0PWxvb2t1cE5vcm1hbFJlY3QodGhpcy4jJGUoZSwhMCksbnVsbCk7aWYodCl7aWYodFsyXS10WzBdPjAmJnRbM10tdFsxXT4wKXJldHVybiB0O3dhcm4oYEVtcHR5LCBvciBpbnZhbGlkLCAvJHtlfSBlbnRyeS5gKX1yZXR1cm4gbnVsbH1nZXQgbWVkaWFCb3goKXtyZXR1cm4gc2hhZG93KHRoaXMsIm1lZGlhQm94Iix0aGlzLiNWZSgiTWVkaWFCb3giKXx8aWMpfWdldCBjcm9wQm94KCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJjcm9wQm94Iix0aGlzLiNWZSgiQ3JvcEJveCIpfHx0aGlzLm1lZGlhQm94KX1nZXQgdXNlclVuaXQoKXtjb25zdCBlPXRoaXMucGFnZURpY3QuZ2V0KCJVc2VyVW5pdCIpO3JldHVybiBzaGFkb3codGhpcywidXNlclVuaXQiLCJudW1iZXIiPT10eXBlb2YgZSYmZT4wP2U6MSl9Z2V0IHZpZXcoKXtjb25zdHtjcm9wQm94OmUsbWVkaWFCb3g6dH09dGhpcztpZihlIT09dCYmIWlzQXJyYXlFcXVhbChlLHQpKXtjb25zdCByPVV0aWwuaW50ZXJzZWN0KGUsdCk7aWYociYmclsyXS1yWzBdPjAmJnJbM10tclsxXT4wKXJldHVybiBzaGFkb3codGhpcywidmlldyIscik7d2FybigiRW1wdHkgL0Nyb3BCb3ggYW5kIC9NZWRpYUJveCBpbnRlcnNlY3Rpb24uIil9cmV0dXJuIHNoYWRvdyh0aGlzLCJ2aWV3Iix0KX1nZXQgcm90YXRlKCl7bGV0IGU9dGhpcy4jJGUoIlJvdGF0ZSIpfHwwO2UlOTAhPTA/ZT0wOmU+PTM2MD9lJT0zNjA6ZTwwJiYoZT0oZSUzNjArMzYwKSUzNjApO3JldHVybiBzaGFkb3codGhpcywicm90YXRlIixlKX0jS2UoZSx0KXtpZighdGhpcy5ldmFsdWF0b3JPcHRpb25zLmlnbm9yZUVycm9ycyl0aHJvdyBlO3dhcm4oYGdldENvbnRlbnRTdHJlYW0gLSBpZ25vcmluZyBzdWItc3RyZWFtICgke3R9KTogIiR7ZX0iLmApfWFzeW5jIGdldENvbnRlbnRTdHJlYW0oKXtjb25zdCBlPWF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywiY29udGVudCIpO3JldHVybiBlIGluc3RhbmNlb2YgQmFzZVN0cmVhbT9lOkFycmF5LmlzQXJyYXkoZSk/bmV3IFN0cmVhbXNTZXF1ZW5jZVN0cmVhbShlLHRoaXMuI0tlLmJpbmQodGhpcykpOm5ldyBOdWxsU3RyZWFtfWdldCB4ZmFEYXRhKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJ4ZmFEYXRhIix0aGlzLnhmYUZhY3Rvcnk/e2Jib3g6dGhpcy54ZmFGYWN0b3J5LmdldEJvdW5kaW5nQm94KHRoaXMucGFnZUluZGV4KX06bnVsbCl9YXN5bmMjSmUoZSx0LHIpe2NvbnN0IGE9W107Zm9yKGNvbnN0IG4gb2YgZSlpZihuLmlkKXtjb25zdCBlPVJlZi5mcm9tU3RyaW5nKG4uaWQpO2lmKCFlKXt3YXJuKGBBIG5vbi1saW5rZWQgYW5ub3RhdGlvbiBjYW5ub3QgYmUgbW9kaWZpZWQ6ICR7bi5pZH1gKTtjb250aW51ZX1pZihuLmRlbGV0ZWQpe3QucHV0KGUsZSk7aWYobi5wb3B1cFJlZil7Y29uc3QgZT1SZWYuZnJvbVN0cmluZyhuLnBvcHVwUmVmKTtlJiZ0LnB1dChlLGUpfWNvbnRpbnVlfWlmKG4ucG9wdXA/LmRlbGV0ZWQpe2NvbnN0IGU9UmVmLmZyb21TdHJpbmcobi5wb3B1cFJlZik7ZSYmdC5wdXQoZSxlKX1yPy5wdXQoZSk7bi5yZWY9ZTthLnB1c2godGhpcy54cmVmLmZldGNoQXN5bmMoZSkudGhlbihlPT57ZSBpbnN0YW5jZW9mIERpY3QmJihuLm9sZEFubm90YXRpb249ZS5jbG9uZSgpKX0sKCk9Pnt3YXJuKGBDYW5ub3QgZmV0Y2ggXGBvbGRBbm5vdGF0aW9uXGAgZm9yOiAke2V9LmApfSkpO2RlbGV0ZSBuLmlkfWF3YWl0IFByb21pc2UuYWxsKGEpfWFzeW5jIHNhdmVOZXdBbm5vdGF0aW9ucyhlLHQscixhLG4pe2lmKHRoaXMueGZhRmFjdG9yeSl0aHJvdyBuZXcgRXJyb3IoIlhGQTogQ2Fubm90IHNhdmUgbmV3IGFubm90YXRpb25zLiIpO2NvbnN0IGk9dGhpcy4jR2UoZSkscz1uZXcgUmVmU2V0Q2FjaGUsbz1uZXcgUmVmU2V0O2F3YWl0IHRoaXMuI0plKHIscyxvKTtjb25zdCBjPXRoaXMucGFnZURpY3QsbD10aGlzLmFubm90YXRpb25zLmZpbHRlcihlPT4hKGUgaW5zdGFuY2VvZiBSZWYmJnMuaGFzKGUpKSksaD1hd2FpdCBBbm5vdGF0aW9uRmFjdG9yeS5zYXZlTmV3QW5ub3RhdGlvbnMoaSx0LHIsYSxuKTtmb3IoY29uc3R7cmVmOmV9b2YgaC5hbm5vdGF0aW9ucyllIGluc3RhbmNlb2YgUmVmJiYhby5oYXMoZSkmJmwucHVzaChlKTtjb25zdCB1PWMuY2xvbmUoKTt1LnNldCgiQW5ub3RzIixsKTtuLnB1dCh0aGlzLnJlZix7ZGF0YTp1fSk7Zm9yKGNvbnN0IGUgb2YgcyluLnB1dChlLHtkYXRhOm51bGx9KX1hc3luYyBzYXZlKGUsdCxyLGEpe2NvbnN0IG49dGhpcy4jR2UoZSksaT1hd2FpdCB0aGlzLl9wYXJzZWRBbm5vdGF0aW9ucyxzPVtdO2Zvcihjb25zdCBlIG9mIGkpcy5wdXNoKGUuc2F2ZShuLHQscixhKS5jYXRjaChmdW5jdGlvbihlKXt3YXJuKGBzYXZlIC0gaWdub3JpbmcgYW5ub3RhdGlvbiBkYXRhIGR1cmluZyAiJHt0Lm5hbWV9IiB0YXNrOiAiJHtlfSIuYCk7cmV0dXJuIG51bGx9KSk7cmV0dXJuIFByb21pc2UuYWxsKHMpfWFzeW5jIGxvYWRSZXNvdXJjZXMoZSl7YXdhaXQodGhpcy4jemU/Pz10aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsInJlc291cmNlcyIpKTthd2FpdCBPYmplY3RMb2FkZXIubG9hZCh0aGlzLnJlc291cmNlcyxlLHRoaXMueHJlZil9YXN5bmMjWWUoZSx0KXtjb25zdCByPWU/LmdldCgiUmVzb3VyY2VzIik7aWYoIShyIGluc3RhbmNlb2YgRGljdCYmci5zaXplKSlyZXR1cm4gdGhpcy5yZXNvdXJjZXM7YXdhaXQgT2JqZWN0TG9hZGVyLmxvYWQocix0LHRoaXMueHJlZik7cmV0dXJuIERpY3QubWVyZ2Uoe3hyZWY6dGhpcy54cmVmLGRpY3RBcnJheTpbcix0aGlzLnJlc291cmNlc10sbWVyZ2VTdWJEaWN0czohMH0pfWFzeW5jIGdldE9wZXJhdG9yTGlzdCh7aGFuZGxlcjplLHNpbms6dCx0YXNrOnIsaW50ZW50OmEsY2FjaGVLZXk6bixhbm5vdGF0aW9uU3RvcmFnZTppPW51bGwsbW9kaWZpZWRJZHM6cz1udWxsfSl7Y29uc3QgaD10aGlzLmdldENvbnRlbnRTdHJlYW0oKSxnPXRoaXMubG9hZFJlc291cmNlcyhnciksbT10aGlzLiNHZShlKSxiPXRoaXMueGZhRmFjdG9yeT9udWxsOmdldE5ld0Fubm90YXRpb25zTWFwKGkpLHk9Yj8uZ2V0KHRoaXMucGFnZUluZGV4KTtsZXQgdz1Qcm9taXNlLnJlc29sdmUobnVsbCkseD1udWxsO2lmKHkpe2NvbnN0IGU9dGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiYW5ub3RhdGlvbkdsb2JhbHMiKTtsZXQgdDtjb25zdCBhPW5ldyBTZXQ7Zm9yKGNvbnN0e2JpdG1hcElkOmUsYml0bWFwOnR9b2YgeSkhZXx8dHx8YS5oYXMoZSl8fGEuYWRkKGUpO2NvbnN0e2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOm59PXRoaXMuZXZhbHVhdG9yT3B0aW9ucztpZihhLnNpemU+MCl7Y29uc3QgZT15LnNsaWNlKCk7Zm9yKGNvbnN0W3Qscl1vZiBpKXQuc3RhcnRzV2l0aChwKSYmci5iaXRtYXAmJmEuaGFzKHIuYml0bWFwSWQpJiZlLnB1c2gocik7dD1Bbm5vdGF0aW9uRmFjdG9yeS5nZW5lcmF0ZUltYWdlcyhlLHRoaXMueHJlZixuKX1lbHNlIHQ9QW5ub3RhdGlvbkZhY3RvcnkuZ2VuZXJhdGVJbWFnZXMoeSx0aGlzLnhyZWYsbik7eD1uZXcgUmVmU2V0O3c9UHJvbWlzZS5hbGwoW2UsdGhpcy4jSmUoeSx4LG51bGwpXSkudGhlbigoW2VdKT0+ZT9Bbm5vdGF0aW9uRmFjdG9yeS5wcmludE5ld0Fubm90YXRpb25zKGUsbSxyLHksdCk6bnVsbCl9Y29uc3QgUz1Qcm9taXNlLmFsbChbaCxnXSkudGhlbihhc3luYyhbaV0pPT57Y29uc3Qgcz1hd2FpdCB0aGlzLiNZZShpLmRpY3QsZ3IpLG89bmV3IE9wZXJhdG9yTGlzdChhLHQpO2Uuc2VuZCgiU3RhcnRSZW5kZXJQYWdlIix7dHJhbnNwYXJlbmN5Om0uaGFzQmxlbmRNb2RlcyhzLHRoaXMubm9uQmxlbmRNb2Rlc1NldCkscGFnZUluZGV4OnRoaXMucGFnZUluZGV4LGNhY2hlS2V5Om59KTthd2FpdCBtLmdldE9wZXJhdG9yTGlzdCh7c3RyZWFtOmksdGFzazpyLHJlc291cmNlczpzLG9wZXJhdG9yTGlzdDpvfSk7cmV0dXJuIG99KTtsZXRbayxDLHZdPWF3YWl0IFByb21pc2UuYWxsKFtTLHRoaXMuX3BhcnNlZEFubm90YXRpb25zLHddKTtpZih2KXtDPUMuZmlsdGVyKGU9PiEoZS5yZWYmJnguaGFzKGUucmVmKSkpO2ZvcihsZXQgZT0wLHQ9di5sZW5ndGg7ZTx0O2UrKyl7Y29uc3Qgcj12W2VdO2lmKHIucmVmVG9SZXBsYWNlKXtjb25zdCBhPUMuZmluZEluZGV4KGU9PmUucmVmJiZpc1JlZnNFcXVhbChlLnJlZixyLnJlZlRvUmVwbGFjZSkpO2lmKGE+PTApe0Muc3BsaWNlKGEsMSxyKTt2LnNwbGljZShlLS0sMSk7dC0tfX19Qz1DLmNvbmNhdCh2KX1pZigwPT09Qy5sZW5ndGh8fGEmZCl7ay5mbHVzaCghMCk7cmV0dXJue2xlbmd0aDprLnRvdGFsTGVuZ3RofX1jb25zdCBUPSEhKGEmdSksTz0hIShhJmYpLE09ISEoYSZvKSxEPSEhKGEmYyksUj0hIShhJmwpLEU9W107Zm9yKGNvbnN0IGUgb2YgQykoTXx8RCYmZS5tdXN0QmVWaWV3ZWQoaSxUKSYmZS5tdXN0QmVWaWV3ZWRXaGVuRWRpdGluZyhPLHMpfHxSJiZlLm11c3RCZVByaW50ZWQoaSkpJiZFLnB1c2goZS5nZXRPcGVyYXRvckxpc3QobSxyLGEsaSkuY2F0Y2goZnVuY3Rpb24oZSl7d2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgYW5ub3RhdGlvbiBkYXRhIGR1cmluZyAiJHtyLm5hbWV9IiB0YXNrOiAiJHtlfSIuYCk7cmV0dXJue29wTGlzdDpudWxsLHNlcGFyYXRlRm9ybTohMSxzZXBhcmF0ZUNhbnZhczohMX19KSk7Y29uc3QgTj1hd2FpdCBQcm9taXNlLmFsbChFKTtsZXQgXz0hMSxMPSExO2Zvcihjb25zdHtvcExpc3Q6ZSxzZXBhcmF0ZUZvcm06dCxzZXBhcmF0ZUNhbnZhczpyfW9mIE4pe2suYWRkT3BMaXN0KGUpO198fD10O0x8fD1yfWsuZmx1c2goITAse2Zvcm06XyxjYW52YXM6TH0pO3JldHVybntsZW5ndGg6ay50b3RhbExlbmd0aH19YXN5bmMgZXh0cmFjdFRleHRDb250ZW50KHtoYW5kbGVyOmUsdGFzazp0LGluY2x1ZGVNYXJrZWRDb250ZW50OnIsZGlzYWJsZU5vcm1hbGl6YXRpb246YSxzaW5rOm4saW50ZXJzZWN0b3I6aT1udWxsfSl7Y29uc3Qgcz10aGlzLmdldENvbnRlbnRTdHJlYW0oKSxvPXRoaXMubG9hZFJlc291cmNlcyhwciksYz10aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygibGFuZyIpLFtsLCxoXT1hd2FpdCBQcm9taXNlLmFsbChbcyxvLGNdKSx1PWF3YWl0IHRoaXMuI1llKGwuZGljdCxwcik7cmV0dXJuIHRoaXMuI0dlKGUpLmdldFRleHRDb250ZW50KHtzdHJlYW06bCx0YXNrOnQscmVzb3VyY2VzOnUsaW5jbHVkZU1hcmtlZENvbnRlbnQ6cixkaXNhYmxlTm9ybWFsaXphdGlvbjphLHNpbms6bix2aWV3Qm94OnRoaXMudmlldyxsYW5nOmgsaW50ZXJzZWN0b3I6aX0pfWFzeW5jIGdldFN0cnVjdFRyZWUoKXtjb25zdCBlPWF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJzdHJ1Y3RUcmVlUm9vdCIpO2lmKCFlKXJldHVybiBudWxsO2F3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zO3RyeXtjb25zdCB0PWF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywiX3BhcnNlU3RydWN0VHJlZSIsW2VdKTtyZXR1cm4gYXdhaXQgdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0LCJzZXJpYWxpemFibGUiKX1jYXRjaChlKXt3YXJuKGBnZXRTdHJ1Y3RUcmVlOiAiJHtlfSIuYCk7cmV0dXJuIG51bGx9fV9wYXJzZVN0cnVjdFRyZWUoZSl7Y29uc3QgdD1uZXcgU3RydWN0VHJlZVBhZ2UoZSx0aGlzLnBhZ2VEaWN0KTt0LnBhcnNlKHRoaXMucmVmKTtyZXR1cm4gdH1hc3luYyBnZXRBbm5vdGF0aW9uc0RhdGEoZSx0LHIpe2NvbnN0IGE9YXdhaXQgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnM7aWYoMD09PWEubGVuZ3RoKXJldHVybiBhO2NvbnN0IG49W10saT1bXTtsZXQgcztjb25zdCBoPSEhKHImbyksdT0hIShyJmMpLGQ9ISEociZsKSxmPVtdO2Zvcihjb25zdCByIG9mIGEpe2NvbnN0IGE9aHx8dSYmci52aWV3YWJsZTsoYXx8ZCYmci5wcmludGFibGUpJiZuLnB1c2goci5kYXRhKTtpZihyLmhhc1RleHRDb250ZW50JiZhKXtzPz89dGhpcy4jR2UoZSk7aS5wdXNoKHIuZXh0cmFjdFRleHRDb250ZW50KHMsdCxbLTEvMCwtMS8wLDEvMCwxLzBdKS5jYXRjaChmdW5jdGlvbihlKXt3YXJuKGBnZXRBbm5vdGF0aW9uc0RhdGEgLSBpZ25vcmluZyB0ZXh0Q29udGVudCBkdXJpbmcgIiR7dC5uYW1lfSIgdGFzazogIiR7ZX0iLmApfSkpfWVsc2Ugci5vdmVybGF5c1RleHRDb250ZW50JiZhJiZmLnB1c2gocil9aWYoZi5sZW5ndGg+MCl7Y29uc3Qgcj1uZXcgSW50ZXJzZWN0b3IoZik7aS5wdXNoKHRoaXMuZXh0cmFjdFRleHRDb250ZW50KHtoYW5kbGVyOmUsdGFzazp0LGluY2x1ZGVNYXJrZWRDb250ZW50OiExLGRpc2FibGVOb3JtYWxpemF0aW9uOiExLHNpbms6bnVsbCx2aWV3Qm94OnRoaXMudmlldyxsYW5nOm51bGwsaW50ZXJzZWN0b3I6cn0pLnRoZW4oKCk9PntyLnNldFRleHQoKX0pKX1hd2FpdCBQcm9taXNlLmFsbChpKTtyZXR1cm4gbn1nZXQgYW5ub3RhdGlvbnMoKXtjb25zdCBlPXRoaXMuIyRlKCJBbm5vdHMiKTtyZXR1cm4gc2hhZG93KHRoaXMsImFubm90YXRpb25zIixBcnJheS5pc0FycmF5KGUpP2U6W10pfWdldCBfcGFyc2VkQW5ub3RhdGlvbnMoKXtjb25zdCBlPXRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywiYW5ub3RhdGlvbnMiKS50aGVuKGFzeW5jIGU9PntpZigwPT09ZS5sZW5ndGgpcmV0dXJuIGU7Y29uc3RbdCxyXT1hd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiYW5ub3RhdGlvbkdsb2JhbHMiKSx0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmaWVsZE9iamVjdHMiKV0pO2lmKCF0KXJldHVybltdO2NvbnN0IGE9cj8ub3JwaGFuRmllbGRzLG49W107Zm9yKGNvbnN0IHIgb2YgZSluLnB1c2goQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlKHRoaXMueHJlZixyLHQsdGhpcy5fbG9jYWxJZEZhY3RvcnksITEsYSxudWxsLHRoaXMucmVmKS5jYXRjaChmdW5jdGlvbihlKXt3YXJuKGBfcGFyc2VkQW5ub3RhdGlvbnM6ICIke2V9Ii5gKTtyZXR1cm4gbnVsbH0pKTtjb25zdCBpPVtdO2xldCBzLG87Zm9yKGNvbnN0IGUgb2YgYXdhaXQgUHJvbWlzZS5hbGwobikpZSYmKGUgaW5zdGFuY2VvZiBXaWRnZXRBbm5vdGF0aW9uPyhvfHw9W10pLnB1c2goZSk6ZSBpbnN0YW5jZW9mIFBvcHVwQW5ub3RhdGlvbj8oc3x8PVtdKS5wdXNoKGUpOmkucHVzaChlKSk7byYmaS5wdXNoKC4uLm8pO3MmJmkucHVzaCguLi5zKTtyZXR1cm4gaX0pO3RoaXMuI1dlPSEwO3JldHVybiBzaGFkb3codGhpcywiX3BhcnNlZEFubm90YXRpb25zIixlKX1nZXQganNBY3Rpb25zKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJqc0FjdGlvbnMiLGNvbGxlY3RBY3Rpb25zKHRoaXMueHJlZix0aGlzLnBhZ2VEaWN0LHNlKSl9YXN5bmMgY29sbGVjdEFubm90YXRpb25zQnlUeXBlKGUsdCxyLGEsbil7Y29uc3R7cGFnZUluZGV4Oml9PXRoaXM7aWYodGhpcy4jV2Upe2NvbnN0IGU9YXdhaXQgdGhpcy5fcGFyc2VkQW5ub3RhdGlvbnM7Zm9yKGNvbnN0e2RhdGE6dH1vZiBlKWlmKCFyfHxyLmhhcyh0LmFubm90YXRpb25UeXBlKSl7dC5wYWdlSW5kZXg9aTthLnB1c2goUHJvbWlzZS5yZXNvbHZlKHQpKX1yZXR1cm59Y29uc3Qgcz1hd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsImFubm90YXRpb25zIik7Zm9yKGNvbnN0IG8gb2YgcylhLnB1c2goQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlKHRoaXMueHJlZixvLG4sdGhpcy5fbG9jYWxJZEZhY3RvcnksITEsbnVsbCxyLHRoaXMucmVmKS50aGVuKGFzeW5jIHI9PntpZighcilyZXR1cm4gbnVsbDtyLmRhdGEucGFnZUluZGV4PWk7aWYoci5oYXNUZXh0Q29udGVudCYmci52aWV3YWJsZSl7Y29uc3QgYT10aGlzLiNHZShlKTthd2FpdCByLmV4dHJhY3RUZXh0Q29udGVudChhLHQsWy0xLzAsLTEvMCwxLzAsMS8wXSl9cmV0dXJuIHIuZGF0YX0pLmNhdGNoKGZ1bmN0aW9uKGUpe3dhcm4oYGNvbGxlY3RBbm5vdGF0aW9uc0J5VHlwZTogIiR7ZX0iLmApO3JldHVybiBudWxsfSkpfX1jb25zdCBzYz1uZXcgVWludDhBcnJheShbMzcsODAsNjgsNzAsNDVdKSxvYz1uZXcgVWludDhBcnJheShbMTE1LDExNiw5NywxMTQsMTE2LDEyMCwxMTQsMTAxLDEwMl0pLGNjPW5ldyBVaW50OEFycmF5KFsxMDEsMTEwLDEwMCwxMTEsOTgsMTA2XSk7ZnVuY3Rpb24gZmluZChlLHQscj0xMDI0LGE9ITEpe2NvbnN0IG49dC5sZW5ndGgsaT1lLnBlZWtCeXRlcyhyKSxzPWkubGVuZ3RoLW47aWYoczw9MClyZXR1cm4hMTtpZihhKXtjb25zdCByPW4tMTtsZXQgYT1pLmxlbmd0aC0xO2Zvcig7YT49cjspe2xldCBzPTA7Zm9yKDtzPG4mJmlbYS1zXT09PXRbci1zXTspcysrO2lmKHM+PW4pe2UucG9zKz1hLXI7cmV0dXJuITB9YS0tfX1lbHNle2xldCByPTA7Zm9yKDtyPD1zOyl7bGV0IGE9MDtmb3IoO2E8biYmaVtyK2FdPT09dFthXTspYSsrO2lmKGE+PW4pe2UucG9zKz1yO3JldHVybiEwfXIrK319cmV0dXJuITF9Y2xhc3MgUERGRG9jdW1lbnR7I1plPW5ldyBNYXA7I1FlPW51bGw7Y29uc3RydWN0b3IoZSx0KXtpZih0Lmxlbmd0aDw9MCl0aHJvdyBuZXcgSW52YWxpZFBERkV4Y2VwdGlvbigiVGhlIFBERiBmaWxlIGlzIGVtcHR5LCBpLmUuIGl0cyBzaXplIGlzIHplcm8gYnl0ZXMuIik7dGhpcy5wZGZNYW5hZ2VyPWU7dGhpcy5zdHJlYW09dDt0aGlzLnhyZWY9bmV3IFhSZWYodCxlKTtjb25zdCByPXtmb250OjB9O3RoaXMuX2dsb2JhbElkRmFjdG9yeT1jbGFzc3tzdGF0aWMgZ2V0RG9jSWQoKXtyZXR1cm5gZ18ke2UuZG9jSWR9YH1zdGF0aWMgY3JlYXRlRm9udElkKCl7cmV0dXJuImYiKyArK3IuZm9udH1zdGF0aWMgY3JlYXRlT2JqSWQoKXt1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBjcmVhdGVPYmpJZGAgY2FsbGVkLiIpfXN0YXRpYyBnZXRQYWdlT2JqSWQoKXt1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRQYWdlT2JqSWRgIGNhbGxlZC4iKX19fXBhcnNlKGUpe3RoaXMueHJlZi5wYXJzZShlKTt0aGlzLmNhdGFsb2c9bmV3IENhdGFsb2codGhpcy5wZGZNYW5hZ2VyLHRoaXMueHJlZil9Z2V0IGxpbmVhcml6YXRpb24oKXtsZXQgZT1udWxsO3RyeXtlPUxpbmVhcml6YXRpb24uY3JlYXRlKHRoaXMuc3RyZWFtKX1jYXRjaChlKXtpZihlIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pdGhyb3cgZTtpbmZvKGUpfXJldHVybiBzaGFkb3codGhpcywibGluZWFyaXphdGlvbiIsZSl9Z2V0IHN0YXJ0WFJlZigpe2NvbnN0IGU9dGhpcy5zdHJlYW07bGV0IHQ9MDtpZih0aGlzLmxpbmVhcml6YXRpb24pe2UucmVzZXQoKTtpZihmaW5kKGUsY2MpKXtlLnNraXAoNik7bGV0IHI9ZS5wZWVrQnl0ZSgpO2Zvcig7aXNXaGl0ZVNwYWNlKHIpOyl7ZS5wb3MrKztyPWUucGVla0J5dGUoKX10PWUucG9zLWUuc3RhcnR9fWVsc2V7Y29uc3Qgcj0xMDI0LGE9b2MubGVuZ3RoO2xldCBuPSExLGk9ZS5lbmQ7Zm9yKDshbiYmaT4wOyl7aS09ci1hO2k8MCYmKGk9MCk7ZS5wb3M9aTtuPWZpbmQoZSxvYyxyLCEwKX1pZihuKXtlLnNraXAoOSk7bGV0IHI7ZG97cj1lLmdldEJ5dGUoKX13aGlsZShpc1doaXRlU3BhY2UocikpO2xldCBhPSIiO2Zvcig7cj49MzImJnI8PTU3Oyl7YSs9U3RyaW5nLmZyb21DaGFyQ29kZShyKTtyPWUuZ2V0Qnl0ZSgpfXQ9cGFyc2VJbnQoYSwxMCk7aXNOYU4odCkmJih0PTApfX1yZXR1cm4gc2hhZG93KHRoaXMsInN0YXJ0WFJlZiIsdCl9Y2hlY2tIZWFkZXIoKXtjb25zdCBlPXRoaXMuc3RyZWFtO2UucmVzZXQoKTtpZighZmluZChlLHNjKSlyZXR1cm47ZS5tb3ZlU3RhcnQoKTtlLnNraXAoc2MubGVuZ3RoKTtsZXQgdCxyPSIiO2Zvcig7KHQ9ZS5nZXRCeXRlKCkpPjMyJiZyLmxlbmd0aDw3OylyKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHQpO3VyLnRlc3Qocik/dGhpcy4jUWU9cjp3YXJuKGBJbnZhbGlkIFBERiBoZWFkZXIgdmVyc2lvbjogJHtyfWApfXBhcnNlU3RhcnRYUmVmKCl7dGhpcy54cmVmLnNldFN0YXJ0WFJlZih0aGlzLnN0YXJ0WFJlZil9Z2V0IG51bVBhZ2VzKCl7bGV0IGU9MDtlPXRoaXMuY2F0YWxvZy5oYXNBY3R1YWxOdW1QYWdlcz90aGlzLmNhdGFsb2cubnVtUGFnZXM6dGhpcy54ZmFGYWN0b3J5P3RoaXMueGZhRmFjdG9yeS5nZXROdW1QYWdlcygpOnRoaXMubGluZWFyaXphdGlvbj90aGlzLmxpbmVhcml6YXRpb24ubnVtUGFnZXM6dGhpcy5jYXRhbG9nLm51bVBhZ2VzO3JldHVybiBzaGFkb3codGhpcywibnVtUGFnZXMiLGUpfSNldChlLHQ9MCl7cmV0dXJuISFBcnJheS5pc0FycmF5KGUpJiZlLmV2ZXJ5KGU9PntpZighKChlPXRoaXMueHJlZi5mZXRjaElmUmVmKGUpKWluc3RhbmNlb2YgRGljdCkpcmV0dXJuITE7aWYoZS5oYXMoIktpZHMiKSl7aWYoKyt0PjEwKXt3YXJuKCIjaGFzT25seURvY3VtZW50U2lnbmF0dXJlczogbWF4aW11bSByZWN1cnNpb24gZGVwdGggcmVhY2hlZCIpO3JldHVybiExfXJldHVybiB0aGlzLiNldChlLmdldCgiS2lkcyIpLHQpfWNvbnN0IHI9aXNOYW1lKGUuZ2V0KCJGVCIpLCJTaWciKSxhPWUuZ2V0KCJSZWN0Iiksbj1BcnJheS5pc0FycmF5KGEpJiZhLmV2ZXJ5KGU9PjA9PT1lKTtyZXR1cm4gciYmbn0pfSN0dChlLHQscj1uZXcgUmVmU2V0KXtpZihBcnJheS5pc0FycmF5KGUpKWZvcihsZXQgYSBvZiBlKXtpZihhIGluc3RhbmNlb2YgUmVmKXtpZihyLmhhcyhhKSljb250aW51ZTtyLnB1dChhKX1hPXRoaXMueHJlZi5mZXRjaElmUmVmKGEpO2lmKCEoYSBpbnN0YW5jZW9mIERpY3QpKWNvbnRpbnVlO2lmKGEuaGFzKCJLaWRzIikpe3RoaXMuI3R0KGEuZ2V0KCJLaWRzIiksdCxyKTtjb250aW51ZX1pZighaXNOYW1lKGEuZ2V0KCJGVCIpLCJTaWciKSljb250aW51ZTtjb25zdCBlPWEuZ2V0KCJWIik7aWYoIShlIGluc3RhbmNlb2YgRGljdCkpY29udGludWU7Y29uc3Qgbj1lLmdldCgiU3ViRmlsdGVyIik7biBpbnN0YW5jZW9mIE5hbWUmJnQuYWRkKG4ubmFtZSl9fWdldCBfeGZhU3RyZWFtcygpe2NvbnN0e2Fjcm9Gb3JtOmV9PXRoaXMuY2F0YWxvZztpZighZSlyZXR1cm4gbnVsbDtjb25zdCB0PWUuZ2V0KCJYRkEiKSxyPW5ldyBNYXAoWyJ4ZHA6eGRwIiwidGVtcGxhdGUiLCJkYXRhc2V0cyIsImNvbmZpZyIsImNvbm5lY3Rpb25TZXQiLCJsb2NhbGVTZXQiLCJzdHlsZXNoZWV0IiwiL3hkcDp4ZHAiXS5tYXAoZT0+W2UsbnVsbF0pKTtpZih0IGluc3RhbmNlb2YgQmFzZVN0cmVhbSYmIXQuaXNFbXB0eSl7ci5zZXQoInhkcDp4ZHAiLHQpO3JldHVybiByfWlmKCFBcnJheS5pc0FycmF5KHQpfHwwPT09dC5sZW5ndGgpcmV0dXJuIG51bGw7Zm9yKGxldCBlPTAsYT10Lmxlbmd0aDtlPGE7ZSs9Mil7bGV0IG47bj0wPT09ZT8ieGRwOnhkcCI6ZT09PWEtMj8iL3hkcDp4ZHAiOnRbZV07aWYoIXIuaGFzKG4pKWNvbnRpbnVlO2NvbnN0IGk9dGhpcy54cmVmLmZldGNoSWZSZWYodFtlKzFdKTtpIGluc3RhbmNlb2YgQmFzZVN0cmVhbSYmIWkuaXNFbXB0eSYmci5zZXQobixpKX1yZXR1cm4gcn1nZXQgeGZhRGF0YXNldHMoKXtjb25zdCBlPXRoaXMuX3hmYVN0cmVhbXM7aWYoIWUpcmV0dXJuIHNoYWRvdyh0aGlzLCJ4ZmFEYXRhc2V0cyIsbnVsbCk7Zm9yKGNvbnN0IHQgb2ZbImRhdGFzZXRzIiwieGRwOnhkcCJdKXtjb25zdCByPWUuZ2V0KHQpO2lmKHIpdHJ5e2NvbnN0IGU9c3RyaW5nVG9VVEY4U3RyaW5nKHIuZ2V0U3RyaW5nKCkpO3JldHVybiBzaGFkb3codGhpcywieGZhRGF0YXNldHMiLG5ldyBEYXRhc2V0UmVhZGVyKHtbdF06ZX0pKX1jYXRjaHt3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTticmVha319cmV0dXJuIHNoYWRvdyh0aGlzLCJ4ZmFEYXRhc2V0cyIsbnVsbCl9Z2V0IHhmYURhdGEoKXtjb25zdCBlPXRoaXMuX3hmYVN0cmVhbXM7aWYoIWUpcmV0dXJuIG51bGw7Y29uc3QgdD1PYmplY3QuY3JlYXRlKG51bGwpO2Zvcihjb25zdFtyLGFdb2YgZSlpZihhKXRyeXt0W3JdPXN0cmluZ1RvVVRGOFN0cmluZyhhLmdldFN0cmluZygpKX1jYXRjaHt3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTtyZXR1cm4gbnVsbH1yZXR1cm4gdH1nZXQgeGZhRmFjdG9yeSgpe2xldCBlO3RoaXMucGRmTWFuYWdlci5lbmFibGVYZmEmJnRoaXMuY2F0YWxvZy5uZWVkc1JlbmRlcmluZyYmdGhpcy5mb3JtSW5mby5oYXNYZmEmJiF0aGlzLmZvcm1JbmZvLmhhc0Fjcm9Gb3JtJiYoZT10aGlzLnhmYURhdGEpO3JldHVybiBzaGFkb3codGhpcywieGZhRmFjdG9yeSIsZT9uZXcgWEZBRmFjdG9yeShlKTpudWxsKX1nZXQgaXNQdXJlWGZhKCl7cmV0dXJuISF0aGlzLnhmYUZhY3RvcnkmJnRoaXMueGZhRmFjdG9yeS5pc1ZhbGlkKCl9Z2V0IGh0bWxGb3JYZmEoKXtyZXR1cm4gdGhpcy54ZmFGYWN0b3J5P3RoaXMueGZhRmFjdG9yeS5nZXRQYWdlcygpOm51bGx9YXN5bmMjcnQoKXtjb25zdCBlPWF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJ4ZmFJbWFnZXMiKTtlJiZ0aGlzLnhmYUZhY3Rvcnkuc2V0SW1hZ2VzKGUpfWFzeW5jI2F0KGUsdCl7Y29uc3Qgcj1hd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm0iKTtpZighcilyZXR1cm47Y29uc3QgYT1hd2FpdCByLmdldEFzeW5jKCJEUiIpO2lmKCEoYSBpbnN0YW5jZW9mIERpY3QpKXJldHVybjthd2FpdCBPYmplY3RMb2FkZXIubG9hZChhLFsiRm9udCJdLHRoaXMueHJlZik7Y29uc3Qgbj1hLmdldCgiRm9udCIpO2lmKCEobiBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtjb25zdCBpPU9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShudWxsKSx0aGlzLnBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucyx7dXNlU3lzdGVtRm9udHM6ITF9KSx7YnVpbHRJbkNNYXBDYWNoZTpzLGZvbnRDYWNoZTpvLHN0YW5kYXJkRm9udERhdGFDYWNoZTpjfT10aGlzLmNhdGFsb2csbD1uZXcgUGFydGlhbEV2YWx1YXRvcih7eHJlZjp0aGlzLnhyZWYsaGFuZGxlcjplLHBhZ2VJbmRleDotMSxpZEZhY3Rvcnk6dGhpcy5fZ2xvYmFsSWRGYWN0b3J5LGZvbnRDYWNoZTpvLGJ1aWx0SW5DTWFwQ2FjaGU6cyxzdGFuZGFyZEZvbnREYXRhQ2FjaGU6YyxvcHRpb25zOml9KSxoPW5ldyBPcGVyYXRvckxpc3QsdT1bXSxkPXtnZXQgZm9udCgpe3JldHVybiB1LmF0KC0xKX0sc2V0IGZvbnQoZSl7dS5wdXNoKGUpfSxjbG9uZSgpe3JldHVybiB0aGlzfX0scGFyc2VGb250PShlLHIsbik9PmwuaGFuZGxlU2V0Rm9udChhLFtOYW1lLmdldChlKSwxXSxudWxsLGgsdCxkLHIsbikuY2F0Y2goZT0+e3dhcm4oYGxvYWRYZmFGb250czogIiR7ZX0iLmApO3JldHVybiBudWxsfSksZj1bXTtmb3IoY29uc3RbZSx0XW9mIG4pe2NvbnN0IHI9dC5nZXQoIkZvbnREZXNjcmlwdG9yIik7aWYoIShyIGluc3RhbmNlb2YgRGljdCkpY29udGludWU7bGV0IGE9ci5nZXQoIkZvbnRGYW1pbHkiKTthPWEucmVwbGFjZUFsbCgvWyBdKyhcZCkvZywiJDEiKTtjb25zdCBuPXtmb250RmFtaWx5OmEsZm9udFdlaWdodDpyLmdldCgiRm9udFdlaWdodCIpLGl0YWxpY0FuZ2xlOi1yLmdldCgiSXRhbGljQW5nbGUiKX07dmFsaWRhdGVDU1NGb250KG4pJiZmLnB1c2gocGFyc2VGb250KGUsbnVsbCxuKSl9YXdhaXQgUHJvbWlzZS5hbGwoZik7Y29uc3QgZz10aGlzLnhmYUZhY3Rvcnkuc2V0Rm9udHModSk7aWYoIWcpcmV0dXJuO2kuaWdub3JlRXJyb3JzPSEwO2YubGVuZ3RoPTA7dS5sZW5ndGg9MDtjb25zdCBwPW5ldyBTZXQ7Zm9yKGNvbnN0IGUgb2YgZylnZXRYZmFGb250TmFtZShgJHtlfS1SZWd1bGFyYCl8fHAuYWRkKGUpO3Auc2l6ZSYmZy5wdXNoKCJQZGZKUy1GYWxsYmFjayIpO2Zvcihjb25zdCBlIG9mIGcpaWYoIXAuaGFzKGUpKWZvcihjb25zdCB0IG9mW3tuYW1lOiJSZWd1bGFyIixmb250V2VpZ2h0OjQwMCxpdGFsaWNBbmdsZTowfSx7bmFtZToiQm9sZCIsZm9udFdlaWdodDo3MDAsaXRhbGljQW5nbGU6MH0se25hbWU6Ikl0YWxpYyIsZm9udFdlaWdodDo0MDAsaXRhbGljQW5nbGU6MTJ9LHtuYW1lOiJCb2xkSXRhbGljIixmb250V2VpZ2h0OjcwMCxpdGFsaWNBbmdsZToxMn1dKXtjb25zdCByPWAke2V9LSR7dC5uYW1lfWA7Zi5wdXNoKHBhcnNlRm9udChyLGdldFhmYUZvbnREaWN0KHIpLHtmb250RmFtaWx5OmUsZm9udFdlaWdodDp0LmZvbnRXZWlnaHQsaXRhbGljQW5nbGU6dC5pdGFsaWNBbmdsZX0pKX1hd2FpdCBQcm9taXNlLmFsbChmKTt0aGlzLnhmYUZhY3RvcnkuYXBwZW5kRm9udHModSxwKX1sb2FkWGZhUmVzb3VyY2VzKGUsdCl7cmV0dXJuIFByb21pc2UuYWxsKFt0aGlzLiNhdChlLHQpLmNhdGNoKCgpPT57fSksdGhpcy4jcnQoKV0pfXNlcmlhbGl6ZVhmYURhdGEoZSl7cmV0dXJuIHRoaXMueGZhRmFjdG9yeT90aGlzLnhmYUZhY3Rvcnkuc2VyaWFsaXplRGF0YShlKTpudWxsfWdldCB2ZXJzaW9uKCl7cmV0dXJuIHRoaXMuY2F0YWxvZy52ZXJzaW9ufHx0aGlzLiNRZX1nZXQgZm9ybUluZm8oKXtjb25zdCBlPXtoYXNGaWVsZHM6ITEsaGFzQWNyb0Zvcm06ITEsaGFzWGZhOiExLGhhc1NpZ25hdHVyZXM6ITF9LHthY3JvRm9ybTp0fT10aGlzLmNhdGFsb2c7aWYoIXQpcmV0dXJuIHNoYWRvdyh0aGlzLCJmb3JtSW5mbyIsZSk7dHJ5e2NvbnN0IHI9dC5nZXQoIkZpZWxkcyIpLGE9QXJyYXkuaXNBcnJheShyKSYmci5sZW5ndGg+MDtlLmhhc0ZpZWxkcz1hO2NvbnN0IG49dC5nZXQoIlhGQSIpO2UuaGFzWGZhPUFycmF5LmlzQXJyYXkobikmJm4ubGVuZ3RoPjB8fG4gaW5zdGFuY2VvZiBCYXNlU3RyZWFtJiYhbi5pc0VtcHR5O2NvbnN0IGk9ISEoMSZ0LmdldCgiU2lnRmxhZ3MiKSkscz1pJiZ0aGlzLiNldChyKTtlLmhhc0Fjcm9Gb3JtPWEmJiFzO2UuaGFzU2lnbmF0dXJlcz1pfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbil0aHJvdyBlO3dhcm4oYENhbm5vdCBmZXRjaCBmb3JtIGluZm9ybWF0aW9uOiAiJHtlfSIuYCl9cmV0dXJuIHNoYWRvdyh0aGlzLCJmb3JtSW5mbyIsZSl9Z2V0IGRvY3VtZW50SW5mbygpe2NvbnN0e2NhdGFsb2c6ZSxmb3JtSW5mbzp0LHhyZWY6cn09dGhpcyxhPXtQREZGb3JtYXRWZXJzaW9uOnRoaXMudmVyc2lvbixMYW5ndWFnZTplLmxhbmcsRW5jcnlwdEZpbHRlck5hbWU6ci5lbmNyeXB0Py5maWx0ZXJOYW1lPz9udWxsLElzTGluZWFyaXplZDohIXRoaXMubGluZWFyaXphdGlvbixJc0Fjcm9Gb3JtUHJlc2VudDp0Lmhhc0Fjcm9Gb3JtLElzWEZBUHJlc2VudDp0Lmhhc1hmYSxJc0NvbGxlY3Rpb25QcmVzZW50OiEhZS5jb2xsZWN0aW9uLElzU2lnbmF0dXJlc1ByZXNlbnQ6dC5oYXNTaWduYXR1cmVzfTtsZXQgbjt0cnl7bj1yLnRyYWlsZXIuZ2V0KCJJbmZvIil9Y2F0Y2goZSl7aWYoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKXRocm93IGU7aW5mbygiVGhlIGRvY3VtZW50IGluZm9ybWF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC4iKX1pZighKG4gaW5zdGFuY2VvZiBEaWN0KSlyZXR1cm4gc2hhZG93KHRoaXMsImRvY3VtZW50SW5mbyIsYSk7Zm9yKGNvbnN0W2UsdF1vZiBuKXtzd2l0Y2goZSl7Y2FzZSJUaXRsZSI6Y2FzZSJBdXRob3IiOmNhc2UiU3ViamVjdCI6Y2FzZSJLZXl3b3JkcyI6Y2FzZSJDcmVhdG9yIjpjYXNlIlByb2R1Y2VyIjpjYXNlIkNyZWF0aW9uRGF0ZSI6Y2FzZSJNb2REYXRlIjppZigic3RyaW5nIj09dHlwZW9mIHQpe2FbZV09c3RyaW5nVG9QREZTdHJpbmcodCk7Y29udGludWV9YnJlYWs7Y2FzZSJUcmFwcGVkIjppZih0IGluc3RhbmNlb2YgTmFtZSl7YVtlXT10O2NvbnRpbnVlfWJyZWFrO2RlZmF1bHQ6bGV0IHI7c3dpdGNoKHR5cGVvZiB0KXtjYXNlInN0cmluZyI6cj1zdHJpbmdUb1BERlN0cmluZyh0KTticmVhaztjYXNlIm51bWJlciI6Y2FzZSJib29sZWFuIjpyPXQ7YnJlYWs7ZGVmYXVsdDp0IGluc3RhbmNlb2YgTmFtZSYmKHI9dCl9aWYodm9pZCAwPT09cil7d2FybihgQmFkIHZhbHVlLCBmb3IgY3VzdG9tIGtleSAiJHtlfSIsIGluIEluZm86ICR7dH0uYCk7Y29udGludWV9YS5DdXN0b20/Pz1PYmplY3QuY3JlYXRlKG51bGwpO2EuQ3VzdG9tW2VdPXI7Y29udGludWV9d2FybihgQmFkIHZhbHVlLCBmb3Iga2V5ICIke2V9IiwgaW4gSW5mbzogJHt0fS5gKX1yZXR1cm4gc2hhZG93KHRoaXMsImRvY3VtZW50SW5mbyIsYSl9Z2V0IGZpbmdlcnByaW50cygpe2NvbnN0IGU9IlwwIi5yZXBlYXQoMTYpO2Z1bmN0aW9uIHZhbGlkYXRlKHQpe3JldHVybiJzdHJpbmciPT10eXBlb2YgdCYmMTY9PT10Lmxlbmd0aCYmdCE9PWV9Y29uc3QgdD10aGlzLnhyZWYudHJhaWxlci5nZXQoIklEIik7bGV0IHIsYTtpZihBcnJheS5pc0FycmF5KHQpJiZ2YWxpZGF0ZSh0WzBdKSl7cj1zdHJpbmdUb0J5dGVzKHRbMF0pO3RbMV0hPT10WzBdJiZ2YWxpZGF0ZSh0WzFdKSYmKGE9c3RyaW5nVG9CeXRlcyh0WzFdKSl9ZWxzZSByPWNhbGN1bGF0ZU1ENSh0aGlzLnN0cmVhbS5nZXRCeXRlUmFuZ2UoMCwxMDI0KSwwLDEwMjQpO3JldHVybiBzaGFkb3codGhpcywiZmluZ2VycHJpbnRzIixbdG9IZXhVdGlsKHIpLGE/dG9IZXhVdGlsKGEpOm51bGxdKX1hc3luYyNudChlKXtjb25zdHtjYXRhbG9nOnQsbGluZWFyaXphdGlvbjpyLHhyZWY6YX09dGhpcyxuPVJlZi5nZXQoci5vYmplY3ROdW1iZXJGaXJzdCwwKTt0cnl7Y29uc3QgZT1hd2FpdCBhLmZldGNoQXN5bmMobik7aWYoZSBpbnN0YW5jZW9mIERpY3Qpe2xldCByPWUuZ2V0UmF3KCJUeXBlIik7ciBpbnN0YW5jZW9mIFJlZiYmKHI9YXdhaXQgYS5mZXRjaEFzeW5jKHIpKTtpZihpc05hbWUociwiUGFnZSIpfHwhZS5oYXMoIlR5cGUiKSYmIWUuaGFzKCJLaWRzIikmJmUuaGFzKCJDb250ZW50cyIpKXt0LnBhZ2VLaWRzQ291bnRDYWNoZS5oYXMobil8fHQucGFnZUtpZHNDb3VudENhY2hlLnB1dChuLDEpO3QucGFnZUluZGV4Q2FjaGUuaGFzKG4pfHx0LnBhZ2VJbmRleENhY2hlLnB1dChuLDApO3JldHVybltlLG5dfX10aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlRoZSBMaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgZG9lc24ndCBwb2ludCB0byBhIHZhbGlkIFBhZ2UgZGljdGlvbmFyeS4iKX1jYXRjaChyKXt3YXJuKGBfZ2V0TGluZWFyaXphdGlvblBhZ2U6ICIke3IubWVzc2FnZX0iLmApO3JldHVybiB0LmdldFBhZ2VEaWN0KGUpfX1nZXRQYWdlKGUpe2NvbnN0IHQ9dGhpcy4jWmUuZ2V0KGUpO2lmKHQpcmV0dXJuIHQ7Y29uc3R7Y2F0YWxvZzpyLGxpbmVhcml6YXRpb246YSx4ZmFGYWN0b3J5Om59PXRoaXM7bGV0IGk7aT1uP1Byb21pc2UucmVzb2x2ZShbRGljdC5lbXB0eSxudWxsXSk6YT8ucGFnZUZpcnN0PT09ZT90aGlzLiNudChlKTpyLmdldFBhZ2VEaWN0KGUpO2k9aS50aGVuKChbdCxhXSk9Pm5ldyBQYWdlKHtwZGZNYW5hZ2VyOnRoaXMucGRmTWFuYWdlcix4cmVmOnRoaXMueHJlZixwYWdlSW5kZXg6ZSxwYWdlRGljdDp0LHJlZjphLGdsb2JhbElkRmFjdG9yeTp0aGlzLl9nbG9iYWxJZEZhY3RvcnksZm9udENhY2hlOnIuZm9udENhY2hlLGJ1aWx0SW5DTWFwQ2FjaGU6ci5idWlsdEluQ01hcENhY2hlLHN0YW5kYXJkRm9udERhdGFDYWNoZTpyLnN0YW5kYXJkRm9udERhdGFDYWNoZSxnbG9iYWxDb2xvclNwYWNlQ2FjaGU6ci5nbG9iYWxDb2xvclNwYWNlQ2FjaGUsZ2xvYmFsSW1hZ2VDYWNoZTpyLmdsb2JhbEltYWdlQ2FjaGUsc3lzdGVtRm9udENhY2hlOnIuc3lzdGVtRm9udENhY2hlLG5vbkJsZW5kTW9kZXNTZXQ6ci5ub25CbGVuZE1vZGVzU2V0LHhmYUZhY3Rvcnk6bn0pKTt0aGlzLiNaZS5zZXQoZSxpKTtyZXR1cm4gaX1hc3luYyBjaGVja0ZpcnN0UGFnZShlPSExKXtpZighZSl0cnl7YXdhaXQgdGhpcy5nZXRQYWdlKDApfWNhdGNoKGUpe2lmKGUgaW5zdGFuY2VvZiBYUmVmRW50cnlFeGNlcHRpb24pe3RoaXMuI1plLmRlbGV0ZSgwKTthd2FpdCB0aGlzLmNsZWFudXAoKTt0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9ufX19YXN5bmMgY2hlY2tMYXN0UGFnZShlPSExKXtjb25zdHtjYXRhbG9nOnQscGRmTWFuYWdlcjpyfT10aGlzO3Quc2V0QWN0dWFsTnVtUGFnZXMoKTtsZXQgYTt0cnl7YXdhaXQgUHJvbWlzZS5hbGwoW3IuZW5zdXJlRG9jKCJ4ZmFGYWN0b3J5Iiksci5lbnN1cmVEb2MoImxpbmVhcml6YXRpb24iKSxyLmVuc3VyZUNhdGFsb2coIm51bVBhZ2VzIildKTtpZih0aGlzLnhmYUZhY3RvcnkpcmV0dXJuO2E9dGhpcy5saW5lYXJpemF0aW9uP3RoaXMubGluZWFyaXphdGlvbi5udW1QYWdlczp0Lm51bVBhZ2VzO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKGEpKXRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBjb3VudCBpcyBub3QgYW4gaW50ZWdlci4iKTtpZihhPD0xKXJldHVybjthd2FpdCB0aGlzLmdldFBhZ2UoYS0xKX1jYXRjaChuKXt0aGlzLiNaZS5kZWxldGUoYS0xKTthd2FpdCB0aGlzLmNsZWFudXAoKTtpZihuIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uJiYhZSl0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9uO3dhcm4oYGNoZWNrTGFzdFBhZ2UgLSBpbnZhbGlkIC9QYWdlcyB0cmVlIC9Db3VudDogJHthfS5gKTtsZXQgaTt0cnl7aT1hd2FpdCB0LmdldEFsbFBhZ2VEaWN0cyhlKX1jYXRjaChyKXtpZihyIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uJiYhZSl0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9uO3Quc2V0QWN0dWFsTnVtUGFnZXMoMSk7cmV0dXJufWZvcihjb25zdFtlLFthLG5dXW9mIGkpe2xldCBpO2lmKGEgaW5zdGFuY2VvZiBFcnJvcil7aT1Qcm9taXNlLnJlamVjdChhKTtpLmNhdGNoKCgpPT57fSl9ZWxzZSBpPVByb21pc2UucmVzb2x2ZShuZXcgUGFnZSh7cGRmTWFuYWdlcjpyLHhyZWY6dGhpcy54cmVmLHBhZ2VJbmRleDplLHBhZ2VEaWN0OmEscmVmOm4sZ2xvYmFsSWRGYWN0b3J5OnRoaXMuX2dsb2JhbElkRmFjdG9yeSxmb250Q2FjaGU6dC5mb250Q2FjaGUsYnVpbHRJbkNNYXBDYWNoZTp0LmJ1aWx0SW5DTWFwQ2FjaGUsc3RhbmRhcmRGb250RGF0YUNhY2hlOnQuc3RhbmRhcmRGb250RGF0YUNhY2hlLGdsb2JhbENvbG9yU3BhY2VDYWNoZTp0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSxnbG9iYWxJbWFnZUNhY2hlOnQuZ2xvYmFsSW1hZ2VDYWNoZSxzeXN0ZW1Gb250Q2FjaGU6dC5zeXN0ZW1Gb250Q2FjaGUsbm9uQmxlbmRNb2Rlc1NldDp0Lm5vbkJsZW5kTW9kZXNTZXQseGZhRmFjdG9yeTpudWxsfSkpO3RoaXMuI1plLnNldChlLGkpfXQuc2V0QWN0dWFsTnVtUGFnZXMoaS5zaXplKX19YXN5bmMgZm9udEZhbGxiYWNrKGUsdCl7Y29uc3R7Y2F0YWxvZzpyLHBkZk1hbmFnZXI6YX09dGhpcztmb3IoY29uc3QgbiBvZiBhd2FpdCBQcm9taXNlLmFsbChyLmZvbnRDYWNoZSkpaWYobi5sb2FkZWROYW1lPT09ZSl7bi5mYWxsYmFjayh0LGEuZXZhbHVhdG9yT3B0aW9ucyk7cmV0dXJufX1hc3luYyBjbGVhbnVwKGU9ITEpe3JldHVybiB0aGlzLmNhdGFsb2c/dGhpcy5jYXRhbG9nLmNsZWFudXAoZSk6Y2xlYXJHbG9iYWxDYWNoZXMoKX1hc3luYyNpdChlLHQscixhLG4saSxzKXtjb25zdHt4cmVmOm99PXRoaXM7aWYoIShyIGluc3RhbmNlb2YgUmVmKXx8aS5oYXMocikpcmV0dXJuO2kucHV0KHIpO2NvbnN0IGM9YXdhaXQgby5mZXRjaEFzeW5jKHIpO2lmKCEoYyBpbnN0YW5jZW9mIERpY3QpKXJldHVybjtsZXQgbD1hd2FpdCBjLmdldEFzeW5jKCJTdWJ0eXBlIik7bD1sIGluc3RhbmNlb2YgTmFtZT9sLm5hbWU6bnVsbDtpZigiTGluayI9PT1sKXJldHVybjtpZihjLmhhcygiVCIpKXtjb25zdCB0PXN0cmluZ1RvUERGU3RyaW5nKGF3YWl0IGMuZ2V0QXN5bmMoIlQiKSk7ZT0iIj09PWU/dDpgJHtlfS4ke3R9YH1lbHNle2xldCByPWM7Zm9yKDs7KXtyPXIuZ2V0UmF3KCJQYXJlbnQiKXx8dDtpZihyIGluc3RhbmNlb2YgUmVmKXtpZihpLmhhcyhyKSlicmVhaztyPWF3YWl0IG8uZmV0Y2hBc3luYyhyKX1pZighKHIgaW5zdGFuY2VvZiBEaWN0KSlicmVhaztpZihyLmhhcygiVCIpKXtjb25zdCB0PXN0cmluZ1RvUERGU3RyaW5nKGF3YWl0IHIuZ2V0QXN5bmMoIlQiKSk7ZT0iIj09PWU/dDpgJHtlfS4ke3R9YDticmVha319fXQmJiFjLmhhcygiUGFyZW50IikmJmlzTmFtZShjLmdldCgiU3VidHlwZSIpLCJXaWRnZXQiKSYmcy5wdXQocix0KTthLmhhcyhlKXx8YS5zZXQoZSxbXSk7YS5nZXQoZSkucHVzaChBbm5vdGF0aW9uRmFjdG9yeS5jcmVhdGUobyxyLG4sbnVsbCwhMCxzLG51bGwsbnVsbCkudGhlbihlPT5lPy5nZXRGaWVsZE9iamVjdCgpKS5jYXRjaChmdW5jdGlvbihlKXt3YXJuKGAjY29sbGVjdEZpZWxkT2JqZWN0czogIiR7ZX0iLmApO3JldHVybiBudWxsfSkpO2lmKCFjLmhhcygiS2lkcyIpKXJldHVybjtjb25zdCBoPWF3YWl0IGMuZ2V0QXN5bmMoIktpZHMiKTtpZihBcnJheS5pc0FycmF5KGgpKWZvcihjb25zdCB0IG9mIGgpYXdhaXQgdGhpcy4jaXQoZSxyLHQsYSxuLGkscyl9Z2V0IGZpZWxkT2JqZWN0cygpe3JldHVybiBzaGFkb3codGhpcywiZmllbGRPYmplY3RzIix0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJmb3JtSW5mbyIpLnRoZW4oYXN5bmMgZT0+e2lmKCFlLmhhc0ZpZWxkcylyZXR1cm4gbnVsbDtjb25zdCB0PWF3YWl0IHRoaXMuYW5ub3RhdGlvbkdsb2JhbHM7aWYoIXQpcmV0dXJuIG51bGw7Y29uc3R7YWNyb0Zvcm06cn09dCxhPW5ldyBSZWZTZXQsbj1PYmplY3QuY3JlYXRlKG51bGwpLGk9bmV3IE1hcCxzPW5ldyBSZWZTZXRDYWNoZTtmb3IoY29uc3QgZSBvZiByLmdldCgiRmllbGRzIikpYXdhaXQgdGhpcy4jaXQoIiIsbnVsbCxlLGksdCxhLHMpO2NvbnN0IG89W107Zm9yKGNvbnN0W2UsdF1vZiBpKW8ucHVzaChQcm9taXNlLmFsbCh0KS50aGVuKHQ9PnsodD10LmZpbHRlcihlPT4hIWUpKS5sZW5ndGg+MCYmKG5bZV09dCl9KSk7YXdhaXQgUHJvbWlzZS5hbGwobyk7cmV0dXJue2FsbEZpZWxkczpvYmplY3RTaXplKG4pPjA/bjpudWxsLG9ycGhhbkZpZWxkczpzfX0pKX1nZXQgaGFzSlNBY3Rpb25zKCl7cmV0dXJuIHNoYWRvdyh0aGlzLCJoYXNKU0FjdGlvbnMiLHRoaXMucGRmTWFuYWdlci5lbnN1cmVEb2MoIl9wYXJzZUhhc0pTQWN0aW9ucyIpKX1hc3luYyBfcGFyc2VIYXNKU0FjdGlvbnMoKXtjb25zdFtlLHRdPWF3YWl0IFByb21pc2UuYWxsKFt0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygianNBY3Rpb25zIiksdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiZmllbGRPYmplY3RzIildKTtyZXR1cm4hIWV8fCEhdD8uYWxsRmllbGRzJiZPYmplY3QudmFsdWVzKHQuYWxsRmllbGRzKS5zb21lKGU9PmUuc29tZShlPT5udWxsIT09ZS5hY3Rpb25zKSl9Z2V0IGNhbGN1bGF0aW9uT3JkZXJJZHMoKXtjb25zdCBlPXRoaXMuY2F0YWxvZy5hY3JvRm9ybT8uZ2V0KCJDTyIpO2lmKCFBcnJheS5pc0FycmF5KGUpfHwwPT09ZS5sZW5ndGgpcmV0dXJuIHNoYWRvdyh0aGlzLCJjYWxjdWxhdGlvbk9yZGVySWRzIixudWxsKTtjb25zdCB0PVtdO2Zvcihjb25zdCByIG9mIGUpciBpbnN0YW5jZW9mIFJlZiYmdC5wdXNoKHIudG9TdHJpbmcoKSk7cmV0dXJuIHNoYWRvdyh0aGlzLCJjYWxjdWxhdGlvbk9yZGVySWRzIix0Lmxlbmd0aD90Om51bGwpfWdldCBhbm5vdGF0aW9uR2xvYmFscygpe3JldHVybiBzaGFkb3codGhpcywiYW5ub3RhdGlvbkdsb2JhbHMiLEFubm90YXRpb25GYWN0b3J5LmNyZWF0ZUdsb2JhbHModGhpcy5wZGZNYW5hZ2VyKSl9fWNsYXNzIEJhc2VQZGZNYW5hZ2Vye2NvbnN0cnVjdG9yKHtkb2NCYXNlVXJsOmUsZG9jSWQ6dCxlbmFibGVYZmE6cixldmFsdWF0b3JPcHRpb25zOmEsaGFuZGxlcjpuLHBhc3N3b3JkOml9KXt0aGlzLl9kb2NCYXNlVXJsPWZ1bmN0aW9uIHBhcnNlRG9jQmFzZVVybChlKXtpZihlKXtjb25zdCB0PWNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwoZSk7aWYodClyZXR1cm4gdC5ocmVmO3dhcm4oYEludmFsaWQgYWJzb2x1dGUgZG9jQmFzZVVybDogIiR7ZX0iLmApfXJldHVybiBudWxsfShlKTt0aGlzLl9kb2NJZD10O3RoaXMuX3Bhc3N3b3JkPWk7dGhpcy5lbmFibGVYZmE9cjthLmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkJiY9RmVhdHVyZVRlc3QuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7YS5pc0ltYWdlRGVjb2RlclN1cHBvcnRlZCYmPUZlYXR1cmVUZXN0LmlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkO3RoaXMuZXZhbHVhdG9yT3B0aW9ucz1PYmplY3QuZnJlZXplKGEpO0ltYWdlUmVzaXplci5zZXRPcHRpb25zKGEpO0pwZWdTdHJlYW0uc2V0T3B0aW9ucyhhKTtPcGVyYXRvckxpc3Quc2V0T3B0aW9ucyhhKTtjb25zdCBzPXsuLi5hLGhhbmRsZXI6bn07SnB4SW1hZ2Uuc2V0T3B0aW9ucyhzKTtJY2NDb2xvclNwYWNlLnNldE9wdGlvbnMocyk7Q215a0lDQ0Jhc2VkQ1Muc2V0T3B0aW9ucyhzKX1nZXQgZG9jSWQoKXtyZXR1cm4gdGhpcy5fZG9jSWR9Z2V0IHBhc3N3b3JkKCl7cmV0dXJuIHRoaXMuX3Bhc3N3b3JkfWdldCBkb2NCYXNlVXJsKCl7cmV0dXJuIHRoaXMuX2RvY0Jhc2VVcmx9ZW5zdXJlRG9jKGUsdCl7cmV0dXJuIHRoaXMuZW5zdXJlKHRoaXMucGRmRG9jdW1lbnQsZSx0KX1lbnN1cmVYUmVmKGUsdCl7cmV0dXJuIHRoaXMuZW5zdXJlKHRoaXMucGRmRG9jdW1lbnQueHJlZixlLHQpfWVuc3VyZUNhdGFsb2coZSx0KXtyZXR1cm4gdGhpcy5lbnN1cmUodGhpcy5wZGZEb2N1bWVudC5jYXRhbG9nLGUsdCl9Z2V0UGFnZShlKXtyZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5nZXRQYWdlKGUpfWZvbnRGYWxsYmFjayhlLHQpe3JldHVybiB0aGlzLnBkZkRvY3VtZW50LmZvbnRGYWxsYmFjayhlLHQpfWNsZWFudXAoZT0hMSl7cmV0dXJuIHRoaXMucGRmRG9jdW1lbnQuY2xlYW51cChlKX1hc3luYyBlbnN1cmUoZSx0LHIpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGVuc3VyZWAgY2FsbGVkIil9cmVxdWVzdFJhbmdlKGUsdCl7dW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgcmVxdWVzdFJhbmdlYCBjYWxsZWQiKX1yZXF1ZXN0TG9hZGVkU3RyZWFtKGU9ITEpe3VucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYHJlcXVlc3RMb2FkZWRTdHJlYW1gIGNhbGxlZCIpfXNlbmRQcm9ncmVzc2l2ZURhdGEoZSl7dW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgc2VuZFByb2dyZXNzaXZlRGF0YWAgY2FsbGVkIil9dXBkYXRlUGFzc3dvcmQoZSl7dGhpcy5fcGFzc3dvcmQ9ZX10ZXJtaW5hdGUoZSl7dW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgdGVybWluYXRlYCBjYWxsZWQiKX19Y2xhc3MgTG9jYWxQZGZNYW5hZ2VyIGV4dGVuZHMgQmFzZVBkZk1hbmFnZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7Y29uc3QgdD1uZXcgU3RyZWFtKGUuc291cmNlKTt0aGlzLnBkZkRvY3VtZW50PW5ldyBQREZEb2N1bWVudCh0aGlzLHQpO3RoaXMuX2xvYWRlZFN0cmVhbVByb21pc2U9UHJvbWlzZS5yZXNvbHZlKHQpfWFzeW5jIGVuc3VyZShlLHQscil7Y29uc3QgYT1lW3RdO3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiBhP2EuYXBwbHkoZSxyKTphfXJlcXVlc3RSYW5nZShlLHQpe3JldHVybiBQcm9taXNlLnJlc29sdmUoKX1yZXF1ZXN0TG9hZGVkU3RyZWFtKGU9ITEpe3JldHVybiB0aGlzLl9sb2FkZWRTdHJlYW1Qcm9taXNlfXRlcm1pbmF0ZShlKXt9fWNsYXNzIE5ldHdvcmtQZGZNYW5hZ2VyIGV4dGVuZHMgQmFzZVBkZk1hbmFnZXJ7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSk7dGhpcy5zdHJlYW1NYW5hZ2VyPW5ldyBDaHVua2VkU3RyZWFtTWFuYWdlcihlLnNvdXJjZSx7bXNnSGFuZGxlcjplLmhhbmRsZXIsbGVuZ3RoOmUubGVuZ3RoLGRpc2FibGVBdXRvRmV0Y2g6ZS5kaXNhYmxlQXV0b0ZldGNoLHJhbmdlQ2h1bmtTaXplOmUucmFuZ2VDaHVua1NpemV9KTt0aGlzLnBkZkRvY3VtZW50PW5ldyBQREZEb2N1bWVudCh0aGlzLHRoaXMuc3RyZWFtTWFuYWdlci5nZXRTdHJlYW0oKSl9YXN5bmMgZW5zdXJlKGUsdCxyKXt0cnl7Y29uc3QgYT1lW3RdO3JldHVybiJmdW5jdGlvbiI9PXR5cGVvZiBhP2EuYXBwbHkoZSxyKTphfWNhdGNoKGEpe2lmKCEoYSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSl0aHJvdyBhO2F3YWl0IHRoaXMucmVxdWVzdFJhbmdlKGEuYmVnaW4sYS5lbmQpO3JldHVybiB0aGlzLmVuc3VyZShlLHQscil9fXJlcXVlc3RSYW5nZShlLHQpe3JldHVybiB0aGlzLnN0cmVhbU1hbmFnZXIucmVxdWVzdFJhbmdlKGUsdCl9cmVxdWVzdExvYWRlZFN0cmVhbShlPSExKXtyZXR1cm4gdGhpcy5zdHJlYW1NYW5hZ2VyLnJlcXVlc3RBbGxDaHVua3MoZSl9c2VuZFByb2dyZXNzaXZlRGF0YShlKXt0aGlzLnN0cmVhbU1hbmFnZXIub25SZWNlaXZlRGF0YSh7Y2h1bms6ZX0pfXRlcm1pbmF0ZShlKXt0aGlzLnN0cmVhbU1hbmFnZXIuYWJvcnQoZSl9fWNvbnN0IGxjPTEsaGM9Mix1Yz0xLGRjPTIsZmM9MyxnYz00LHBjPTUsbWM9NixiYz03LHljPTg7ZnVuY3Rpb24gb25Gbigpe31mdW5jdGlvbiB3cmFwUmVhc29uKGUpe2lmKGUgaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbnx8ZSBpbnN0YW5jZW9mIEludmFsaWRQREZFeGNlcHRpb258fGUgaW5zdGFuY2VvZiBQYXNzd29yZEV4Y2VwdGlvbnx8ZSBpbnN0YW5jZW9mIFJlc3BvbnNlRXhjZXB0aW9ufHxlIGluc3RhbmNlb2YgVW5rbm93bkVycm9yRXhjZXB0aW9uKXJldHVybiBlO2UgaW5zdGFuY2VvZiBFcnJvcnx8Im9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT09ZXx8dW5yZWFjaGFibGUoJ3dyYXBSZWFzb246IEV4cGVjdGVkICJyZWFzb24iIHRvIGJlIGEgKHBvc3NpYmx5IGNsb25lZCkgRXJyb3IuJyk7c3dpdGNoKGUubmFtZSl7Y2FzZSJBYm9ydEV4Y2VwdGlvbiI6cmV0dXJuIG5ldyBBYm9ydEV4Y2VwdGlvbihlLm1lc3NhZ2UpO2Nhc2UiSW52YWxpZFBERkV4Y2VwdGlvbiI6cmV0dXJuIG5ldyBJbnZhbGlkUERGRXhjZXB0aW9uKGUubWVzc2FnZSk7Y2FzZSJQYXNzd29yZEV4Y2VwdGlvbiI6cmV0dXJuIG5ldyBQYXNzd29yZEV4Y2VwdGlvbihlLm1lc3NhZ2UsZS5jb2RlKTtjYXNlIlJlc3BvbnNlRXhjZXB0aW9uIjpyZXR1cm4gbmV3IFJlc3BvbnNlRXhjZXB0aW9uKGUubWVzc2FnZSxlLnN0YXR1cyxlLm1pc3NpbmcpO2Nhc2UiVW5rbm93bkVycm9yRXhjZXB0aW9uIjpyZXR1cm4gbmV3IFVua25vd25FcnJvckV4Y2VwdGlvbihlLm1lc3NhZ2UsZS5kZXRhaWxzKX1yZXR1cm4gbmV3IFVua25vd25FcnJvckV4Y2VwdGlvbihlLm1lc3NhZ2UsZS50b1N0cmluZygpKX1jbGFzcyBNZXNzYWdlSGFuZGxlcnsjc3Q9bmV3IEFib3J0Q29udHJvbGxlcjtjb25zdHJ1Y3RvcihlLHQscil7dGhpcy5zb3VyY2VOYW1lPWU7dGhpcy50YXJnZXROYW1lPXQ7dGhpcy5jb21PYmo9cjt0aGlzLmNhbGxiYWNrSWQ9MTt0aGlzLnN0cmVhbUlkPTE7dGhpcy5zdHJlYW1TaW5rcz1PYmplY3QuY3JlYXRlKG51bGwpO3RoaXMuc3RyZWFtQ29udHJvbGxlcnM9T2JqZWN0LmNyZWF0ZShudWxsKTt0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzPU9iamVjdC5jcmVhdGUobnVsbCk7dGhpcy5hY3Rpb25IYW5kbGVyPU9iamVjdC5jcmVhdGUobnVsbCk7ci5hZGRFdmVudExpc3RlbmVyKCJtZXNzYWdlIix0aGlzLiNvdC5iaW5kKHRoaXMpLHtzaWduYWw6dGhpcy4jc3Quc2lnbmFsfSl9I290KHtkYXRhOmV9KXtpZihlLnRhcmdldE5hbWUhPT10aGlzLnNvdXJjZU5hbWUpcmV0dXJuO2lmKGUuc3RyZWFtKXt0aGlzLiNjdChlKTtyZXR1cm59aWYoZS5jYWxsYmFjayl7Y29uc3QgdD1lLmNhbGxiYWNrSWQscj10aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW3RdO2lmKCFyKXRocm93IG5ldyBFcnJvcihgQ2Fubm90IHJlc29sdmUgY2FsbGJhY2sgJHt0fWApO2RlbGV0ZSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW3RdO2lmKGUuY2FsbGJhY2s9PT1sYylyLnJlc29sdmUoZS5kYXRhKTtlbHNle2lmKGUuY2FsbGJhY2shPT1oYyl0aHJvdyBuZXcgRXJyb3IoIlVuZXhwZWN0ZWQgY2FsbGJhY2sgY2FzZSIpO3IucmVqZWN0KHdyYXBSZWFzb24oZS5yZWFzb24pKX1yZXR1cm59Y29uc3QgdD10aGlzLmFjdGlvbkhhbmRsZXJbZS5hY3Rpb25dO2lmKCF0KXRocm93IG5ldyBFcnJvcihgVW5rbm93biBhY3Rpb24gZnJvbSB3b3JrZXI6ICR7ZS5hY3Rpb259YCk7aWYoZS5jYWxsYmFja0lkKXtjb25zdCByPXRoaXMuc291cmNlTmFtZSxhPWUuc291cmNlTmFtZSxuPXRoaXMuY29tT2JqO1Byb21pc2UudHJ5KHQsZS5kYXRhKS50aGVuKGZ1bmN0aW9uKHQpe24ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsY2FsbGJhY2s6bGMsY2FsbGJhY2tJZDplLmNhbGxiYWNrSWQsZGF0YTp0fSl9LGZ1bmN0aW9uKHQpe24ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsY2FsbGJhY2s6aGMsY2FsbGJhY2tJZDplLmNhbGxiYWNrSWQscmVhc29uOndyYXBSZWFzb24odCl9KX0pO3JldHVybn1lLnN0cmVhbUlkP3RoaXMuI2x0KGUpOnQoZS5kYXRhKX1vbihlLHQpe2NvbnN0IHI9dGhpcy5hY3Rpb25IYW5kbGVyO2lmKHJbZV0pdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBpcyBhbHJlYWR5IGFuIGFjdGlvbk5hbWUgY2FsbGVkICIke2V9ImApO3JbZV09dH1zZW5kKGUsdCxyKXt0aGlzLmNvbU9iai5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTp0aGlzLnNvdXJjZU5hbWUsdGFyZ2V0TmFtZTp0aGlzLnRhcmdldE5hbWUsYWN0aW9uOmUsZGF0YTp0fSxyKX1zZW5kV2l0aFByb21pc2UoZSx0LHIpe2NvbnN0IGE9dGhpcy5jYWxsYmFja0lkKyssbj1Qcm9taXNlLndpdGhSZXNvbHZlcnMoKTt0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2FdPW47dHJ5e3RoaXMuY29tT2JqLnBvc3RNZXNzYWdlKHtzb3VyY2VOYW1lOnRoaXMuc291cmNlTmFtZSx0YXJnZXROYW1lOnRoaXMudGFyZ2V0TmFtZSxhY3Rpb246ZSxjYWxsYmFja0lkOmEsZGF0YTp0fSxyKX1jYXRjaChlKXtuLnJlamVjdChlKX1yZXR1cm4gbi5wcm9taXNlfXNlbmRXaXRoU3RyZWFtKGUsdCxyLGEpe2NvbnN0IG49dGhpcy5zdHJlYW1JZCsrLGk9dGhpcy5zb3VyY2VOYW1lLHM9dGhpcy50YXJnZXROYW1lLG89dGhpcy5jb21PYmo7cmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbSh7c3RhcnQ6cj0+e2NvbnN0IGM9UHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7dGhpcy5zdHJlYW1Db250cm9sbGVyc1tuXT17Y29udHJvbGxlcjpyLHN0YXJ0Q2FsbDpjLHB1bGxDYWxsOm51bGwsY2FuY2VsQ2FsbDpudWxsLGlzQ2xvc2VkOiExfTtvLnBvc3RNZXNzYWdlKHtzb3VyY2VOYW1lOmksdGFyZ2V0TmFtZTpzLGFjdGlvbjplLHN0cmVhbUlkOm4sZGF0YTp0LGRlc2lyZWRTaXplOnIuZGVzaXJlZFNpemV9LGEpO3JldHVybiBjLnByb21pc2V9LHB1bGw6ZT0+e2NvbnN0IHQ9UHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7dGhpcy5zdHJlYW1Db250cm9sbGVyc1tuXS5wdWxsQ2FsbD10O28ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6aSx0YXJnZXROYW1lOnMsc3RyZWFtOm1jLHN0cmVhbUlkOm4sZGVzaXJlZFNpemU6ZS5kZXNpcmVkU2l6ZX0pO3JldHVybiB0LnByb21pc2V9LGNhbmNlbDplPT57YXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwiY2FuY2VsIG11c3QgaGF2ZSBhIHZhbGlkIHJlYXNvbiIpO2NvbnN0IHQ9UHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7dGhpcy5zdHJlYW1Db250cm9sbGVyc1tuXS5jYW5jZWxDYWxsPXQ7dGhpcy5zdHJlYW1Db250cm9sbGVyc1tuXS5pc0Nsb3NlZD0hMDtvLnBvc3RNZXNzYWdlKHtzb3VyY2VOYW1lOmksdGFyZ2V0TmFtZTpzLHN0cmVhbTp1YyxzdHJlYW1JZDpuLHJlYXNvbjp3cmFwUmVhc29uKGUpfSk7cmV0dXJuIHQucHJvbWlzZX19LHIpfSNsdChlKXtjb25zdCB0PWUuc3RyZWFtSWQscj10aGlzLnNvdXJjZU5hbWUsYT1lLnNvdXJjZU5hbWUsbj10aGlzLmNvbU9iaixpPXRoaXMscz10aGlzLmFjdGlvbkhhbmRsZXJbZS5hY3Rpb25dLG89e2VucXVldWUoZSxpPTEscyl7aWYodGhpcy5pc0NhbmNlbGxlZClyZXR1cm47Y29uc3Qgbz10aGlzLmRlc2lyZWRTaXplO3RoaXMuZGVzaXJlZFNpemUtPWk7aWYobz4wJiZ0aGlzLmRlc2lyZWRTaXplPD0wKXt0aGlzLnNpbmtDYXBhYmlsaXR5PVByb21pc2Uud2l0aFJlc29sdmVycygpO3RoaXMucmVhZHk9dGhpcy5zaW5rQ2FwYWJpbGl0eS5wcm9taXNlfW4ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsc3RyZWFtOmdjLHN0cmVhbUlkOnQsY2h1bms6ZX0scyl9LGNsb3NlKCl7aWYoIXRoaXMuaXNDYW5jZWxsZWQpe3RoaXMuaXNDYW5jZWxsZWQ9ITA7bi5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTpyLHRhcmdldE5hbWU6YSxzdHJlYW06ZmMsc3RyZWFtSWQ6dH0pO2RlbGV0ZSBpLnN0cmVhbVNpbmtzW3RdfX0sZXJyb3IoZSl7YXNzZXJ0KGUgaW5zdGFuY2VvZiBFcnJvciwiZXJyb3IgbXVzdCBoYXZlIGEgdmFsaWQgcmVhc29uIik7aWYoIXRoaXMuaXNDYW5jZWxsZWQpe3RoaXMuaXNDYW5jZWxsZWQ9ITA7bi5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTpyLHRhcmdldE5hbWU6YSxzdHJlYW06cGMsc3RyZWFtSWQ6dCxyZWFzb246d3JhcFJlYXNvbihlKX0pfX0sc2lua0NhcGFiaWxpdHk6UHJvbWlzZS53aXRoUmVzb2x2ZXJzKCksb25QdWxsOm51bGwsb25DYW5jZWw6bnVsbCxpc0NhbmNlbGxlZDohMSxkZXNpcmVkU2l6ZTplLmRlc2lyZWRTaXplLHJlYWR5Om51bGx9O28uc2lua0NhcGFiaWxpdHkucmVzb2x2ZSgpO28ucmVhZHk9by5zaW5rQ2FwYWJpbGl0eS5wcm9taXNlO3RoaXMuc3RyZWFtU2lua3NbdF09bztQcm9taXNlLnRyeShzLGUuZGF0YSxvKS50aGVuKGZ1bmN0aW9uKCl7bi5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTpyLHRhcmdldE5hbWU6YSxzdHJlYW06eWMsc3RyZWFtSWQ6dCxzdWNjZXNzOiEwfSl9LGZ1bmN0aW9uKGUpe24ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsc3RyZWFtOnljLHN0cmVhbUlkOnQscmVhc29uOndyYXBSZWFzb24oZSl9KX0pfSNjdChlKXtjb25zdCB0PWUuc3RyZWFtSWQscj10aGlzLnNvdXJjZU5hbWUsYT1lLnNvdXJjZU5hbWUsbj10aGlzLmNvbU9iaixpPXRoaXMuc3RyZWFtQ29udHJvbGxlcnNbdF0scz10aGlzLnN0cmVhbVNpbmtzW3RdO3N3aXRjaChlLnN0cmVhbSl7Y2FzZSB5YzplLnN1Y2Nlc3M/aS5zdGFydENhbGwucmVzb2x2ZSgpOmkuc3RhcnRDYWxsLnJlamVjdCh3cmFwUmVhc29uKGUucmVhc29uKSk7YnJlYWs7Y2FzZSBiYzplLnN1Y2Nlc3M/aS5wdWxsQ2FsbC5yZXNvbHZlKCk6aS5wdWxsQ2FsbC5yZWplY3Qod3JhcFJlYXNvbihlLnJlYXNvbikpO2JyZWFrO2Nhc2UgbWM6aWYoIXMpe24ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsc3RyZWFtOmJjLHN0cmVhbUlkOnQsc3VjY2VzczohMH0pO2JyZWFrfXMuZGVzaXJlZFNpemU8PTAmJmUuZGVzaXJlZFNpemU+MCYmcy5zaW5rQ2FwYWJpbGl0eS5yZXNvbHZlKCk7cy5kZXNpcmVkU2l6ZT1lLmRlc2lyZWRTaXplO1Byb21pc2UudHJ5KHMub25QdWxsfHxvbkZuKS50aGVuKGZ1bmN0aW9uKCl7bi5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTpyLHRhcmdldE5hbWU6YSxzdHJlYW06YmMsc3RyZWFtSWQ6dCxzdWNjZXNzOiEwfSl9LGZ1bmN0aW9uKGUpe24ucG9zdE1lc3NhZ2Uoe3NvdXJjZU5hbWU6cix0YXJnZXROYW1lOmEsc3RyZWFtOmJjLHN0cmVhbUlkOnQscmVhc29uOndyYXBSZWFzb24oZSl9KX0pO2JyZWFrO2Nhc2UgZ2M6YXNzZXJ0KGksImVucXVldWUgc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTtpZihpLmlzQ2xvc2VkKWJyZWFrO2kuY29udHJvbGxlci5lbnF1ZXVlKGUuY2h1bmspO2JyZWFrO2Nhc2UgZmM6YXNzZXJ0KGksImNsb3NlIHNob3VsZCBoYXZlIHN0cmVhbSBjb250cm9sbGVyIik7aWYoaS5pc0Nsb3NlZClicmVhaztpLmlzQ2xvc2VkPSEwO2kuY29udHJvbGxlci5jbG9zZSgpO3RoaXMuI2h0KGksdCk7YnJlYWs7Y2FzZSBwYzphc3NlcnQoaSwiZXJyb3Igc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTtpLmNvbnRyb2xsZXIuZXJyb3Iod3JhcFJlYXNvbihlLnJlYXNvbikpO3RoaXMuI2h0KGksdCk7YnJlYWs7Y2FzZSBkYzplLnN1Y2Nlc3M/aS5jYW5jZWxDYWxsLnJlc29sdmUoKTppLmNhbmNlbENhbGwucmVqZWN0KHdyYXBSZWFzb24oZS5yZWFzb24pKTt0aGlzLiNodChpLHQpO2JyZWFrO2Nhc2UgdWM6aWYoIXMpYnJlYWs7Y29uc3Qgbz13cmFwUmVhc29uKGUucmVhc29uKTtQcm9taXNlLnRyeShzLm9uQ2FuY2VsfHxvbkZuLG8pLnRoZW4oZnVuY3Rpb24oKXtuLnBvc3RNZXNzYWdlKHtzb3VyY2VOYW1lOnIsdGFyZ2V0TmFtZTphLHN0cmVhbTpkYyxzdHJlYW1JZDp0LHN1Y2Nlc3M6ITB9KX0sZnVuY3Rpb24oZSl7bi5wb3N0TWVzc2FnZSh7c291cmNlTmFtZTpyLHRhcmdldE5hbWU6YSxzdHJlYW06ZGMsc3RyZWFtSWQ6dCxyZWFzb246d3JhcFJlYXNvbihlKX0pfSk7cy5zaW5rQ2FwYWJpbGl0eS5yZWplY3Qobyk7cy5pc0NhbmNlbGxlZD0hMDtkZWxldGUgdGhpcy5zdHJlYW1TaW5rc1t0XTticmVhaztkZWZhdWx0OnRocm93IG5ldyBFcnJvcigiVW5leHBlY3RlZCBzdHJlYW0gY2FzZSIpfX1hc3luYyNodChlLHQpe2F3YWl0IFByb21pc2UuYWxsU2V0dGxlZChbZS5zdGFydENhbGw/LnByb21pc2UsZS5wdWxsQ2FsbD8ucHJvbWlzZSxlLmNhbmNlbENhbGw/LnByb21pc2VdKTtkZWxldGUgdGhpcy5zdHJlYW1Db250cm9sbGVyc1t0XX1kZXN0cm95KCl7dGhpcy4jc3Q/LmFib3J0KCk7dGhpcy4jc3Q9bnVsbH19YXN5bmMgZnVuY3Rpb24gd3JpdGVPYmplY3QoZSx0LHIse2VuY3J5cHQ6YT1udWxsfSl7Y29uc3Qgbj1hPy5jcmVhdGVDaXBoZXJUcmFuc2Zvcm0oZS5udW0sZS5nZW4pO3IucHVzaChgJHtlLm51bX0gJHtlLmdlbn0gb2JqXG5gKTt0IGluc3RhbmNlb2YgRGljdD9hd2FpdCB3cml0ZURpY3QodCxyLG4pOnQgaW5zdGFuY2VvZiBCYXNlU3RyZWFtP2F3YWl0IHdyaXRlU3RyZWFtKHQscixuKTooQXJyYXkuaXNBcnJheSh0KXx8QXJyYXlCdWZmZXIuaXNWaWV3KHQpKSYmYXdhaXQgd3JpdGVBcnJheSh0LHIsbik7ci5wdXNoKCJcbmVuZG9ialxuIil9YXN5bmMgZnVuY3Rpb24gd3JpdGVEaWN0KGUsdCxyKXt0LnB1c2goIjw8Iik7Zm9yKGNvbnN0IGEgb2YgZS5nZXRLZXlzKCkpe3QucHVzaChgIC8ke2VzY2FwZVBERk5hbWUoYSl9IGApO2F3YWl0IHdyaXRlVmFsdWUoZS5nZXRSYXcoYSksdCxyKX10LnB1c2goIj4+Iil9YXN5bmMgZnVuY3Rpb24gd3JpdGVTdHJlYW0oZSx0LHIpe2xldCBhPWUuZ2V0Qnl0ZXMoKTtjb25zdHtkaWN0Om59PWUsW2ksc109YXdhaXQgUHJvbWlzZS5hbGwoW24uZ2V0QXN5bmMoIkZpbHRlciIpLG4uZ2V0QXN5bmMoIkRlY29kZVBhcm1zIildKSxvPWlzTmFtZShBcnJheS5pc0FycmF5KGkpP2F3YWl0IG4ueHJlZi5mZXRjaElmUmVmQXN5bmMoaVswXSk6aSwiRmxhdGVEZWNvZGUiKTtpZihhLmxlbmd0aD49MjU2fHxvKXRyeXtjb25zdCBlPW5ldyBDb21wcmVzc2lvblN0cmVhbSgiZGVmbGF0ZSIpLHQ9ZS53cml0YWJsZS5nZXRXcml0ZXIoKTthd2FpdCB0LnJlYWR5O3Qud3JpdGUoYSkudGhlbihhc3luYygpPT57YXdhaXQgdC5yZWFkeTthd2FpdCB0LmNsb3NlKCl9KS5jYXRjaCgoKT0+e30pO2NvbnN0IHI9YXdhaXQgbmV3IFJlc3BvbnNlKGUucmVhZGFibGUpLmFycmF5QnVmZmVyKCk7YT1uZXcgVWludDhBcnJheShyKTtsZXQgYyxsO2lmKGkpe2lmKCFvKXtjPUFycmF5LmlzQXJyYXkoaSk/W05hbWUuZ2V0KCJGbGF0ZURlY29kZSIpLC4uLmldOltOYW1lLmdldCgiRmxhdGVEZWNvZGUiKSxpXTtzJiYobD1BcnJheS5pc0FycmF5KHMpP1tudWxsLC4uLnNdOltudWxsLHNdKX19ZWxzZSBjPU5hbWUuZ2V0KCJGbGF0ZURlY29kZSIpO2MmJm4uc2V0KCJGaWx0ZXIiLGMpO2wmJm4uc2V0KCJEZWNvZGVQYXJtcyIsbCl9Y2F0Y2goZSl7aW5mbyhgd3JpdGVTdHJlYW0gLSBjYW5ub3QgY29tcHJlc3MgZGF0YTogIiR7ZX0iLmApfWxldCBjPWJ5dGVzVG9TdHJpbmcoYSk7ciYmKGM9ci5lbmNyeXB0U3RyaW5nKGMpKTtuLnNldCgiTGVuZ3RoIixjLmxlbmd0aCk7YXdhaXQgd3JpdGVEaWN0KG4sdCxyKTt0LnB1c2goIiBzdHJlYW1cbiIsYywiXG5lbmRzdHJlYW0iKX1hc3luYyBmdW5jdGlvbiB3cml0ZUFycmF5KGUsdCxyKXt0LnB1c2goIlsiKTtsZXQgYT0hMDtmb3IoY29uc3QgbiBvZiBlKXthP2E9ITE6dC5wdXNoKCIgIik7YXdhaXQgd3JpdGVWYWx1ZShuLHQscil9dC5wdXNoKCJdIil9YXN5bmMgZnVuY3Rpb24gd3JpdGVWYWx1ZShlLHQscil7aWYoZSBpbnN0YW5jZW9mIE5hbWUpdC5wdXNoKGAvJHtlc2NhcGVQREZOYW1lKGUubmFtZSl9YCk7ZWxzZSBpZihlIGluc3RhbmNlb2YgUmVmKXQucHVzaChgJHtlLm51bX0gJHtlLmdlbn0gUmApO2Vsc2UgaWYoQXJyYXkuaXNBcnJheShlKXx8QXJyYXlCdWZmZXIuaXNWaWV3KGUpKWF3YWl0IHdyaXRlQXJyYXkoZSx0LHIpO2Vsc2UgaWYoInN0cmluZyI9PXR5cGVvZiBlKXtyJiYoZT1yLmVuY3J5cHRTdHJpbmcoZSkpO3QucHVzaChgKCR7ZXNjYXBlU3RyaW5nKGUpfSlgKX1lbHNlIm51bWJlciI9PXR5cGVvZiBlP3QucHVzaChudW1iZXJUb1N0cmluZyhlKSk6ImJvb2xlYW4iPT10eXBlb2YgZT90LnB1c2goZS50b1N0cmluZygpKTplIGluc3RhbmNlb2YgRGljdD9hd2FpdCB3cml0ZURpY3QoZSx0LHIpOmUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtP2F3YWl0IHdyaXRlU3RyZWFtKGUsdCxyKTpudWxsPT09ZT90LnB1c2goIm51bGwiKTp3YXJuKGBVbmhhbmRsZWQgdmFsdWUgaW4gd3JpdGVyOiAke3R5cGVvZiBlfSwgcGxlYXNlIGZpbGUgYSBidWcuYCl9ZnVuY3Rpb24gd3JpdGVJbnQoZSx0LHIsYSl7Zm9yKGxldCBuPXQrci0xO24+ci0xO24tLSl7YVtuXT0yNTUmZTtlPj49OH1yZXR1cm4gcit0fWZ1bmN0aW9uIHdyaXRlU3RyaW5nKGUsdCxyKXtjb25zdCBhPWUubGVuZ3RoO2ZvcihsZXQgbj0wO248YTtuKyspclt0K25dPTI1NSZlLmNoYXJDb2RlQXQobik7cmV0dXJuIHQrYX1mdW5jdGlvbiB1cGRhdGVYRkEoe3hmYURhdGE6ZSx4ZmFEYXRhc2V0c1JlZjp0LGNoYW5nZXM6cix4cmVmOmF9KXtpZihudWxsPT09ZSl7ZT1mdW5jdGlvbiB3cml0ZVhGQURhdGFGb3JBY3JvZm9ybShlLHQpe2NvbnN0IHI9bmV3IFNpbXBsZVhNTFBhcnNlcih7aGFzQXR0cmlidXRlczohMH0pLnBhcnNlRnJvbVN0cmluZyhlKTtmb3IoY29uc3R7eGZhOmV9b2YgdCl7aWYoIWUpY29udGludWU7Y29uc3R7cGF0aDp0LHZhbHVlOmF9PWU7aWYoIXQpY29udGludWU7Y29uc3Qgbj1wYXJzZVhGQVBhdGgodCk7bGV0IGk9ci5kb2N1bWVudEVsZW1lbnQuc2VhcmNoTm9kZShuLDApOyFpJiZuLmxlbmd0aD4xJiYoaT1yLmRvY3VtZW50RWxlbWVudC5zZWFyY2hOb2RlKFtuLmF0KC0xKV0sMCkpO2k/aS5jaGlsZE5vZGVzPUFycmF5LmlzQXJyYXkoYSk/YS5tYXAoZT0+bmV3IFNpbXBsZURPTU5vZGUoInZhbHVlIixlKSk6W25ldyBTaW1wbGVET01Ob2RlKCIjdGV4dCIsYSldOndhcm4oYE5vZGUgbm90IGZvdW5kIGZvciBwYXRoOiAke3R9YCl9Y29uc3QgYT1bXTtyLmRvY3VtZW50RWxlbWVudC5kdW1wKGEpO3JldHVybiBhLmpvaW4oIiIpfShhLmZldGNoSWZSZWYodCkuZ2V0U3RyaW5nKCkscil9Y29uc3Qgbj1uZXcgU3RyaW5nU3RyZWFtKGUpO24uZGljdD1uZXcgRGljdChhKTtuLmRpY3Quc2V0SWZOYW1lKCJUeXBlIiwiRW1iZWRkZWRGaWxlIik7ci5wdXQodCx7ZGF0YTpufSl9ZnVuY3Rpb24gZ2V0SW5kZXhlcyhlKXtjb25zdCB0PVtdO2Zvcihjb25zdHtyZWY6cn1vZiBlKXIubnVtPT09dC5hdCgtMikrdC5hdCgtMSk/dFt0Lmxlbmd0aC0xXSs9MTp0LnB1c2goci5udW0sMSk7cmV0dXJuIHR9ZnVuY3Rpb24gY29tcHV0ZUlEcyhlLHQscil7aWYoQXJyYXkuaXNBcnJheSh0LmZpbGVJZHMpJiZ0LmZpbGVJZHMubGVuZ3RoPjApe2NvbnN0IGE9ZnVuY3Rpb24gY29tcHV0ZU1ENShlLHQpe2NvbnN0IHI9TWF0aC5mbG9vcihEYXRlLm5vdygpLzFlMyksYT10LmZpbGVuYW1lfHwiIixuPVtyLnRvU3RyaW5nKCksYSxlLnRvU3RyaW5nKCksLi4udC5pbmZvTWFwLnZhbHVlcygpXSxpPU1hdGguc3VtUHJlY2lzZShuLm1hcChlPT5lLmxlbmd0aCkpLHM9bmV3IFVpbnQ4QXJyYXkoaSk7bGV0IG89MDtmb3IoY29uc3QgZSBvZiBuKW89d3JpdGVTdHJpbmcoZSxvLHMpO3JldHVybiBieXRlc1RvU3RyaW5nKGNhbGN1bGF0ZU1ENShzLDAscy5sZW5ndGgpKX0oZSx0KTtyLnNldCgiSUQiLFt0LmZpbGVJZHNbMF0sYV0pfX1hc3luYyBmdW5jdGlvbiBpbmNyZW1lbnRhbFVwZGF0ZSh7b3JpZ2luYWxEYXRhOmUseHJlZkluZm86dCxjaGFuZ2VzOnIseHJlZjphPW51bGwsaGFzWGZhOm49ITEseGZhRGF0YXNldHNSZWY6aT1udWxsLGhhc1hmYURhdGFzZXRzRW50cnk6cz0hMSxuZWVkQXBwZWFyYW5jZXM6byxhY3JvRm9ybVJlZjpjPW51bGwsYWNyb0Zvcm06bD1udWxsLHhmYURhdGE6aD1udWxsLHVzZVhyZWZTdHJlYW06dT0hMX0pe2F3YWl0IGFzeW5jIGZ1bmN0aW9uIHVwZGF0ZUFjcm9mb3JtKHt4cmVmOmUsYWNyb0Zvcm06dCxhY3JvRm9ybVJlZjpyLGhhc1hmYTphLGhhc1hmYURhdGFzZXRzRW50cnk6bix4ZmFEYXRhc2V0c1JlZjppLG5lZWRBcHBlYXJhbmNlczpzLGNoYW5nZXM6b30peyFhfHxufHxpfHx3YXJuKCJYRkEgLSBDYW5ub3Qgc2F2ZSBpdCIpO2lmKCFzJiYoIWF8fCFpfHxuKSlyZXR1cm47Y29uc3QgYz10LmNsb25lKCk7aWYoYSYmIW4pe2NvbnN0IGU9dC5nZXQoIlhGQSIpLnNsaWNlKCk7ZS5zcGxpY2UoMiwwLCJkYXRhc2V0cyIpO2Uuc3BsaWNlKDMsMCxpKTtjLnNldCgiWEZBIixlKX1zJiZjLnNldCgiTmVlZEFwcGVhcmFuY2VzIiwhMCk7by5wdXQocix7ZGF0YTpjfSl9KHt4cmVmOmEsYWNyb0Zvcm06bCxhY3JvRm9ybVJlZjpjLGhhc1hmYTpuLGhhc1hmYURhdGFzZXRzRW50cnk6cyx4ZmFEYXRhc2V0c1JlZjppLG5lZWRBcHBlYXJhbmNlczpvLGNoYW5nZXM6cn0pO24mJnVwZGF0ZVhGQSh7eGZhRGF0YTpoLHhmYURhdGFzZXRzUmVmOmksY2hhbmdlczpyLHhyZWY6YX0pO2NvbnN0IGQ9ZnVuY3Rpb24gZ2V0VHJhaWxlckRpY3QoZSx0LHIpe2NvbnN0IGE9bmV3IERpY3QobnVsbCk7YS5zZXQoIlByZXYiLGUuc3RhcnRYUmVmKTtjb25zdCBuPWUubmV3UmVmO2lmKHIpe3QucHV0KG4se2RhdGE6IiJ9KTthLnNldCgiU2l6ZSIsbi5udW0rMSk7YS5zZXRJZk5hbWUoIlR5cGUiLCJYUmVmIil9ZWxzZSBhLnNldCgiU2l6ZSIsbi5udW0pO251bGwhPT1lLnJvb3RSZWYmJmEuc2V0KCJSb290IixlLnJvb3RSZWYpO251bGwhPT1lLmluZm9SZWYmJmEuc2V0KCJJbmZvIixlLmluZm9SZWYpO251bGwhPT1lLmVuY3J5cHRSZWYmJmEuc2V0KCJFbmNyeXB0IixlLmVuY3J5cHRSZWYpO3JldHVybiBhfSh0LHIsdSksZj1bXSxnPWF3YWl0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlQ2hhbmdlcyhlLHQscj1bXSl7Y29uc3QgYT1bXTtmb3IoY29uc3Rbbix7ZGF0YTppfV1vZiBlLml0ZW1zKCkpaWYobnVsbCE9PWkmJiJzdHJpbmciIT10eXBlb2YgaSl7YXdhaXQgd3JpdGVPYmplY3QobixpLHIsdCk7YS5wdXNoKHtyZWY6bixkYXRhOnIuam9pbigiIil9KTtyLmxlbmd0aD0wfWVsc2UgYS5wdXNoKHtyZWY6bixkYXRhOml9KTtyZXR1cm4gYS5zb3J0KChlLHQpPT5lLnJlZi5udW0tdC5yZWYubnVtKX0ocixhLGYpO2xldCBwPWUubGVuZ3RoO2NvbnN0IG09ZS5hdCgtMSk7aWYoMTAhPT1tJiYxMyE9PW0pe2YucHVzaCgiXG4iKTtwKz0xfWZvcihjb25zdHtkYXRhOmV9b2YgZyludWxsIT09ZSYmZi5wdXNoKGUpO2F3YWl0KHU/YXN5bmMgZnVuY3Rpb24gZ2V0WFJlZlN0cmVhbVRhYmxlKGUsdCxyLGEsbil7Y29uc3QgaT1bXTtsZXQgcz0wLG89MDtmb3IoY29uc3R7cmVmOmUsZGF0YTphfW9mIHIpe2xldCByO3M9TWF0aC5tYXgocyx0KTtpZihudWxsIT09YSl7cj1NYXRoLm1pbihlLmdlbiw2NTUzNSk7aS5wdXNoKFsxLHQscl0pO3QrPWEubGVuZ3RofWVsc2V7cj1NYXRoLm1pbihlLmdlbisxLDY1NTM1KTtpLnB1c2goWzAsMCxyXSl9bz1NYXRoLm1heChvLHIpfWEuc2V0KCJJbmRleCIsZ2V0SW5kZXhlcyhyKSk7Y29uc3QgYz1bMSxnZXRTaXplSW5CeXRlcyhzKSxnZXRTaXplSW5CeXRlcyhvKV07YS5zZXQoIlciLGMpO2NvbXB1dGVJRHModCxlLGEpO2NvbnN0IGw9TWF0aC5zdW1QcmVjaXNlKGMpLGg9bmV3IFVpbnQ4QXJyYXkobCppLmxlbmd0aCksdT1uZXcgU3RyZWFtKGgpO3UuZGljdD1hO2xldCBkPTA7Zm9yKGNvbnN0W2UsdCxyXW9mIGkpe2Q9d3JpdGVJbnQoZSxjWzBdLGQsaCk7ZD13cml0ZUludCh0LGNbMV0sZCxoKTtkPXdyaXRlSW50KHIsY1syXSxkLGgpfWF3YWl0IHdyaXRlT2JqZWN0KGUubmV3UmVmLHUsbix7fSk7bi5wdXNoKCJzdGFydHhyZWZcbiIsdC50b1N0cmluZygpLCJcbiUlRU9GXG4iKX0odCxwLGcsZCxmKTphc3luYyBmdW5jdGlvbiBnZXRYUmVmVGFibGUoZSx0LHIsYSxuKXtuLnB1c2goInhyZWZcbiIpO2NvbnN0IGk9Z2V0SW5kZXhlcyhyKTtsZXQgcz0wO2Zvcihjb25zdHtyZWY6ZSxkYXRhOmF9b2Ygcil7aWYoZS5udW09PT1pW3NdKXtuLnB1c2goYCR7aVtzXX0gJHtpW3MrMV19XG5gKTtzKz0yfWlmKG51bGwhPT1hKXtuLnB1c2goYCR7dC50b1N0cmluZygpLnBhZFN0YXJ0KDEwLCIwIil9ICR7TWF0aC5taW4oZS5nZW4sNjU1MzUpLnRvU3RyaW5nKCkucGFkU3RhcnQoNSwiMCIpfSBuXHJcbmApO3QrPWEubGVuZ3RofWVsc2Ugbi5wdXNoKGAwMDAwMDAwMDAwICR7TWF0aC5taW4oZS5nZW4rMSw2NTUzNSkudG9TdHJpbmcoKS5wYWRTdGFydCg1LCIwIil9IGZcclxuYCl9Y29tcHV0ZUlEcyh0LGUsYSk7bi5wdXNoKCJ0cmFpbGVyXG4iKTthd2FpdCB3cml0ZURpY3QoYSxuKTtuLnB1c2goIlxuc3RhcnR4cmVmXG4iLHQudG9TdHJpbmcoKSwiXG4lJUVPRlxuIil9KHQscCxnLGQsZikpO2NvbnN0IGI9ZS5sZW5ndGgrTWF0aC5zdW1QcmVjaXNlKGYubWFwKGU9PmUubGVuZ3RoKSkseT1uZXcgVWludDhBcnJheShiKTt5LnNldChlKTtsZXQgdz1lLmxlbmd0aDtmb3IoY29uc3QgZSBvZiBmKXc9d3JpdGVTdHJpbmcoZSx3LHkpO3JldHVybiB5fWNsYXNzIFBERldvcmtlclN0cmVhbXtjb25zdHJ1Y3RvcihlKXt0aGlzLl9tc2dIYW5kbGVyPWU7dGhpcy5fY29udGVudExlbmd0aD1udWxsO3RoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyPW51bGw7dGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycz1bXX1nZXRGdWxsUmVhZGVyKCl7YXNzZXJ0KCF0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciwiUERGV29ya2VyU3RyZWFtLmdldEZ1bGxSZWFkZXIgY2FuIG9ubHkgYmUgY2FsbGVkIG9uY2UuIik7dGhpcy5fZnVsbFJlcXVlc3RSZWFkZXI9bmV3IFBERldvcmtlclN0cmVhbVJlYWRlcih0aGlzLl9tc2dIYW5kbGVyKTtyZXR1cm4gdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXJ9Z2V0UmFuZ2VSZWFkZXIoZSx0KXtjb25zdCByPW5ldyBQREZXb3JrZXJTdHJlYW1SYW5nZVJlYWRlcihlLHQsdGhpcy5fbXNnSGFuZGxlcik7dGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycy5wdXNoKHIpO3JldHVybiByfWNhbmNlbEFsbFJlcXVlc3RzKGUpe3RoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyPy5jYW5jZWwoZSk7Zm9yKGNvbnN0IHQgb2YgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycy5zbGljZSgwKSl0LmNhbmNlbChlKX19Y2xhc3MgUERGV29ya2VyU3RyZWFtUmVhZGVye2NvbnN0cnVjdG9yKGUpe3RoaXMuX21zZ0hhbmRsZXI9ZTt0aGlzLm9uUHJvZ3Jlc3M9bnVsbDt0aGlzLl9jb250ZW50TGVuZ3RoPW51bGw7dGhpcy5faXNSYW5nZVN1cHBvcnRlZD0hMTt0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZD0hMTtjb25zdCB0PXRoaXMuX21zZ0hhbmRsZXIuc2VuZFdpdGhTdHJlYW0oIkdldFJlYWRlciIpO3RoaXMuX3JlYWRlcj10LmdldFJlYWRlcigpO3RoaXMuX2hlYWRlcnNSZWFkeT10aGlzLl9tc2dIYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiUmVhZGVySGVhZGVyc1JlYWR5IikudGhlbihlPT57dGhpcy5faXNTdHJlYW1pbmdTdXBwb3J0ZWQ9ZS5pc1N0cmVhbWluZ1N1cHBvcnRlZDt0aGlzLl9pc1JhbmdlU3VwcG9ydGVkPWUuaXNSYW5nZVN1cHBvcnRlZDt0aGlzLl9jb250ZW50TGVuZ3RoPWUuY29udGVudExlbmd0aH0pfWdldCBoZWFkZXJzUmVhZHkoKXtyZXR1cm4gdGhpcy5faGVhZGVyc1JlYWR5fWdldCBjb250ZW50TGVuZ3RoKCl7cmV0dXJuIHRoaXMuX2NvbnRlbnRMZW5ndGh9Z2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCl7cmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkfWdldCBpc1JhbmdlU3VwcG9ydGVkKCl7cmV0dXJuIHRoaXMuX2lzUmFuZ2VTdXBwb3J0ZWR9YXN5bmMgcmVhZCgpe2NvbnN0e3ZhbHVlOmUsZG9uZTp0fT1hd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpO3JldHVybiB0P3t2YWx1ZTp2b2lkIDAsZG9uZTohMH06e3ZhbHVlOmUuYnVmZmVyLGRvbmU6ITF9fWNhbmNlbChlKXt0aGlzLl9yZWFkZXIuY2FuY2VsKGUpfX1jbGFzcyBQREZXb3JrZXJTdHJlYW1SYW5nZVJlYWRlcntjb25zdHJ1Y3RvcihlLHQscil7dGhpcy5fbXNnSGFuZGxlcj1yO3RoaXMub25Qcm9ncmVzcz1udWxsO2NvbnN0IGE9dGhpcy5fbXNnSGFuZGxlci5zZW5kV2l0aFN0cmVhbSgiR2V0UmFuZ2VSZWFkZXIiLHtiZWdpbjplLGVuZDp0fSk7dGhpcy5fcmVhZGVyPWEuZ2V0UmVhZGVyKCl9Z2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCl7cmV0dXJuITF9YXN5bmMgcmVhZCgpe2NvbnN0e3ZhbHVlOmUsZG9uZTp0fT1hd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpO3JldHVybiB0P3t2YWx1ZTp2b2lkIDAsZG9uZTohMH06e3ZhbHVlOmUuYnVmZmVyLGRvbmU6ITF9fWNhbmNlbChlKXt0aGlzLl9yZWFkZXIuY2FuY2VsKGUpfX1jbGFzcyBXb3JrZXJUYXNre2NvbnN0cnVjdG9yKGUpe3RoaXMubmFtZT1lO3RoaXMudGVybWluYXRlZD0hMTt0aGlzLl9jYXBhYmlsaXR5PVByb21pc2Uud2l0aFJlc29sdmVycygpfWdldCBmaW5pc2hlZCgpe3JldHVybiB0aGlzLl9jYXBhYmlsaXR5LnByb21pc2V9ZmluaXNoKCl7dGhpcy5fY2FwYWJpbGl0eS5yZXNvbHZlKCl9dGVybWluYXRlKCl7dGhpcy50ZXJtaW5hdGVkPSEwfWVuc3VyZU5vdFRlcm1pbmF0ZWQoKXtpZih0aGlzLnRlcm1pbmF0ZWQpdGhyb3cgbmV3IEVycm9yKCJXb3JrZXIgdGFzayB3YXMgdGVybWluYXRlZCIpfX1jbGFzcyBXb3JrZXJNZXNzYWdlSGFuZGxlcntzdGF0aWN7InVuZGVmaW5lZCI9PXR5cGVvZiB3aW5kb3cmJiFyJiYidW5kZWZpbmVkIiE9dHlwZW9mIHNlbGYmJiJmdW5jdGlvbiI9PXR5cGVvZiBzZWxmLnBvc3RNZXNzYWdlJiYib25tZXNzYWdlImluIHNlbGYmJnRoaXMuaW5pdGlhbGl6ZUZyb21Qb3J0KHNlbGYpfXN0YXRpYyBzZXR1cChlLHQpe2xldCByPSExO2Uub24oInRlc3QiLHQ9PntpZighcil7cj0hMDtlLnNlbmQoInRlc3QiLHQgaW5zdGFuY2VvZiBVaW50OEFycmF5KX19KTtlLm9uKCJjb25maWd1cmUiLGU9PnshZnVuY3Rpb24gc2V0VmVyYm9zaXR5TGV2ZWwoZSl7TnVtYmVyLmlzSW50ZWdlcihlKSYmKFF0PWUpfShlLnZlcmJvc2l0eSl9KTtlLm9uKCJHZXREb2NSZXF1ZXN0IixlPT50aGlzLmNyZWF0ZURvY3VtZW50SGFuZGxlcihlLHQpKX1zdGF0aWMgY3JlYXRlRG9jdW1lbnRIYW5kbGVyKGUsdCl7bGV0IHIsYT0hMSxuPW51bGw7Y29uc3QgaT1uZXcgU2V0LHM9Z2V0VmVyYm9zaXR5TGV2ZWwoKSx7ZG9jSWQ6byxhcGlWZXJzaW9uOmN9PWUsbD0iNS40LjI5NiI7aWYoYyE9PWwpdGhyb3cgbmV3IEVycm9yKGBUaGUgQVBJIHZlcnNpb24gIiR7Y30iIGRvZXMgbm90IG1hdGNoIHRoZSBXb3JrZXIgdmVyc2lvbiAiJHtsfSIuYCk7Y29uc3QgYnVpbGRNc2c9KGUsdCk9PmBUaGUgXGAke2V9LnByb3RvdHlwZVxgIGNvbnRhaW5zIHVuZXhwZWN0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSAiJHt0fSIsIHRodXMgYnJlYWtpbmcgZS5nLiBcYGZvci4uLmluXGAgaXRlcmF0aW9uIG9mICR7ZX1zLmA7Zm9yKGNvbnN0IGUgaW57fSl0aHJvdyBuZXcgRXJyb3IoYnVpbGRNc2coIk9iamVjdCIsZSkpO2Zvcihjb25zdCBlIGluW10pdGhyb3cgbmV3IEVycm9yKGJ1aWxkTXNnKCJBcnJheSIsZSkpO2NvbnN0IGg9bysiX3dvcmtlciI7bGV0IHU9bmV3IE1lc3NhZ2VIYW5kbGVyKGgsbyx0KTtmdW5jdGlvbiBlbnN1cmVOb3RUZXJtaW5hdGVkKCl7aWYoYSl0aHJvdyBuZXcgRXJyb3IoIldvcmtlciB3YXMgdGVybWluYXRlZCIpfWZ1bmN0aW9uIHN0YXJ0V29ya2VyVGFzayhlKXtpLmFkZChlKX1mdW5jdGlvbiBmaW5pc2hXb3JrZXJUYXNrKGUpe2UuZmluaXNoKCk7aS5kZWxldGUoZSl9YXN5bmMgZnVuY3Rpb24gbG9hZERvY3VtZW50KGUpe2F3YWl0IHIuZW5zdXJlRG9jKCJjaGVja0hlYWRlciIpO2F3YWl0IHIuZW5zdXJlRG9jKCJwYXJzZVN0YXJ0WFJlZiIpO2F3YWl0IHIuZW5zdXJlRG9jKCJwYXJzZSIsW2VdKTthd2FpdCByLmVuc3VyZURvYygiY2hlY2tGaXJzdFBhZ2UiLFtlXSk7YXdhaXQgci5lbnN1cmVEb2MoImNoZWNrTGFzdFBhZ2UiLFtlXSk7Y29uc3QgdD1hd2FpdCByLmVuc3VyZURvYygiaXNQdXJlWGZhIik7aWYodCl7Y29uc3QgZT1uZXcgV29ya2VyVGFzaygibG9hZFhmYVJlc291cmNlcyIpO3N0YXJ0V29ya2VyVGFzayhlKTthd2FpdCByLmVuc3VyZURvYygibG9hZFhmYVJlc291cmNlcyIsW3UsZV0pO2ZpbmlzaFdvcmtlclRhc2soZSl9Y29uc3RbYSxuXT1hd2FpdCBQcm9taXNlLmFsbChbci5lbnN1cmVEb2MoIm51bVBhZ2VzIiksci5lbnN1cmVEb2MoImZpbmdlcnByaW50cyIpXSk7cmV0dXJue251bVBhZ2VzOmEsZmluZ2VycHJpbnRzOm4saHRtbEZvclhmYTp0P2F3YWl0IHIuZW5zdXJlRG9jKCJodG1sRm9yWGZhIik6bnVsbH19ZnVuY3Rpb24gc2V0dXBEb2MoZSl7ZnVuY3Rpb24gb25TdWNjZXNzKGUpe2Vuc3VyZU5vdFRlcm1pbmF0ZWQoKTt1LnNlbmQoIkdldERvYyIse3BkZkluZm86ZX0pfWZ1bmN0aW9uIG9uRmFpbHVyZShlKXtlbnN1cmVOb3RUZXJtaW5hdGVkKCk7aWYoZSBpbnN0YW5jZW9mIFBhc3N3b3JkRXhjZXB0aW9uKXtjb25zdCB0PW5ldyBXb3JrZXJUYXNrKGBQYXNzd29yZEV4Y2VwdGlvbjogcmVzcG9uc2UgJHtlLmNvZGV9YCk7c3RhcnRXb3JrZXJUYXNrKHQpO3Uuc2VuZFdpdGhQcm9taXNlKCJQYXNzd29yZFJlcXVlc3QiLGUpLnRoZW4oZnVuY3Rpb24oe3Bhc3N3b3JkOmV9KXtmaW5pc2hXb3JrZXJUYXNrKHQpO3IudXBkYXRlUGFzc3dvcmQoZSk7cGRmTWFuYWdlclJlYWR5KCl9KS5jYXRjaChmdW5jdGlvbigpe2ZpbmlzaFdvcmtlclRhc2sodCk7dS5zZW5kKCJEb2NFeGNlcHRpb24iLGUpfSl9ZWxzZSB1LnNlbmQoIkRvY0V4Y2VwdGlvbiIsd3JhcFJlYXNvbihlKSl9ZnVuY3Rpb24gcGRmTWFuYWdlclJlYWR5KCl7ZW5zdXJlTm90VGVybWluYXRlZCgpO2xvYWREb2N1bWVudCghMSkudGhlbihvblN1Y2Nlc3MsZnVuY3Rpb24oZSl7ZW5zdXJlTm90VGVybWluYXRlZCgpO2UgaW5zdGFuY2VvZiBYUmVmUGFyc2VFeGNlcHRpb24/ci5yZXF1ZXN0TG9hZGVkU3RyZWFtKCkudGhlbihmdW5jdGlvbigpe2Vuc3VyZU5vdFRlcm1pbmF0ZWQoKTtsb2FkRG9jdW1lbnQoITApLnRoZW4ob25TdWNjZXNzLG9uRmFpbHVyZSl9KTpvbkZhaWx1cmUoZSl9KX1lbnN1cmVOb3RUZXJtaW5hdGVkKCk7KGFzeW5jIGZ1bmN0aW9uIGdldFBkZk1hbmFnZXIoe2RhdGE6ZSxwYXNzd29yZDp0LGRpc2FibGVBdXRvRmV0Y2g6cixyYW5nZUNodW5rU2l6ZTphLGxlbmd0aDppLGRvY0Jhc2VVcmw6cyxlbmFibGVYZmE6YyxldmFsdWF0b3JPcHRpb25zOmx9KXtjb25zdCBoPXtzb3VyY2U6bnVsbCxkaXNhYmxlQXV0b0ZldGNoOnIsZG9jQmFzZVVybDpzLGRvY0lkOm8sZW5hYmxlWGZhOmMsZXZhbHVhdG9yT3B0aW9uczpsLGhhbmRsZXI6dSxsZW5ndGg6aSxwYXNzd29yZDp0LHJhbmdlQ2h1bmtTaXplOmF9O2lmKGUpe2guc291cmNlPWU7cmV0dXJuIG5ldyBMb2NhbFBkZk1hbmFnZXIoaCl9Y29uc3QgZD1uZXcgUERGV29ya2VyU3RyZWFtKHUpLGY9ZC5nZXRGdWxsUmVhZGVyKCksZz1Qcm9taXNlLndpdGhSZXNvbHZlcnMoKTtsZXQgcCxtPVtdLGI9MDtmLmhlYWRlcnNSZWFkeS50aGVuKGZ1bmN0aW9uKCl7aWYoZi5pc1JhbmdlU3VwcG9ydGVkKXtoLnNvdXJjZT1kO2gubGVuZ3RoPWYuY29udGVudExlbmd0aDtoLmRpc2FibGVBdXRvRmV0Y2h8fD1mLmlzU3RyZWFtaW5nU3VwcG9ydGVkO3A9bmV3IE5ldHdvcmtQZGZNYW5hZ2VyKGgpO2Zvcihjb25zdCBlIG9mIG0pcC5zZW5kUHJvZ3Jlc3NpdmVEYXRhKGUpO209W107Zy5yZXNvbHZlKHApO249bnVsbH19KS5jYXRjaChmdW5jdGlvbihlKXtnLnJlamVjdChlKTtuPW51bGx9KTtuZXcgUHJvbWlzZShmdW5jdGlvbihlLHQpe2NvbnN0IHJlYWRDaHVuaz1mdW5jdGlvbih7dmFsdWU6ZSxkb25lOnJ9KXt0cnl7ZW5zdXJlTm90VGVybWluYXRlZCgpO2lmKHIpe2lmKCFwKXtjb25zdCBlPWFycmF5QnVmZmVyc1RvQnl0ZXMobSk7bT1bXTtpJiZlLmxlbmd0aCE9PWkmJndhcm4oInJlcG9ydGVkIEhUVFAgbGVuZ3RoIGlzIGRpZmZlcmVudCBmcm9tIGFjdHVhbCIpO2guc291cmNlPWU7cD1uZXcgTG9jYWxQZGZNYW5hZ2VyKGgpO2cucmVzb2x2ZShwKX1uPW51bGw7cmV0dXJufWIrPWUuYnl0ZUxlbmd0aDtmLmlzU3RyZWFtaW5nU3VwcG9ydGVkfHx1LnNlbmQoIkRvY1Byb2dyZXNzIix7bG9hZGVkOmIsdG90YWw6TWF0aC5tYXgoYixmLmNvbnRlbnRMZW5ndGh8fDApfSk7cD9wLnNlbmRQcm9ncmVzc2l2ZURhdGEoZSk6bS5wdXNoKGUpO2YucmVhZCgpLnRoZW4ocmVhZENodW5rLHQpfWNhdGNoKGUpe3QoZSl9fTtmLnJlYWQoKS50aGVuKHJlYWRDaHVuayx0KX0pLmNhdGNoKGZ1bmN0aW9uKGUpe2cucmVqZWN0KGUpO249bnVsbH0pO249ZT0+e2QuY2FuY2VsQWxsUmVxdWVzdHMoZSl9O3JldHVybiBnLnByb21pc2V9KShlKS50aGVuKGZ1bmN0aW9uKGUpe2lmKGEpe2UudGVybWluYXRlKG5ldyBBYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTt0aHJvdyBuZXcgRXJyb3IoIldvcmtlciB3YXMgdGVybWluYXRlZCIpfXI9ZTtyLnJlcXVlc3RMb2FkZWRTdHJlYW0oITApLnRoZW4oZT0+e3Uuc2VuZCgiRGF0YUxvYWRlZCIse2xlbmd0aDplLmJ5dGVzLmJ5dGVMZW5ndGh9KX0pfSkudGhlbihwZGZNYW5hZ2VyUmVhZHksb25GYWlsdXJlKX11Lm9uKCJHZXRQYWdlIixmdW5jdGlvbihlKXtyZXR1cm4gci5nZXRQYWdlKGUucGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uKGUpe3JldHVybiBQcm9taXNlLmFsbChbci5lbnN1cmUoZSwicm90YXRlIiksci5lbnN1cmUoZSwicmVmIiksci5lbnN1cmUoZSwidXNlclVuaXQiKSxyLmVuc3VyZShlLCJ2aWV3IildKS50aGVuKGZ1bmN0aW9uKFtlLHQscixhXSl7cmV0dXJue3JvdGF0ZTplLHJlZjp0LHJlZlN0cjp0Py50b1N0cmluZygpPz9udWxsLHVzZXJVbml0OnIsdmlldzphfX0pfSl9KTt1Lm9uKCJHZXRQYWdlSW5kZXgiLGZ1bmN0aW9uKGUpe2NvbnN0IHQ9UmVmLmdldChlLm51bSxlLmdlbik7cmV0dXJuIHIuZW5zdXJlQ2F0YWxvZygiZ2V0UGFnZUluZGV4IixbdF0pfSk7dS5vbigiR2V0RGVzdGluYXRpb25zIixmdW5jdGlvbihlKXtyZXR1cm4gci5lbnN1cmVDYXRhbG9nKCJkZXN0aW5hdGlvbnMiKX0pO3Uub24oIkdldERlc3RpbmF0aW9uIixmdW5jdGlvbihlKXtyZXR1cm4gci5lbnN1cmVDYXRhbG9nKCJnZXREZXN0aW5hdGlvbiIsW2UuaWRdKX0pO3Uub24oIkdldFBhZ2VMYWJlbHMiLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZUNhdGFsb2coInBhZ2VMYWJlbHMiKX0pO3Uub24oIkdldFBhZ2VMYXlvdXQiLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZUNhdGFsb2coInBhZ2VMYXlvdXQiKX0pO3Uub24oIkdldFBhZ2VNb2RlIixmdW5jdGlvbihlKXtyZXR1cm4gci5lbnN1cmVDYXRhbG9nKCJwYWdlTW9kZSIpfSk7dS5vbigiR2V0Vmlld2VyUHJlZmVyZW5jZXMiLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZUNhdGFsb2coInZpZXdlclByZWZlcmVuY2VzIil9KTt1Lm9uKCJHZXRPcGVuQWN0aW9uIixmdW5jdGlvbihlKXtyZXR1cm4gci5lbnN1cmVDYXRhbG9nKCJvcGVuQWN0aW9uIil9KTt1Lm9uKCJHZXRBdHRhY2htZW50cyIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZW5zdXJlQ2F0YWxvZygiYXR0YWNobWVudHMiKX0pO3Uub24oIkdldERvY0pTQWN0aW9ucyIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZW5zdXJlQ2F0YWxvZygianNBY3Rpb25zIil9KTt1Lm9uKCJHZXRQYWdlSlNBY3Rpb25zIixmdW5jdGlvbih7cGFnZUluZGV4OmV9KXtyZXR1cm4gci5nZXRQYWdlKGUpLnRoZW4oZT0+ci5lbnN1cmUoZSwianNBY3Rpb25zIikpfSk7dS5vbigiR2V0QW5ub3RhdGlvbnNCeVR5cGUiLGFzeW5jIGZ1bmN0aW9uKHt0eXBlczplLHBhZ2VJbmRleGVzVG9Ta2lwOnR9KXtjb25zdFthLG5dPWF3YWl0IFByb21pc2UuYWxsKFtyLmVuc3VyZURvYygibnVtUGFnZXMiKSxyLmVuc3VyZURvYygiYW5ub3RhdGlvbkdsb2JhbHMiKV0pO2lmKCFuKXJldHVybiBudWxsO2NvbnN0IGk9W10scz1bXTtsZXQgbz1udWxsO3RyeXtmb3IobGV0IGM9MCxsPWE7YzxsO2MrKylpZighdD8uaGFzKGMpKXtpZighbyl7bz1uZXcgV29ya2VyVGFzaygiR2V0QW5ub3RhdGlvbnNCeVR5cGUiKTtzdGFydFdvcmtlclRhc2sobyl9aS5wdXNoKHIuZ2V0UGFnZShjKS50aGVuKGFzeW5jIHQ9PnQmJnQuY29sbGVjdEFubm90YXRpb25zQnlUeXBlKHUsbyxlLHMsbil8fFtdKSl9YXdhaXQgUHJvbWlzZS5hbGwoaSk7cmV0dXJuKGF3YWl0IFByb21pc2UuYWxsKHMpKS5maWx0ZXIoZT0+ISFlKX1maW5hbGx5e28mJmZpbmlzaFdvcmtlclRhc2sobyl9fSk7dS5vbigiR2V0T3V0bGluZSIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZW5zdXJlQ2F0YWxvZygiZG9jdW1lbnRPdXRsaW5lIil9KTt1Lm9uKCJHZXRPcHRpb25hbENvbnRlbnRDb25maWciLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZUNhdGFsb2coIm9wdGlvbmFsQ29udGVudENvbmZpZyIpfSk7dS5vbigiR2V0UGVybWlzc2lvbnMiLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZUNhdGFsb2coInBlcm1pc3Npb25zIil9KTt1Lm9uKCJHZXRNZXRhZGF0YSIsZnVuY3Rpb24oZSl7cmV0dXJuIFByb21pc2UuYWxsKFtyLmVuc3VyZURvYygiZG9jdW1lbnRJbmZvIiksci5lbnN1cmVDYXRhbG9nKCJtZXRhZGF0YSIpXSl9KTt1Lm9uKCJHZXRNYXJrSW5mbyIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZW5zdXJlQ2F0YWxvZygibWFya0luZm8iKX0pO3Uub24oIkdldERhdGEiLGZ1bmN0aW9uKGUpe3JldHVybiByLnJlcXVlc3RMb2FkZWRTdHJlYW0oKS50aGVuKGU9PmUuYnl0ZXMpfSk7dS5vbigiR2V0QW5ub3RhdGlvbnMiLGZ1bmN0aW9uKHtwYWdlSW5kZXg6ZSxpbnRlbnQ6dH0pe3JldHVybiByLmdldFBhZ2UoZSkudGhlbihmdW5jdGlvbihyKXtjb25zdCBhPW5ldyBXb3JrZXJUYXNrKGBHZXRBbm5vdGF0aW9uczogcGFnZSAke2V9YCk7c3RhcnRXb3JrZXJUYXNrKGEpO3JldHVybiByLmdldEFubm90YXRpb25zRGF0YSh1LGEsdCkudGhlbihlPT57ZmluaXNoV29ya2VyVGFzayhhKTtyZXR1cm4gZX0sZT0+e2ZpbmlzaFdvcmtlclRhc2soYSk7dGhyb3cgZX0pfSl9KTt1Lm9uKCJHZXRGaWVsZE9iamVjdHMiLGZ1bmN0aW9uKGUpe3JldHVybiByLmVuc3VyZURvYygiZmllbGRPYmplY3RzIikudGhlbihlPT5lPy5hbGxGaWVsZHN8fG51bGwpfSk7dS5vbigiSGFzSlNBY3Rpb25zIixmdW5jdGlvbihlKXtyZXR1cm4gci5lbnN1cmVEb2MoImhhc0pTQWN0aW9ucyIpfSk7dS5vbigiR2V0Q2FsY3VsYXRpb25PcmRlcklkcyIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZW5zdXJlRG9jKCJjYWxjdWxhdGlvbk9yZGVySWRzIil9KTt1Lm9uKCJTYXZlRG9jdW1lbnQiLGFzeW5jIGZ1bmN0aW9uKHtpc1B1cmVYZmE6ZSxudW1QYWdlczp0LGFubm90YXRpb25TdG9yYWdlOmEsZmlsZW5hbWU6bn0pe2NvbnN0IGk9W3IucmVxdWVzdExvYWRlZFN0cmVhbSgpLHIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm0iKSxyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtUmVmIiksci5lbnN1cmVEb2MoInN0YXJ0WFJlZiIpLHIuZW5zdXJlRG9jKCJ4cmVmIiksci5lbnN1cmVDYXRhbG9nKCJzdHJ1Y3RUcmVlUm9vdCIpXSxzPW5ldyBSZWZTZXRDYWNoZSxvPVtdLGM9ZT9udWxsOmdldE5ld0Fubm90YXRpb25zTWFwKGEpLFtsLGgsZCxmLGcscF09YXdhaXQgUHJvbWlzZS5hbGwoaSksbT1nLnRyYWlsZXIuZ2V0UmF3KCJSb290Iil8fG51bGw7bGV0IGI7aWYoYyl7cD9hd2FpdCBwLmNhblVwZGF0ZVN0cnVjdFRyZWUoe3BkZk1hbmFnZXI6cixuZXdBbm5vdGF0aW9uc0J5UGFnZTpjfSkmJihiPXApOmF3YWl0IFN0cnVjdFRyZWVSb290LmNhbkNyZWF0ZVN0cnVjdHVyZVRyZWUoe2NhdGFsb2dSZWY6bSxwZGZNYW5hZ2VyOnIsbmV3QW5ub3RhdGlvbnNCeVBhZ2U6Y30pJiYoYj1udWxsKTtjb25zdCBlPUFubm90YXRpb25GYWN0b3J5LmdlbmVyYXRlSW1hZ2VzKGEudmFsdWVzKCksZyxyLmV2YWx1YXRvck9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpLHQ9dm9pZCAwPT09Yj9vOltdO2Zvcihjb25zdFthLG5db2YgYyl0LnB1c2goci5nZXRQYWdlKGEpLnRoZW4odD0+e2NvbnN0IHI9bmV3IFdvcmtlclRhc2soYFNhdmUgKGVkaXRvcik6IHBhZ2UgJHthfWApO3N0YXJ0V29ya2VyVGFzayhyKTtyZXR1cm4gdC5zYXZlTmV3QW5ub3RhdGlvbnModSxyLG4sZSxzKS5maW5hbGx5KGZ1bmN0aW9uKCl7ZmluaXNoV29ya2VyVGFzayhyKX0pfSkpO251bGw9PT1iP28ucHVzaChQcm9taXNlLmFsbCh0KS50aGVuKGFzeW5jKCk9Pnthd2FpdCBTdHJ1Y3RUcmVlUm9vdC5jcmVhdGVTdHJ1Y3R1cmVUcmVlKHtuZXdBbm5vdGF0aW9uc0J5UGFnZTpjLHhyZWY6ZyxjYXRhbG9nUmVmOm0scGRmTWFuYWdlcjpyLGNoYW5nZXM6c30pfSkpOmImJm8ucHVzaChQcm9taXNlLmFsbCh0KS50aGVuKGFzeW5jKCk9Pnthd2FpdCBiLnVwZGF0ZVN0cnVjdHVyZVRyZWUoe25ld0Fubm90YXRpb25zQnlQYWdlOmMscGRmTWFuYWdlcjpyLGNoYW5nZXM6c30pfSkpfWlmKGUpby5wdXNoKHIuZW5zdXJlRG9jKCJzZXJpYWxpemVYZmFEYXRhIixbYV0pKTtlbHNlIGZvcihsZXQgZT0wO2U8dDtlKyspby5wdXNoKHIuZ2V0UGFnZShlKS50aGVuKGZ1bmN0aW9uKHQpe2NvbnN0IHI9bmV3IFdvcmtlclRhc2soYFNhdmU6IHBhZ2UgJHtlfWApO3N0YXJ0V29ya2VyVGFzayhyKTtyZXR1cm4gdC5zYXZlKHUscixhLHMpLmZpbmFsbHkoZnVuY3Rpb24oKXtmaW5pc2hXb3JrZXJUYXNrKHIpfSl9KSk7Y29uc3QgeT1hd2FpdCBQcm9taXNlLmFsbChvKTtsZXQgdz1udWxsO2lmKGUpe3c9eVswXTtpZighdylyZXR1cm4gbC5ieXRlc31lbHNlIGlmKDA9PT1zLnNpemUpcmV0dXJuIGwuYnl0ZXM7Y29uc3QgeD1kJiZoIGluc3RhbmNlb2YgRGljdCYmcy52YWx1ZXMoKS5zb21lKGU9PmUubmVlZEFwcGVhcmFuY2VzKSxTPWggaW5zdGFuY2VvZiBEaWN0JiZoLmdldCgiWEZBIil8fG51bGw7bGV0IGs9bnVsbCxDPSExO2lmKEFycmF5LmlzQXJyYXkoUykpe2ZvcihsZXQgZT0wLHQ9Uy5sZW5ndGg7ZTx0O2UrPTIpaWYoImRhdGFzZXRzIj09PVNbZV0pe2s9U1tlKzFdO0M9ITB9bnVsbD09PWsmJihrPWcuZ2V0TmV3VGVtcG9yYXJ5UmVmKCkpfWVsc2UgUyYmd2FybigiVW5zdXBwb3J0ZWQgWEZBIHR5cGUuIik7bGV0IHY9T2JqZWN0LmNyZWF0ZShudWxsKTtpZihnLnRyYWlsZXIpe2NvbnN0IGU9bmV3IE1hcCx0PWcudHJhaWxlci5nZXQoIkluZm8iKXx8bnVsbDtpZih0IGluc3RhbmNlb2YgRGljdClmb3IoY29uc3RbcixhXW9mIHQpInN0cmluZyI9PXR5cGVvZiBhJiZlLnNldChyLHN0cmluZ1RvUERGU3RyaW5nKGEpKTt2PXtyb290UmVmOm0sZW5jcnlwdFJlZjpnLnRyYWlsZXIuZ2V0UmF3KCJFbmNyeXB0Iil8fG51bGwsbmV3UmVmOmcuZ2V0TmV3VGVtcG9yYXJ5UmVmKCksaW5mb1JlZjpnLnRyYWlsZXIuZ2V0UmF3KCJJbmZvIil8fG51bGwsaW5mb01hcDplLGZpbGVJZHM6Zy50cmFpbGVyLmdldCgiSUQiKXx8bnVsbCxzdGFydFhSZWY6ZixmaWxlbmFtZTpufX1yZXR1cm4gaW5jcmVtZW50YWxVcGRhdGUoe29yaWdpbmFsRGF0YTpsLmJ5dGVzLHhyZWZJbmZvOnYsY2hhbmdlczpzLHhyZWY6ZyxoYXNYZmE6ISFTLHhmYURhdGFzZXRzUmVmOmssaGFzWGZhRGF0YXNldHNFbnRyeTpDLG5lZWRBcHBlYXJhbmNlczp4LGFjcm9Gb3JtUmVmOmQsYWNyb0Zvcm06aCx4ZmFEYXRhOncsdXNlWHJlZlN0cmVhbTppc0RpY3QoZy50b3BEaWN0LCJYUmVmIil9KS5maW5hbGx5KCgpPT57Zy5yZXNldE5ld1RlbXBvcmFyeVJlZigpfSl9KTt1Lm9uKCJHZXRPcGVyYXRvckxpc3QiLGZ1bmN0aW9uKGUsdCl7Y29uc3QgYT1lLnBhZ2VJbmRleDtyLmdldFBhZ2UoYSkudGhlbihmdW5jdGlvbihyKXtjb25zdCBuPW5ldyBXb3JrZXJUYXNrKGBHZXRPcGVyYXRvckxpc3Q6IHBhZ2UgJHthfWApO3N0YXJ0V29ya2VyVGFzayhuKTtjb25zdCBpPXM+PWNlP0RhdGUubm93KCk6MDtyLmdldE9wZXJhdG9yTGlzdCh7aGFuZGxlcjp1LHNpbms6dCx0YXNrOm4saW50ZW50OmUuaW50ZW50LGNhY2hlS2V5OmUuY2FjaGVLZXksYW5ub3RhdGlvblN0b3JhZ2U6ZS5hbm5vdGF0aW9uU3RvcmFnZSxtb2RpZmllZElkczplLm1vZGlmaWVkSWRzfSkudGhlbihmdW5jdGlvbihlKXtmaW5pc2hXb3JrZXJUYXNrKG4pO2kmJmluZm8oYHBhZ2U9JHthKzF9IC0gZ2V0T3BlcmF0b3JMaXN0OiB0aW1lPSR7RGF0ZS5ub3coKS1pfW1zLCBsZW49JHtlLmxlbmd0aH1gKTt0LmNsb3NlKCl9LGZ1bmN0aW9uKGUpe2ZpbmlzaFdvcmtlclRhc2sobik7bi50ZXJtaW5hdGVkfHx0LmVycm9yKGUpfSl9KX0pO3Uub24oIkdldFRleHRDb250ZW50IixmdW5jdGlvbihlLHQpe2NvbnN0e3BhZ2VJbmRleDphLGluY2x1ZGVNYXJrZWRDb250ZW50Om4sZGlzYWJsZU5vcm1hbGl6YXRpb246aX09ZTtyLmdldFBhZ2UoYSkudGhlbihmdW5jdGlvbihlKXtjb25zdCByPW5ldyBXb3JrZXJUYXNrKCJHZXRUZXh0Q29udGVudDogcGFnZSAiK2EpO3N0YXJ0V29ya2VyVGFzayhyKTtjb25zdCBvPXM+PWNlP0RhdGUubm93KCk6MDtlLmV4dHJhY3RUZXh0Q29udGVudCh7aGFuZGxlcjp1LHRhc2s6cixzaW5rOnQsaW5jbHVkZU1hcmtlZENvbnRlbnQ6bixkaXNhYmxlTm9ybWFsaXphdGlvbjppfSkudGhlbihmdW5jdGlvbigpe2ZpbmlzaFdvcmtlclRhc2socik7byYmaW5mbyhgcGFnZT0ke2ErMX0gLSBnZXRUZXh0Q29udGVudDogdGltZT1gKyhEYXRlLm5vdygpLW8pKyJtcyIpO3QuY2xvc2UoKX0sZnVuY3Rpb24oZSl7ZmluaXNoV29ya2VyVGFzayhyKTtyLnRlcm1pbmF0ZWR8fHQuZXJyb3IoZSl9KX0pfSk7dS5vbigiR2V0U3RydWN0VHJlZSIsZnVuY3Rpb24oZSl7cmV0dXJuIHIuZ2V0UGFnZShlLnBhZ2VJbmRleCkudGhlbihlPT5yLmVuc3VyZShlLCJnZXRTdHJ1Y3RUcmVlIikpfSk7dS5vbigiRm9udEZhbGxiYWNrIixmdW5jdGlvbihlKXtyZXR1cm4gci5mb250RmFsbGJhY2soZS5pZCx1KX0pO3Uub24oIkNsZWFudXAiLGZ1bmN0aW9uKGUpe3JldHVybiByLmNsZWFudXAoITApfSk7dS5vbigiVGVybWluYXRlIixmdW5jdGlvbihlKXthPSEwO2NvbnN0IHQ9W107aWYocil7ci50ZXJtaW5hdGUobmV3IEFib3J0RXhjZXB0aW9uKCJXb3JrZXIgd2FzIHRlcm1pbmF0ZWQuIikpO2NvbnN0IGU9ci5jbGVhbnVwKCk7dC5wdXNoKGUpO3I9bnVsbH1lbHNlIGNsZWFyR2xvYmFsQ2FjaGVzKCk7bj8uKG5ldyBBYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTtmb3IoY29uc3QgZSBvZiBpKXt0LnB1c2goZS5maW5pc2hlZCk7ZS50ZXJtaW5hdGUoKX1yZXR1cm4gUHJvbWlzZS5hbGwodCkudGhlbihmdW5jdGlvbigpe3UuZGVzdHJveSgpO3U9bnVsbH0pfSk7dS5vbigiUmVhZHkiLGZ1bmN0aW9uKHQpe3NldHVwRG9jKGUpO2U9bnVsbH0pO3JldHVybiBofXN0YXRpYyBpbml0aWFsaXplRnJvbVBvcnQoZSl7Y29uc3QgdD1uZXcgTWVzc2FnZUhhbmRsZXIoIndvcmtlciIsIm1haW4iLGUpO3RoaXMuc2V0dXAodCxlKTt0LnNlbmQoInJlYWR5IixudWxsKX19Z2xvYmFsVGhpcy5wZGZqc1dvcmtlcj17V29ya2VyTWVzc2FnZUhhbmRsZXJ9O2V4cG9ydHtXb3JrZXJNZXNzYWdlSGFuZGxlcn07"; +global.DOMMatrix = DOMMatrix2; +global.Path2D = Path2D2; +global.ImageData = ImageData2; +var runtimeDirname; +if (typeof __dirname !== "undefined") { + runtimeDirname = __dirname; +} else { + const __filename = fileURLToPath(import.meta.url); + runtimeDirname = path.dirname(__filename); +} +(async () => { + try { + await Promise.resolve().then(() => (init_pdf_worker(), pdf_worker_exports)); + } catch (err) { + console.error("pdf.worker load error!..\n", err); + } +})(); +function getData() { + return pdf_worker_min_default; +} + // services/profile/src/lib/extract-text.ts var inflateRawAsync = promisify(inflateRaw); +PDFParse.setWorker(getData()); var PDF_MIME = "application/pdf"; var DOCX_MIME = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; var TEXT_MIME = "text/plain"; @@ -153080,6 +215448,9 @@ var MAX_EXTRACTED_TEXT_CHARS = 2e5; var MAX_PDF_PAGES = 30; var MAX_DOCX_ENTRIES = 1e3; var MAX_DOCX_UNCOMPRESSED_BYTES = 30 * 1024 * 1024; +var MAX_PDF_STREAM_BYTES = 32 * 1024 * 1024; +var MAX_PDF_TOTAL_STREAM_BYTES = 128 * 1024 * 1024; +var MAX_PDF_STREAMS_CHECKED = 2e4; var FORMAT_BY_MIME = { [PDF_MIME]: "pdf", [DOCX_MIME]: "docx", @@ -153240,6 +215611,38 @@ async function verifyResumeUpload(buffer2, declaredContentType) { if (format === "docx") await assertSafeDocxArchive(buffer2); return MIME_BY_FORMAT[format]; } +function startsLikeZlib(body) { + return body.length >= 2 && (body[0] & 15) === 8 && (body[0] << 8 | body[1]) % 31 === 0; +} +function assertSafePdfStreams(buffer2) { + let total = 0; + let checked = 0; + let from = 0; + for (; ; ) { + const keyword = buffer2.indexOf("stream", from, "latin1"); + if (keyword === -1) return; + from = keyword + 6; + if (keyword >= 3 && buffer2.toString("latin1", keyword - 3, keyword) === "end") continue; + let start = keyword + 6; + if (buffer2[start] === 13) start += 1; + if (buffer2[start] === 10) start += 1; + if (!startsLikeZlib(buffer2.subarray(start, start + 2))) continue; + checked += 1; + if (checked > MAX_PDF_STREAMS_CHECKED) throw archiveTooLarge(); + const end = buffer2.indexOf("endstream", start, "latin1"); + const body = buffer2.subarray(start, end === -1 ? buffer2.length : end); + let inflated; + try { + inflated = inflateSync(body, { maxOutputLength: MAX_PDF_STREAM_BYTES }).length; + } catch (cause) { + if (cause.code === "ERR_BUFFER_TOO_LARGE") throw archiveTooLarge(); + continue; + } + total += inflated; + if (total > MAX_PDF_TOTAL_STREAM_BYTES) throw archiveTooLarge(); + from = Math.max(from, end === -1 ? buffer2.length : end); + } +} function finalizeText(text2) { const clean = text2.includes("\0") ? text2.replaceAll("\0", "") : text2; return clean.length > MAX_EXTRACTED_TEXT_CHARS ? clean.slice(0, MAX_EXTRACTED_TEXT_CHARS) : clean; @@ -153247,6 +215650,7 @@ function finalizeText(text2) { async function extractText(buffer2, contentType) { const mime = await verifyResumeUpload(buffer2, contentType); if (mime === PDF_MIME) { + assertSafePdfStreams(buffer2); const parser = new PDFParse({ data: buffer2 }); try { const result2 = await parser.getText({ first: MAX_PDF_PAGES }); @@ -153273,6 +215677,21 @@ function resumeFailureReason(cause) { return RESUME_FAILURE_REASONS.unreadable; } +// services/profile/src/lib/filename.ts +var FALLBACK_NAME = "resume"; +var MAX_NAME_LENGTH = 255; +var MAX_EXTENSION_LENGTH = 16; +var UNSAFE_CHARS = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g; +function sanitizeFilename(raw) { + const lastSegment = (raw ?? "").split(/[\\/]/).pop() ?? ""; + const cleaned = lastSegment.replace(UNSAFE_CHARS, "").replace(/\s+/g, " ").trim(); + if (cleaned === "" || /^[. ]+$/.test(cleaned)) return FALLBACK_NAME; + if (cleaned.length <= MAX_NAME_LENGTH) return cleaned; + const dot = cleaned.lastIndexOf("."); + const extension = dot > 0 && cleaned.length - dot <= MAX_EXTENSION_LENGTH ? cleaned.slice(dot) : ""; + return `${Array.from(cleaned.slice(0, dot > 0 ? dot : cleaned.length)).slice(0, MAX_NAME_LENGTH - extension.length).join("")}${extension}`; +} + // services/profile/src/lib/hash.ts import { createHash as createHash2 } from "node:crypto"; function sha256HexBuffer(data) { @@ -153281,6 +215700,7 @@ function sha256HexBuffer(data) { // services/profile/src/http/routes/upload-resume.ts var UNIQUE_VIOLATION = "23505"; +var FOREIGN_KEY_VIOLATION = "23503"; var sourceSchema = external_exports.enum(["upload", "connector", "import"]).default("upload"); function uploadResumeRoute(app2, deps) { app2.post( @@ -153305,19 +215725,21 @@ function uploadResumeRoute(app2, deps) { return; } const storageKey = `resumes/${actor.user_id}/${contentHash}`; - await deps.storage.put(storageKey, buffer2, { contentType }); let resumeId; try { const resume = await insertPending(deps.db, { userId: actor.user_id, storageUrl: storageKey, - originalFilename: data.filename, + originalFilename: sanitizeFilename(data.filename), contentType, byteSize: buffer2.length, contentHash }); resumeId = resume.resumeId; } catch (cause) { + if (pgErrorCode(cause) === FOREIGN_KEY_VIOLATION) { + throw new AppError("UNAUTHENTICATED", "This account no longer exists"); + } if (pgErrorCode(cause) === UNIQUE_VIOLATION) { const raced = await findByUserAndHash(deps.db, actor.user_id, contentHash); if (raced) { @@ -153328,6 +215750,12 @@ function uploadResumeRoute(app2, deps) { } throw cause; } + try { + await deps.storage.put(storageKey, buffer2, { contentType }); + } catch (cause) { + await deleteById(deps.db, resumeId).catch(() => void 0); + throw cause; + } let parsed = null; try { const text2 = await extractText(buffer2, contentType); diff --git a/api/referrals/index.js b/api/referrals/index.js index bc8dcab..1afeac1 100644 --- a/api/referrals/index.js +++ b/api/referrals/index.js @@ -53881,8 +53881,38 @@ var AppError = class extends Error { function isAppError(value) { return value instanceof AppError; } +var DATABASE_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([ + "53300", + // too_many_connections + "57P01", + // admin_shutdown + "57P02", + // crash_shutdown + "57P03", + // cannot_connect_now + "08000", + "08001", + "08003", + "08004", + "08006", + "08007", + "CONNECTION_CLOSED", + "CONNECTION_DESTROYED", + "CONNECTION_ENDED", + "CONNECT_TIMEOUT", + "ECONNREFUSED", + "ECONNRESET", + "EPIPE", + "ETIMEDOUT", + "ENOTFOUND", + "EAI_AGAIN" +]); function toAppError(value) { if (isAppError(value)) return value; + const code = pgErrorCode(value); + if (code !== void 0 && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError("UPSTREAM_UNAVAILABLE", "The service is temporarily unavailable. Please try again shortly.", { cause: value }); + } const message2 = value instanceof Error ? value.message : String(value); return new AppError("INTERNAL_ERROR", message2, { cause: value, exposeMessage: false }); } @@ -53910,6 +53940,23 @@ function decodeCursor(cursor) { return null; } } +var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +var MAX_CURSOR_SCORE = 1e9; +function invalidCursor() { + return new AppError("VALIDATION_ERROR", "Invalid cursor", { + details: [{ path: "cursor", message: "Not a cursor this API issued" }] + }); +} +function parseScoreCursor(cursor) { + if (cursor === void 0) return null; + const decoded = decodeCursor(cursor); + const score = decoded?.score; + const id = decoded?.id; + if (typeof score !== "number" || !Number.isFinite(score) || Math.abs(score) > MAX_CURSOR_SCORE || typeof id !== "string" || !UUID.test(id)) { + throw invalidCursor(); + } + return { score, id }; +} // packages/utils/src/logger.ts var import_pino = __toESM(require_pino(), 1); @@ -53918,39 +53965,61 @@ var import_pino = __toESM(require_pino(), 1); var REDACTED = "[redacted]"; // packages/utils/src/logger.ts -function createLogger({ service, level = "info", pretty = false }) { - return (0, import_pino.pino)({ - level, - base: { service }, - redact: { - paths: [ - "password", - "password_hash", - "token", - "access_token", - "refresh_token", - "secret", - "api_key", - "req.headers.authorization", - "req.headers.cookie", - 'res.headers["set-cookie"]', - "*.password", - "*.access_token", - "*.refresh_token" - ], - censor: REDACTED - }, - timestamp: import_pino.pino.stdTimeFunctions.isoTime, - formatters: { - level: (label) => ({ level: label }) +function createLogger({ service, level = "info", pretty = false, destination }) { + return (0, import_pino.pino)( + { + level, + base: { service }, + redact: { + paths: [ + "password", + "password_hash", + "token", + "access_token", + "refresh_token", + "secret", + "api_key", + "req.headers.authorization", + "req.headers.cookie", + 'res.headers["set-cookie"]', + "*.password", + "*.access_token", + "*.refresh_token", + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + "authorization", + "cookie", + "headers.authorization", + "headers.cookie", + 'headers["x-api-key"]', + "*.authorization", + "*.cookie", + "*.headers.authorization", + "*.headers.cookie", + '*.headers["x-api-key"]', + "*.token", + "*.secret", + "*.api_key", + "*.client_secret", + "*.private_key", + // A resume's text is personal data and can be 200,000 characters of it. + "parsed_text", + "*.parsed_text" + ], + censor: REDACTED + }, + timestamp: import_pino.pino.stdTimeFunctions.isoTime, + formatters: { + level: (label) => ({ level: label }) + }, + ...pretty ? { + transport: { + target: "pino-pretty", + options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } + } + } : {} }, - ...pretty ? { - transport: { - target: "pino-pretty", - options: { colorize: true, translateTime: "HH:MM:ss.l", ignore: "pid,hostname" } - } - } : {} - }); + destination + ); } // packages/utils/src/retry.ts @@ -53984,12 +54053,16 @@ function createVercelHandler(app2) { } var SERVERLESS_PLACEHOLDER_PORT = "3000"; var SERVERLESS_DEFAULT_MESSAGING_DRIVER = "postgres"; +function serverlessMessagingDriver(configured) { + const driver = configured?.trim() ?? ""; + return driver === "" || driver.toLowerCase() === "memory" ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} function withServerlessEnvDefaults(source = process.env) { if (!source.VERCEL) return source; return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER) }; } @@ -75415,14 +75488,26 @@ function createTokenVerifierConfig(env2) { issuer: authBase }; } +function isKeySetUnavailable(cause) { + if (!(cause instanceof errors_exports.JOSEError)) return true; + return cause instanceof errors_exports.JWKSTimeout || cause instanceof errors_exports.JWKSInvalid || cause.constructor === errors_exports.JOSEError; +} async function verifyAccessToken(token, config2) { let payload; try { ({ payload } = await jwtVerify(token, config2.jwks, { issuer: config2.issuer, - audience: "authenticated" + audience: "authenticated", + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ["exp", "sub"] })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError("UPSTREAM_UNAVAILABLE", "Sign-in keys are temporarily unavailable", { + cause + }); + } const message2 = cause instanceof errors_exports.JWTExpired ? "Access token has expired" : "Access token is invalid"; throw new AppError("UNAUTHENTICATED", message2, { cause }); } @@ -86125,18 +86210,110 @@ var storageEnvSchema = external_exports.object({ SUPABASE_STORAGE_BUCKET: external_exports.string().min(1).default("resumes"), SUPABASE_SECRET_KEY: external_exports.string().min(1).optional() }); +var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]); +function normalizeSupabaseUrl(value) { + let url2; + try { + url2 = new URL(value.trim()); + } catch { + return void 0; + } + if (url2.username !== "" || url2.password !== "") return void 0; + const secure = url2.protocol === "https:"; + const localStack = url2.protocol === "http:" && LOOPBACK_HOSTS.has(url2.hostname); + return secure || localStack ? url2.origin : void 0; +} +var supabaseUrlSchema = external_exports.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === void 0) { + ctx.addIssue({ + code: "custom", + message: "SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)" + }); + return external_exports.NEVER; + } + return origin; +}); var supabaseAuthEnvSchema = external_exports.object({ - SUPABASE_URL: external_exports.string().url("SUPABASE_URL must be a valid URL") + SUPABASE_URL: supabaseUrlSchema +}); +var WINDOW_UNIT_MS = { + s: 1e3, + sec: 1e3, + secs: 1e3, + second: 1e3, + seconds: 1e3, + m: 6e4, + min: 6e4, + mins: 6e4, + minute: 6e4, + minutes: 6e4, + h: 36e5, + hr: 36e5, + hrs: 36e5, + hour: 36e5, + hours: 36e5, + d: 864e5, + day: 864e5, + days: 864e5 +}; +var RATE_LIMIT_WINDOW_MIN_MS = 1e3; +var RATE_LIMIT_WINDOW_MAX_MS = 7 * 864e5; +function parseRateLimitWindowMs(text2) { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text2.trim()); + if (match === null) return void 0; + const unit = WINDOW_UNIT_MS[(match[2] ?? "").toLowerCase()]; + if (unit === void 0) return void 0; + return Math.round(Number(match[1]) * unit); +} +var rateLimitWindowSchema = external_exports.string().refine( + (text2) => { + const ms = parseRateLimitWindowMs(text2); + return ms !== void 0 && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"' + } +); +function normalizeCorsOrigin(entry) { + const text2 = entry.trim(); + let url2; + try { + url2 = new URL(text2); + } catch { + return void 0; + } + if (url2.protocol !== "http:" && url2.protocol !== "https:") return void 0; + if (url2.username !== "" || url2.password !== "" || url2.search !== "" || url2.hash !== "") { + return void 0; + } + if (url2.pathname !== "/") return void 0; + return url2.origin; +} +function splitCorsOrigins(value) { + return value.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); +} +var corsOriginsSchema = external_exports.string().default("").superRefine((value, ctx) => { + if (value.trim() === "*") return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === void 0) { + ctx.addIssue({ + code: "custom", + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com` + }); + } + } }); var httpEnvSchema = external_exports.object({ HOST: external_exports.string().min(1).default("0.0.0.0"), PORT: external_exports.coerce.number().int().min(1).max(65535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: external_exports.string().default(""), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: external_exports.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: external_exports.string().default("1 minute"), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default("1 minute"), BODY_LIMIT_BYTES: external_exports.coerce.number().int().min(1024).default(1048576) }); +var cronSecretSchema = external_exports.string().trim().min(16, "CRON_SECRET must be at least 16 characters").regex(/^\S+$/, "CRON_SECRET must not contain whitespace"); var ConfigError = class extends Error { constructor(service, issues) { super(`Invalid configuration for ${service}: @@ -86160,8 +86337,7 @@ function loadEnv(service, schema, source = process.env) { function parseCorsOrigins(value) { const trimmed = value.trim(); if (trimmed === "*") return true; - if (trimmed === "") return []; - return trimmed.split(",").map((origin) => origin.trim()).filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed).map(normalizeCorsOrigin).filter((origin) => origin !== void 0); } // packages/observability/src/metrics.ts @@ -86325,9 +86501,9 @@ async function insertContact(db2, input2) { return row; } async function listForCompany(db2, companyId, pagination) { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorScore = typeof cursorValue?.score === "number" ? cursorValue.score : null; - const cursorId = typeof cursorValue?.id === "string" ? cursorValue.id : null; + const cursor = parseScoreCursor(pagination.cursor); + const cursorScore = cursor?.score ?? null; + const cursorId = cursor?.id ?? null; const conditions = [eq(schema_exports.contacts.companyId, companyId)]; if (cursorScore !== null && cursorId) { const tieBreak = or( @@ -86693,7 +86869,7 @@ var referralsServiceEnvSchema = external_exports.object({ * `Authorization: Bearer $CRON_SECRET` when this variable is set. Unset, the * route answers 503 and never runs a drain. */ - CRON_SECRET: external_exports.string().min(16, "CRON_SECRET must be at least 16 characters").optional(), + CRON_SECRET: cronSecretSchema.optional(), /** * Comma-separated `auth.users` ids allowed to write to the shared contacts * directory (see `requirePlatformAdmin` in @atlas/auth-kit). Empty/unset diff --git a/apps/admin/next.config.ts b/apps/admin/next.config.ts index a7d06ba..c19a01d 100644 --- a/apps/admin/next.config.ts +++ b/apps/admin/next.config.ts @@ -3,6 +3,8 @@ import type { NextConfig } from 'next'; const nextConfig: NextConfig = { transpilePackages: ['@atlas/ui', '@atlas/types'], reactStrictMode: true, + // No need to tell every visitor which framework answered. + poweredByHeader: false, async headers() { return [ { @@ -16,6 +18,8 @@ const nextConfig: NextConfig = { { key: 'X-Frame-Options', value: 'DENY' }, { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'Referrer-Policy', value: 'no-referrer' }, + { key: 'Content-Security-Policy', value: "frame-ancestors 'none'" }, + { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=(), payment=(), usb=()' }, ], }, ]; diff --git a/apps/admin/test/csv-hostile.test.ts b/apps/admin/test/csv-hostile.test.ts new file mode 100644 index 0000000..8b5ebd4 --- /dev/null +++ b/apps/admin/test/csv-hostile.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from 'vitest'; +import { preflightCsv } from '../src/lib/import-csv'; + +/** + * The console reads the chosen file in the browser before uploading it. Reading must stay linear in + * its size (a quadratic pattern would freeze the tab on a 4 MB file) and must always answer. Each shape runs at two sizes and the growth is + * checked rather than running the full size, so a regression fails fast instead of hanging. + */ +const SMALL = 100_000; +const LARGE = 400_000; +const HEADER = 'email,full_name\n'; +const fill = (unit: string) => (size: number) => unit.repeat(Math.ceil(size / unit.length)).slice(0, size); + +const SHAPES: ReadonlyArray string]> = [ + ['only commas', (size) => HEADER + fill(',')(size)], + ['only newlines', (size) => HEADER + fill('\n')(size)], + ['only carriage returns', (size) => HEADER + fill('\r')(size)], + ['CRLF blank lines', (size) => HEADER + fill('\r\n')(size)], + ['an open quote that never closes', (size) => `${HEADER}"${'a'.repeat(size)}`], + ['quotes inside an unquoted field', (size) => HEADER + fill('a"b,')(size)], + ['doubled quotes inside a quoted field', (size) => `${HEADER}"${fill('""')(size)}"`], + ['alternating quotes and commas', (size) => HEADER + fill('","')(size)], + ['one enormous cell', (size) => `${HEADER}a@b.co,${'x'.repeat(size)}`], + ['many tiny rows', (size) => HEADER + fill('a@b.co,N\n')(size)], + ['many columns in one row', (size) => `${HEADER}${fill('a,')(size)}`], + ['spaces and tabs', (size) => HEADER + fill(' \t')(size)], + ['a BOM repeated', (size) => HEADER + fill('')(size)], + ['NUL bytes', (size) => `${HEADER}a@b.co,${fill('\u0000')(size)}`], + ['formula prefixes', (size) => HEADER + fill('=cmd|\' /C calc\'!A0,+1\n')(size)], +]; + +function runtime(text: string): number { + const start = performance.now(); + // A file the console refuses is fine; what matters is that it answers, and quickly. + const result = preflightCsv(text); + expect(typeof result.ok).toBe('boolean'); + return performance.now() - start; +} + +describe('the browser-side roster CSV check on hostile input', () => { + it.each(SHAPES)('stays linear: %s', (_label, shape) => { + const small = Math.min(runtime(shape(SMALL)), runtime(shape(SMALL))); + const large = Math.min(runtime(shape(LARGE)), runtime(shape(LARGE))); + if (large <= 80) return; + expect(large / Math.max(small, 1), `${small.toFixed(1)} ms at ${SMALL}, ${large.toFixed(1)} ms at ${LARGE}`).toBeLessThan(9); + }); +}); diff --git a/apps/admin/test/security-headers.test.ts b/apps/admin/test/security-headers.test.ts new file mode 100644 index 0000000..646a439 --- /dev/null +++ b/apps/admin/test/security-headers.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; +import nextConfig from '../next.config'; + +type HeaderRule = { source: string; headers: Array<{ key: string; value: string }> }; + +describe('security headers', async () => { + const rules = (await nextConfig.headers?.()) as HeaderRule[]; + const pages = rules.find((rule) => rule.source.includes('(?!_next/static')); + const header = (name: string) => pages?.headers.find((entry) => entry.key.toLowerCase() === name.toLowerCase())?.value; + + it('applies to pages but not to the fingerprinted bundles, which keep their long-lived cache headers', () => { + expect(pages).toBeDefined(); + const matcher = new RegExp(`^${pages!.source}$`); + expect(matcher.test('/dashboard')).toBe(true); + expect(matcher.test('/login')).toBe(true); + expect(matcher.test('/_next/static/chunks/app.js')).toBe(false); + }); + + it('forbids framing in both the old and the current way', () => { + expect(header('X-Frame-Options')).toBe('DENY'); + expect(header('Content-Security-Policy')).toContain("frame-ancestors 'none'"); + }); + + it('stops content-type sniffing and limits what is sent to other sites', () => { + expect(header('X-Content-Type-Options')).toBe('nosniff'); + expect(['no-referrer', 'strict-origin-when-cross-origin', 'same-origin']).toContain(header('Referrer-Policy')); + }); + + it('does not announce the framework', () => { + expect(nextConfig.poweredByHeader).toBe(false); + }); + + it('switches off browser features the app does not use', () => { + const policy = header('Permissions-Policy') ?? ''; + for (const feature of ['camera', 'microphone', 'geolocation']) expect(policy).toContain(`${feature}=()`); + }); +}); diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index 2015f8d..2ecf011 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -3,6 +3,27 @@ import type { NextConfig } from 'next'; const nextConfig: NextConfig = { transpilePackages: ['@atlas/ui', '@atlas/types'], reactStrictMode: true, + // No need to tell every visitor which framework answered. + poweredByHeader: false, + async headers() { + return [ + { + // Never let the app be framed (the dashboard holds resumes and an account-deletion button, a + // clickjacking target), stop browsers guessing content types, and keep full addresses (job + // and application ids) from leaving for other sites. Powerful browser features the app has + // no use for are switched off. Pages only: the fingerprinted bundles under /_next/static keep + // Next's own long-lived cache headers. + source: '/((?!_next/static|_next/image|favicon.ico).*)', + headers: [ + { key: 'X-Frame-Options', value: 'DENY' }, + { key: 'Content-Security-Policy', value: "frame-ancestors 'none'" }, + { key: 'X-Content-Type-Options', value: 'nosniff' }, + { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, + { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=(), payment=(), usb=()' }, + ], + }, + ]; + }, }; export default nextConfig; diff --git a/apps/web/src/components/jobs/job-view-model.ts b/apps/web/src/components/jobs/job-view-model.ts index 0215b00..e5a8d09 100644 --- a/apps/web/src/components/jobs/job-view-model.ts +++ b/apps/web/src/components/jobs/job-view-model.ts @@ -96,6 +96,117 @@ function decodeEntities(text: string): string { }); } +/** Block-level tags whose closing tag ends a paragraph. */ +const PARAGRAPH_CLOSERS = new Set(['p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'tr']); + +const WHITESPACE = /\s/; +const isSpaceAt = (text: string, index: number): boolean => WHITESPACE.test(text.charAt(index)); +const isNameCharAt = (text: string, index: number, first: boolean): boolean => { + const code = text.charCodeAt(index) | 0x20; // folds A-Z onto a-z + return (code >= 0x61 && code <= 0x7a) || (!first && text.charCodeAt(index) >= 0x30 && text.charCodeAt(index) <= 0x39); +}; + +interface TagInfo { + closing: boolean; + name: string; + /** Nothing but whitespace follows the name before the final ">" (so `` but not ``). */ + bare: boolean; +} + +/** Reads `<` + `text[start, end)` + `>` as a tag, by index, without copying: whitespace, an optional "/", a name. */ +function readTag(text: string, start: number, end: number): TagInfo { + let k = start; + while (k < end && isSpaceAt(text, k)) k += 1; + const closing = text.charAt(k) === '/' && k < end; + if (closing) { + k += 1; + while (k < end && isSpaceAt(text, k)) k += 1; + } + const nameStart = k; + while (k < end && isNameCharAt(text, k, k === nameStart)) k += 1; + const name = text.slice(nameStart, k).toLowerCase(); + while (k < end && isSpaceAt(text, k)) k += 1; + return { closing, name, bare: k === end }; +} + +function tagToText({ closing, name }: TagInfo): string { + if (closing) { + if (name === 'li') return '\n'; + return PARAGRAPH_CLOSERS.has(name) ? '\n\n' : ''; + } + if (name === 'br') return '\n'; + if (name === 'ul' || name === 'ol') return '\n\n'; + return name === 'li' ? '• ' : ''; +} + +/** + * Removes HTML tags (and ``) rescans the rest of the text + * from every "<", which on a description of 200,000 characters made of "<" or unclosed tags froze the + * tab of everyone who opened the job. Two things keep it linear: a "<" with no ">" anywhere after it + * (or no closing tag for a script) ends the search for good, and the next ">" is remembered. + */ +function stripTags(text: string): string { + const length = text.length; + // The first ">" at or after `cacheFrom` (-1: there is none), remembered so a long run of "<" with a + // ">" far away does not search for it again from every "<". + let cacheFrom = 0; + let cacheGt = -2; // -2: nothing cached yet + const gtAfter = (from: number): number => { + if (cacheGt !== -2 && from >= cacheFrom && (cacheGt === -1 || from <= cacheGt)) return cacheGt; + cacheFrom = from; + cacheGt = text.indexOf('>', from); + return cacheGt; + }; + const closedBlocks = new Set(); // block names (script, style) known to have no closing tag left + + /** The index just past the closing tag of a `c')).toEqual(['ac']); + expect(descriptionToParagraphs('ac')).toEqual(['ac']); + expect(descriptionToParagraphs('aHello').join(' '); + expect(joined).toBe('Hello'); + }); +}); diff --git a/apps/web/test/security-headers.test.ts b/apps/web/test/security-headers.test.ts new file mode 100644 index 0000000..646a439 --- /dev/null +++ b/apps/web/test/security-headers.test.ts @@ -0,0 +1,37 @@ +import { describe, expect, it } from 'vitest'; +import nextConfig from '../next.config'; + +type HeaderRule = { source: string; headers: Array<{ key: string; value: string }> }; + +describe('security headers', async () => { + const rules = (await nextConfig.headers?.()) as HeaderRule[]; + const pages = rules.find((rule) => rule.source.includes('(?!_next/static')); + const header = (name: string) => pages?.headers.find((entry) => entry.key.toLowerCase() === name.toLowerCase())?.value; + + it('applies to pages but not to the fingerprinted bundles, which keep their long-lived cache headers', () => { + expect(pages).toBeDefined(); + const matcher = new RegExp(`^${pages!.source}$`); + expect(matcher.test('/dashboard')).toBe(true); + expect(matcher.test('/login')).toBe(true); + expect(matcher.test('/_next/static/chunks/app.js')).toBe(false); + }); + + it('forbids framing in both the old and the current way', () => { + expect(header('X-Frame-Options')).toBe('DENY'); + expect(header('Content-Security-Policy')).toContain("frame-ancestors 'none'"); + }); + + it('stops content-type sniffing and limits what is sent to other sites', () => { + expect(header('X-Content-Type-Options')).toBe('nosniff'); + expect(['no-referrer', 'strict-origin-when-cross-origin', 'same-origin']).toContain(header('Referrer-Policy')); + }); + + it('does not announce the framework', () => { + expect(nextConfig.poweredByHeader).toBe(false); + }); + + it('switches off browser features the app does not use', () => { + const policy = header('Permissions-Policy') ?? ''; + for (const feature of ['camera', 'microphone', 'geolocation']) expect(policy).toContain(`${feature}=()`); + }); +}); diff --git a/docs/17_break_report.md b/docs/17_break_report.md new file mode 100644 index 0000000..8ab50d1 --- /dev/null +++ b/docs/17_break_report.md @@ -0,0 +1,61 @@ +# 17. Break report + +Findings from trying to break Project Atlas locally (in-process apps, a private Postgres, no live +systems). Newest cycle last. Severity follows the scale used for the exercise: Critical (cross-tenant +access, privilege escalation, secret exposure), High (data loss, business rule bypass), Medium (500s or +hangs on hostile input, silent fail-open settings), Low (hardening gaps), Info (things that held). +Work list: `NEXT.md`. + +| # | Sev | Area | Finding | State | +|---|-----|------|---------|-------| +| 1 | Medium | Config | `RATE_LIMIT_WINDOW` was an unchecked string. `abc`, `1 parsec`, an empty value or `0` booted fine and then every business request answered 500 (the limiter threw per request). A negative value (`-5 minutes`) and a bare number (`60`, read as 60 ms) booted fine and limited nothing. The same held for `PRIVACY_RATE_LIMIT_WINDOW`. | Fixed: both are validated at boot (`rateLimitWindowSchema`, one second to seven days, ` ` only). Tests in `packages/config/test`. | +| 2 | Info | Rate limit | The limiter's in-memory store is a 5,000-entry LRU, so many unique clients cannot grow memory without bound. | Held. | +| 3 | Low | Rate limit | Clients are told apart by `request.ip` with `trustProxy: true`. That is the first `X-Forwarded-For` entry, which a client chooses unless the edge overwrites the header. Vercel does overwrite it, so the launch deployment is not affected; behind a proxy that only appends, one client could pick fresh buckets at will, or push others' buckets out of the LRU. | Accepted for launch, documented in `registerRateLimitedRoutes`. Revisit if the API ever moves behind another proxy. | +| 4 | Medium | Config | `CORS_ORIGINS` entries were not checked. `https://app.example.com/` (trailing slash), `app.example.com` (no scheme), a URL with a path, or `null` started the service fine and then matched no browser `Origin`, so every browser call failed with a CORS error and nothing in the logs said why. | Fixed: a trailing slash and upper-case are forgiven (normalized to the exact origin form), and an entry that can never match stops the boot with the entry named. Tests in `packages/config/test/cors-origins.test.ts`. | +| 5 | Low | Config | `CORS_ORIGINS=*` is accepted in production although `docs/16` says never to use it and the config comment says development only. The API authenticates with bearer tokens, not cookies, so a wildcard does not expose a session, but the rule is not enforced. | Open: needs an owner decision, because the live preview may rely on `*` (see `NEXT.md`, "Needs Nikshey"). | +| 6 | Medium | Auth | When the Supabase key set (JWKS) could not be fetched or read (project paused, network failure, 5xx, a page that is not a key set), token verification answered **401 on every request**. The web app treats a 401 as "this session is dead" and signs the user out, so a short outage or a paused project logged everyone out instead of showing "try again". | Fixed: key-set failures now answer 503 `UPSTREAM_UNAVAILABLE`; a bad token on a healthy key set is still 401. Tests in `packages/auth-kit/test/tokens-attacks.test.ts`. | +| 7 | Low | Auth | `jwtVerify` was called without required claims, and jose treats a missing `exp` as a token that never expires. Exploiting it needs a validly signed token, which Supabase never issues without `exp`, so this is hardening. | Fixed: `exp` and `sub` are required. | +| 8 | Medium | Jobs ingestion | A job board that put a NUL byte (`\u0000`) in any title, location or description made Postgres refuse that posting, so it was counted as rejected. Any rejected posting makes the run skip the sweep that deactivates closed roles, so one such posting kept every stale posting of that board active and recommended for as long as the board listed it. The same fields also stored other control characters (BEL, ESC) and bidirectional overrides (U+202E), which garble logs and can make a title read as something else. | Fixed: every posting text field is stripped of NUL, control characters (except tab, line feed, carriage return) and bidi overrides/isolates before it is stored (`stripUnsafeChars` in `job-sources/common.ts`). Tests: `services/jobs/test/hostile-postings.test.ts` (fails without the fix), `job-source-mappers.test.ts`. | +| 9 | High | Profile / ai | `parseResumeText` used an email pattern with open-ended quantifiers (`[a-zA-Z0-9._%+-]+@...`). On a run of local-part characters with no `@` (a resume that is one long word, or `aaaa...`, `----...`, `1111...`, `2020-2020-...`) it rescanned from every start position: quadratic time. A 200,000-character `text/plain` upload (the extraction cap) kept the function busy for minutes, far past the 30 s limit, and the parse runs inside the upload request. One authenticated request could pin an instance; 20 uploads a minute per address could pin many. It also affected `POST /v1/resumes/:id/optimize` and anything else that parses resume text. Found when the first sweep hung the test run for over six minutes. | Fixed: the local part, domain and top-level domain are bounded (64, 255, 24). The parse of any 200,000-character shape in the sweep now takes under 100 ms. New `packages/ai/test/adversarial-input.test.ts` checks growth on 37 hostile shapes at two sizes (it fails in under two minutes against the old pattern instead of hanging). | +| 10 | Medium | Profile | A PDF could carry a decompression bomb: a page content stream of Flate data that inflates about 1,000 to 1. A 299 KB PDF made pdf.js spend 3.1 s and about 670 MB; the upload limit (1 MB by default) allows roughly 1 GB inflated, past a function's memory, and it runs inside the upload request. The DOCX path already had a zip-bomb guard; the PDF path had none. | Fixed: before pdf.js sees the file, every zlib-looking stream is inflated with a cap (32 MB each, 128 MB together; `assertSafePdfStreams`), so a bomb is refused with 413 "too large or complex". A 300 MB bomb is now refused in 26 ms and a 1 GB one in 152 ms. Tests in `services/profile/test/extract-text.test.ts`. | +| 11 | High | Applications | Status moves were read, validated, then written with an unconditional `UPDATE ... WHERE application_id = ...`. Two requests that both read the same status both passed validation and both wrote. Observed: 20 simultaneous `queued` requests all answered 200 and left 20 events; 15 simultaneous `submitted` requests published `application.submitted` 15 times; and with `offer` and `rejected` sent together an application was recorded as `interviewing -> offer` after it had already been `rejected` (a terminal status), so the head and the trail disagreed with the lifecycle. Reachable by a double click, or the owner and staff acting together. | Fixed: the update only applies while the application is still in the status the move was validated against (`AND status = from_status`); the loser gets 409 `CONFLICT` and nothing is written or published. Tests: `services/applications/test/applications-races.test.ts` (failed 3 of 5 before, passes repeatedly after). | +| 12 | Low | Applications | Thirty identical creates at once (same idempotency key, same body) answered 201 once, 200 for most, and **409 for 12 of them**, because the winner's row was invisible to the key lookup but visible to the "already applied to this job" check. A retry racing its original saw an error for something that had succeeded. | Fixed: a row with the same key and the same request found at that point is a replay (200). | +| 13 | Medium | All list endpoints | The page `cursor` is opaque, but any string is accepted. Valid JSON that was not a cursor this API issued went straight to the database as a timestamp or a uuid: `{"createdAt":"not-a-date","id":"..."}` (and `2026-02-31`, which `Date.parse` accepts but Postgres refuses) answered **500** on applications, jobs, recommendations, resumes, messages and a company's contacts; other malformed shapes (numbers, objects, a missing id) were silently treated as the first page. Only the admin roster validated its cursor. | Fixed: one pair of validators in `@atlas/utils` (`parseTimeCursor`, `parseScoreCursor`: real calendar date and clock time, uuid ids, finite bounded scores) is used by every list query, including the roster; a cursor that is not exactly what the API issues is a 400 `VALIDATION_ERROR` "Invalid cursor". Tests: `packages/utils/test/cursors.test.ts` (42 cases) and six forged-cursor cases over HTTP in `applications-flow.test.ts` (all failed before). | +| 14 | High | Config / auth | `SUPABASE_URL` was any URL. With the trailing slash the dashboard shows (`https://abc.supabase.co/`) the expected issuer became `https://abc.supabase.co//auth/v1`, which no token carries: the service started, then refused **every** request as unauthenticated, and the web app signed everyone out. `http://` (a key set fetched in the clear), credentials in the URL and non-web schemes were accepted too. | Fixed: the value is reduced to its origin (a trailing slash or path is forgiven) and anything that is not `https` (or `http` on localhost for a local stack) stops the boot. Tests: `packages/config/test/supabase-url.test.ts`. | +| 15 | Medium | Config | `MESSAGING_DRIVER=memory` is what `.env.example` shows for local work. Pasted into Vercel's settings it would drop every cross-service event without a sound (each function is its own process), which is the failure the serverless default exists to prevent; the default only covered the variable being unset. | Fixed: on Vercel `memory` (or an empty value) is not honoured and the outbox is used. Tests in `packages/utils/test/vercel.test.ts`. | +| 16 | Low | Config | `CRON_SECRET` kept surrounding whitespace (a secret pasted into a dashboard often keeps its newline), so the comparison could never succeed and the scheduler got 401 for ever; one with whitespace inside could never match a header value. | Fixed: surrounding whitespace is dropped, whitespace inside stops the boot (`cronSecretSchema`, used by the five services that take it). | +| 17 | Low | Docs | `.env.example` left out variables services read (`BODY_LIMIT_BYTES`, `DATABASE_POOL_MAX`, `MESSAGING_*`, `LOG_PRETTY`, `HOST`). | Fixed, and `packages/utils/test/env-example.test.ts` fails when a service reads a variable the file does not document. `REDIS_URL` and `SUPABASE_ACCESS_TOKEN` remain in the file although no service reads them (Redis is not used). | +| 18 | Low | Web app | `apps/web` sent no security headers at all (the admin console already did): the dashboard, which holds resumes and an account-deletion button, could be framed from another site (clickjacking), content-type sniffing was on, the full address (job and application ids) went to other sites in the Referer, and `X-Powered-By: Next.js` was sent. | Fixed: `X-Frame-Options: DENY` plus `frame-ancestors 'none'`, `nosniff`, `Referrer-Policy: strict-origin-when-cross-origin`, a `Permissions-Policy` that switches off camera, microphone, location, payment and USB, and no `X-Powered-By`; the admin console got the same additions. Checked on a running build (pages carry the headers, the fingerprinted bundles keep `immutable`). Tests in `apps/*/test/security-headers.test.ts`. A full Content-Security-Policy is not set: Next's inline bootstrap scripts need a nonce setup, which is its own piece of work. | +| 19 | **High (launch blocker)** | Profile bundle | **Every PDF resume failed to parse in the deployed bundle.** pdf.js runs its parser as a separate worker module that it loads by file name next to the code that asks for it; inside `api/profile/index.js` that is `api/profile/pdf.worker.mjs`, which does not exist (the bundler cannot inline a file loaded by name, and `vercel.json` includes only the canvas addon). Every PDF upload ended as `status: failed` with "We could not read this file", the most common resume format. Text and DOCX worked, and every test passed, because the tests run the TypeScript sources, where the worker is found inside `node_modules`. Found by the first end-to-end run of the committed bundles (`Setting up fake worker failed: Cannot find module .../api/profile/pdf.worker.mjs`). | Fixed: the worker is passed to pdf.js as the data URL that `pdf-parse` ships (`PDFParse.setWorker(getData())` from `pdf-parse/worker`), which needs no file. Profile bundle is now 9.2 MB (was 5.5). New test `packages/auth-kit/test/bundles-e2e.test.ts` boots all ten committed bundles over real HTTP against Postgres and a stand-in key server and uploads a text, a PDF and a DOCX resume through the profile bundle (failed before the fix). | +| 20 | Low | Logging | The logger redacted only a handful of exact paths (`req.headers.authorization`, `password`, `*.access_token`, ...). The same secrets one level over (`headers.authorization`, `request.headers["x-api-key"]`, `*.secret`, `*.token`) and a resume's `parsed_text` would have been logged in full. `redact()`, `maskEmail()` and `maskToken()` in `@atlas/utils` are used nowhere, although their header comment said the shared logger applied them. | Fixed: the redaction paths cover those shapes (tests in `packages/utils/test/logger.test.ts`), the logger takes an optional `destination` so tests can read what it wrote, and the helper's comment now says what it is. | +| 21 | Medium | Profile | The uploaded file's name was stored as the client sent it. A NUL byte or a name over 400 characters made the insert fail, so the upload answered **500 after the file had already been written to storage** (an orphaned blob each time); an empty name was stored as an empty string, breaking the API's own `min(1)` contract; control characters and a right-to-left override (`resume\u202Egnp.txt` shows as `resumept.png`-style reversed text) were stored and shown back. The storage path itself is built from the user id and content hash, so traversal names never reached the filesystem. | Fixed: `sanitizeFilename` keeps the last path segment, drops control characters and bidi overrides, collapses whitespace, falls back to `resume` for names that say nothing, and cuts to 255 characters keeping a short extension without splitting a character. Tests: `services/profile/test/filename.test.ts` and ten hostile-name uploads in `resume-flow.test.ts` (five failed before). | +| 22 | Low | All services | When the database could not be reached or refused the connection (the pooler out of connections, a restart, a network failure), every request answered **500 `INTERNAL_ERROR`**, the same as a bug in our code. A client cannot tell "try again" from "this is broken", and an outage reads as a crash in the logs. | Fixed: connection-class failures (`53300`, `57P01-03`, class `08`, and the driver and socket codes `CONNECTION_CLOSED`, `CONNECT_TIMEOUT`, `ECONNREFUSED`, `ECONNRESET`, ...) answer **503 `UPSTREAM_UNAVAILABLE`** with a fixed message and no driver text. Constraint, syntax and data errors stay 500/409 as before. Tests in `packages/utils/test/utils.test.ts` and over HTTP against a dead port in `body-fuzz.test.ts`. | +| 23 | Medium | Profile / privacy | After an account was deleted, its still-valid access token (it lives until it expires, up to an hour) could keep uploading resumes: the file was **written to storage first**, then the insert failed on the missing user and the request answered **500**, leaving a file of a user who had asked for everything to be erased, with nothing pointing at it and no sweeper to find it. Reproduced through the deployed auth and profile bundles: two such files were left behind by the test itself. The same ordering left a file behind whenever the insert failed for any other reason. | Fixed: the record is inserted first and the file stored second; a deleted account (foreign-key violation) is answered **401 "This account no longer exists"** and nothing is written; if storing the file fails the record is removed. Test: `bundles-e2e.test.ts` (account deletion across the auth and profile bundles). | +| 24 | High | Web app | **A job posting could freeze the browser tab of everyone who opened it.** The web app cleans a job description (`descriptionToParagraphs`) with a chain of regular expressions (`<[^>]*>`, ``, `<\s*li[^>]*>`) that rescan the rest of the text from every `<`. A description of up to 200,000 characters made of `<`, `a<`, `< `, `` took seconds at 50,000 characters (1.5 s for a run of `<`, so about 25 s at the cap) and grows with the square. The server-side cleaner had been written to avoid exactly this and has a test for it; the client had its own, older copy. A hostile or sloppy job board reaches every user through the shared catalog (plain-text fields of Lever and Ashby postings arrive uncleaned). | Fixed: one linear pass over the text (`stripTags`): the next `>` is remembered, a `<` with no `>` left ends the search for good, a script or style block with no closing tag is searched for once, not from every opening tag. Same output as the old chain on 18 samples of ordinary markup (a differential test keeps the old chain beside it), and `
` and other tags with attributes now turn into the breaks they stand for. 22 growth tests in `apps/web/test/description-hostile.test.ts` (eight failed before). | + +## What was checked and held + +- `vercel.json`: every `/v1/...` and `/internal//...` route that each deployed service declares resolves to that service's function, every rewrite destination has a bundle and a function entry, and the service-local `/internal/drain`, `/health` and `/metrics` are not routed at all. New test `packages/utils/test/vercel-routing.test.ts` (it fails when a rewrite is removed). +- Drain and ingest secret checks (`isAuthorizedDrainRequest`): hashed and compared in constant time, no length oracle, empty secret never matches, a duplicate `Authorization` header (joined with a comma by Node) is refused, a secret containing spaces fails closed. +- Token forgery (new `tokens-attacks.test.ts`, all refused with 401): `alg: none` (with, without and with a junk signature), HS256 signed with the public key as secret (PEM, JWK JSON and raw coordinates), a token signed by another key under the right, an unknown or no `kid`, an embedded `jwk` header, `jku` and `x5u` pointing at an attacker, a payload swapped under a valid signature, wrong issuer (including a trailing slash), wrong or missing audience (string and array), `nbf` in the future, junk and 1 MB tokens, a missing or non-uuid `sub`, an unknown role, a non-uuid organization, and role or organization supplied through `user_metadata` or the top level of the token (ignored). +- Ownership checks read: resumes, messages, applications (owner or same-organization admin/owner, 404 otherwise), recommendations (own, or a member of the caller's organization), contacts (a company's contacts only to someone who applied there), learning metrics and job ingest/sources (platform admins only). All answer 404 for what the caller may not see. +- Job-board reading: the request URL is the provider's fixed origin plus a token checked against a pattern (and checked again after the URL is built); redirects are refused; the response is capped at 25 MB by header and by streamed size; the deadline holds even for a `fetch` that ignores the abort signal; error text stored on the source is fixed, never copied from the response. Hostile postings ingested end to end against Postgres: `javascript:` and `data:` apply links are stored as no link, markup in a title is kept as text, a 100 KB title and a 500 KB description are cut to 300 and 200,000 characters, entries with no id or the wrong shape are skipped without failing the board. +- The other parsing regexes in `packages/ai` (phone, URL, month/year, date ranges, section headers, bullet and keyword matching) and `extractSkillKeywords`/`analyzeResumeForJob` grow linearly on the same 37 shapes, including a keyword that is itself a pattern (`(a+)+$`), which is escaped and matched as text. +- Uploads: the DOCX guard already refused lying headers, too many entries, encrypted entries, unknown compression, truncated and offset-rebased archives, and hidden extra directory records (existing tests); text uploads reject NUL, control-character soup and known binary signatures; the declared content type is checked against the bytes and never echoed. +- Thirty creates for one job with different idempotency keys: one 201, twenty-nine 409, one row, no 500 (the unique indexes hold). Outreach's send and mark-sent already claim a message with a conditional update; scheduling is switched off with delivery. `setScheduled` is an unconditional update, which would race a send if delivery were ever enabled (noted in `NEXT.md`). +- Six simultaneous deletions of one account (new test in `delete-account.test.ts`, run repeatedly): all answer 200, one tombstone, no leftover rows, no deadlock. +- Request bodies, content types, query strings and path ids on the applications service (new `body-fuzz.test.ts`, 76 cases): empty, truncated, BOM-prefixed, null/array/scalar bodies, prototype keys, duplicate keys, NUL and lone surrogates, huge numbers, 5,000-deep nesting, wrong content types, a body over the limit (413), unsupported methods (404), malformed and path-traversal ids, odd `limit`/`cursor`/filter values. Every one is a 4xx in the standard envelope with a request id and no stack or driver text. +- Frontends, by reading and by existing tests: no `dangerouslySetInnerHTML`, `innerHTML`, `eval` or `document.write` anywhere in `apps/`; the one external link built from API data (the employer's apply page) goes through `safeExternalUrl` (http/https only) with `rel="noopener noreferrer"`; the `mailto:` builder percent-encodes every field, strips line breaks from the subject and accepts one plain recipient; the sign-in redirect (`next`) accepts only one-slash same-origin paths and rejects backslashes, control characters (a tab turns `//evil.com` into `//evil.com`) and encoded forms; the roster CSV export and import are formula-injection safe (existing tests). Not done: driving the pages in a browser with hostile data (no Playwright run this stretch). +- The committed bundles, booted for real (the new `bundles-e2e.test.ts`, 19 cases): all ten start with Vercel's environment, answer `/health`, turn an anonymous caller and a forged token away with 401 in the standard envelope; auth `me` and export work; only a platform admin can ingest jobs, and the posting is then listed with its employer; the scheduler route needs the secret; resumes can be uploaded and optimized; applications can be created, replayed and moved to `submitted`; a PDF decompression bomb is recorded as "too large or complex" in well under five seconds; another user gets 404 for a resume and an empty application list. The bundles are byte-for-byte repeatable (two builds, identical hashes), the only package left external is `@napi-rs/canvas` (installed for the function by `vercel.json`), and no bundle contains a private key or an access key (the one match for `service_role` is a comment). +- Secrets: no JWT, `sb_secret_`, private key, AWS/GitHub/Slack/OpenAI-style token or `postgres://user:password@host` URL with a real host in any added line of any of the 181 commits on any ref; `.gitignore` covers `.env*` (except the example), `.atlas-storage`, `.atlas-secrets`, logs and build output; none of the ten bundles contains a key. Logs: `x-request-id` is never trusted (every request id is a fresh uuid), a user-supplied line break or ANSI escape stays inside one JSON line, and a database error carries the failing value only in its `message` (Postgres itself masks the bound parameters as `'...'`). +- Roster CSV import (`services/admin/test/csv-hostile.test.ts`, 15 shapes at two sizes): commas, newlines, bare carriage returns, an unclosed quote, quotes inside fields, doubled quotes, one enormous cell, many tiny rows, many columns, NUL, formula prefixes. Parsing grows linearly and every failure is a clean 400 or 413. The remaining regular expressions in the services (referral relevance, header normalization, timestamps, uuids) are simple and bounded. +- Authentication on every route: the bundle test reads the route table of each booted bundle (not a hand-kept list) and sends every route that is not `/health` or `/metrics`, anonymously and with a forged token, expecting 401. All ten bundles pass, so no route is missing its authentication check. A new route that forgets it fails the test. +- Over-posting: no request schema passes unknown keys through (zod strips them); the three `z.record(z.string(), z.unknown())` are event and export payload shapes, not request bodies. `user_id`, `organization_id` and `role` in a body are ignored and come from the token. +- The product's main loop, across four deployed functions and the Postgres outbox (bundle test, run repeatedly): a resume is uploaded (profile), a job is ingested (jobs), the matching drain route processes the queued `resume.parsed` and `job.discovered` events, and the job comes back from `GET /v1/jobs/recommendations` with a score above zero and reasons naming the matched skills. The learning, analytics and referrals drain routes refuse a missing or wrong secret and drain cleanly with the right one. Note for readers: matching scores a job against the user's **latest parsed** resume, so uploading a second, different resume changes every score. +- The university pilot through the admin bundle (bundle test): a university owner imports a roster CSV (an email with a platform account is created, one without is skipped and counted), reads it back (identity only: no name, no activity until the student shares), exports it as CSV and opens the funnel; a user who is not a member gets 404 on all three. Account deletion through the auth bundle removes the rows and the stored file, refuses a lower-case `confirm`, and leaves no user row behind. +- A real browser (Chromium at phone width) against the built web app with the API and Supabase unreachable: the home, login, register, forgot/reset password, privacy and 404 pages render with no script errors and no sideways scroll; `/dashboard`, `/dashboard/jobs` and `/dashboard/resume` send a signed-out visitor to `/login`; `/auth/callback` with a bad code and `next=//evil.com` ends on `/login?oauth_error=session`, not on another site; `/login?next=//evil.com` and `next=/\evil.com` stay on the login page. Not done: signed-in pages with hostile data (needs a stand-in Supabase for the session). +- Scheduled workflows: secrets reach `curl` through environment variables (never spliced into the script), the one user input (`source_id`) is passed through an environment variable and checked against a UUID pattern before use, `permissions: {}`, a concurrency group stops runs piling up, and CI uses `pull_request` (not `pull_request_target`), so fork pull requests get no secrets. Actions are pinned by major tag (`@v4`), not by commit; acceptable here, a hardening choice for later. The repository is public, so Actions minutes are not a constraint on the five-minute drain schedule. +- Outreach: twenty simultaneous draft creates with one idempotency key make one draft (new test); marking a draft sent while ten requests race was already covered. +- The admin console's own CSV check, run in the browser before upload, on the same 15 hostile shapes as the server's parser (`apps/admin/test/csv-hostile.test.ts`): linear, and it always answers. +- `RATE_LIMIT_MAX` of 0 is refused at boot (`min(1)`). +- `/health`, `/metrics` and `/internal/*` are exempt because they are registered outside the limited scope, not by path matching, so no path trick can move a business route into the exempt set. diff --git a/packages/ai/src/resume-parser.ts b/packages/ai/src/resume-parser.ts index 37ff071..6c03d98 100644 --- a/packages/ai/src/resume-parser.ts +++ b/packages/ai/src/resume-parser.ts @@ -9,7 +9,10 @@ import { extractSkillKeywords } from './skills.js'; * replace the body later without profile-service noticing. */ -const EMAIL_RE = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/; +// Every quantifier is bounded (64 is the limit for a local part, 255 for a domain): with open-ended +// ones, a long run of local-part characters and no "@" is rescanned from every start position, which +// takes quadratic time on a resume made of one 200,000-character word. +const EMAIL_RE = /[a-zA-Z0-9._%+-]{1,64}@[a-zA-Z0-9.-]{1,255}\.[a-zA-Z]{2,24}/; const PHONE_RE = /(?:\+?\d{1,3}[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/; const URL_RE = /\bhttps?:\/\/[^\s,;)]+|(?:www\.)[^\s,;)]+/gi; diff --git a/packages/ai/test/adversarial-input.test.ts b/packages/ai/test/adversarial-input.test.ts new file mode 100644 index 0000000..6fc9f8a --- /dev/null +++ b/packages/ai/test/adversarial-input.test.ts @@ -0,0 +1,130 @@ +import { describe, expect, it } from 'vitest'; +import { analyzeResumeForJob, containsKeyword, extractSkillKeywords, parseResumeText, scoreResume } from '../src/index.js'; + +/** + * Resume and job text is typed by strangers (extracted text is capped at 200,000 characters). The + * regular-expression based parts must stay roughly linear on it, or one upload or one posting ties up + * a serverless function until the platform kills it. + * + * Each shape below is aimed at a usual backtracking trap: a long run of one character, a near miss of a + * pattern, thousands of repeats of a section header, bullet or date. Running them at the full 200,000 + * characters would hang the test run if a pattern regressed (nothing can interrupt a regular expression + * from inside the process), so each shape is run at two small sizes and the growth is checked: four + * times the text may cost about four times as long, and a quadratic pattern costs sixteen times. + */ +const SMALL = 10_000; +const LARGE = 40_000; +const GROWTH_LIMIT = 9; +/** Below this a run is too short to measure the growth of, and plainly fast enough. */ +const NEGLIGIBLE_MS = 60; + +type Shape = (size: number) => string; +const fill = + (unit: string): Shape => + (size) => + unit.repeat(Math.ceil(size / unit.length)).slice(0, size); + +const SHAPES: ReadonlyArray = [ + ['one letter', fill('a')], + ['spaces', fill(' ')], + ['newlines', fill('\n')], + ['tabs and spaces', fill(' \t')], + ['hyphens', fill('-')], + ['bullets', fill('• ')], + ['dash bullets, one per line', fill('- a\n')], + ['digits', fill('1')], + ['near-miss email: repeated local@', fill('a@')], + ['near-miss email: dots', fill('a.')], + ['near-miss url', fill('http://')], + ['parentheses', fill('(')], + ['phone-like digits', fill('(555) 555-')], + ['date ranges', fill('Jan 2020 - ')], + ['years', fill('2020-')], + ['section header repeated', fill('Experience\n')], + ['skills header repeated', fill('SKILLS: ')], + ['education header repeated', fill('Education\nBSc ')], + ['c++ and .net', fill('c++ .net c# ')], + ['regex metacharacters', fill('.*+?^${}()|[]\\')], + ['combining marks', fill('é')], + ['emoji', fill('🙂')], + ['right-to-left text', fill('שלום ')], + ['NUL bytes', fill('\u0000')], + ['one long word ending in a symbol', (size) => `${fill('word')(size)}!`], + ['job-title lines', fill('Senior Engineer at Acme Corp, Berlin (2019 - 2021)\n')], + ['percent and digit bullets', fill('* Improved 20% \n')], + ['one word, then spaces, then another', (size) => `a${' '.repeat(size)}b`], + ['month, then spaces', (size) => `Jan${' '.repeat(size)}x`], + ['year, then spaces', (size) => `2020${' '.repeat(size)}x`], + ['range separators', fill('2020 - ')], + ['"to" ranges', fill('Jan 2020 to ')], + ['at-sign, then a long domain', (size) => `a@${'b'.repeat(size)}`], + ['at-sign, then dotted labels', (size) => `a@${fill('b.')(size)}`], + ['degree line', (size) => `bachelor ${fill('in a')(size)}`], + ['one huge line with a separator at the end', (size) => `${'a'.repeat(size)} at ${'b'.repeat(10)}`], + ['many separators', fill('a - ')], +]; + +/** The fastest of three runs, in milliseconds (the minimum is the least affected by other work). */ +function bestOfThree(run: () => unknown): number { + let best = Number.POSITIVE_INFINITY; + for (let attempt = 0; attempt < 3; attempt += 1) { + const start = performance.now(); + run(); + best = Math.min(best, performance.now() - start); + } + return best; +} + +function expectLinear(label: string, run: (size: number) => unknown): void { + const small = bestOfThree(() => run(SMALL)); + const large = bestOfThree(() => run(LARGE)); + if (large <= NEGLIGIBLE_MS) return; + expect(large / Math.max(small, 1), `${label}: ${small.toFixed(1)} ms at ${SMALL}, ${large.toFixed(1)} ms at ${LARGE}`).toBeLessThan( + GROWTH_LIMIT, + ); +} + +describe('text processing grows linearly on hostile input', () => { + it.each(SHAPES)('parseResumeText + scoreResume: %s', (label, shape) => { + expectLinear(label, (size) => { + const text = shape(size); + return scoreResume(parseResumeText(text), text); + }); + }); + + it.each(SHAPES)('extractSkillKeywords: %s', (label, shape) => { + expectLinear(label, (size) => extractSkillKeywords(shape(size))); + }); + + it.each(SHAPES)('analyzeResumeForJob with this as both the resume and the posting: %s', (label, shape) => { + expectLinear(label, (size) => { + const text = shape(size); + return analyzeResumeForJob(parseResumeText(text), text, { + title: text.slice(0, 300), + description: text, + skills: [], + }); + }); + }); + + it('containsKeyword treats a keyword as text, not as a pattern', () => { + expect(containsKeyword('uses c++ daily', 'c++')).toBe(true); + expect(containsKeyword('aaaaaaaaaaaaaaaaaaaaaaaaaaaa', '(a+)+$')).toBe(false); + expect(containsKeyword('x'.repeat(100_000), '(x+x+)+y')).toBe(false); + }); +}); + +describe('the email pattern still reads ordinary addresses', () => { + it.each([ + ['Ada Lovelace\nada.lovelace+jobs@example.co.uk\n', 'ada.lovelace+jobs@example.co.uk'], + ['contact: a_b-c%d@sub.domain-name.org, phone', 'a_b-c%d@sub.domain-name.org'], + ['x@y.io', 'x@y.io'], + ])('finds the address in %j', (text, email) => { + expect(parseResumeText(text).contact.email).toBe(email); + }); + + it('finds no address in text that has none', () => { + expect(parseResumeText('no address here, only a@b').contact.email).toBeNull(); + expect(parseResumeText(`${'a'.repeat(5000)}`).contact.email).toBeNull(); + }); +}); diff --git a/packages/auth-kit/src/tokens.ts b/packages/auth-kit/src/tokens.ts index 488f521..fe2b7fd 100644 --- a/packages/auth-kit/src/tokens.ts +++ b/packages/auth-kit/src/tokens.ts @@ -26,6 +26,23 @@ export function createTokenVerifierConfig(env: TokenVerifierEnvSource): TokenVer }; } +/** + * True when verification failed because the key set could not be obtained or read, not because + * of anything wrong with the token: the endpoint is unreachable, slow, answers with an error, or + * serves something that is not a key set. A project that is paused or briefly down must read as + * "try again" (503), not as "this session is invalid" (401), or every client signs its user out. + * A plain JOSEError (neither a token problem such as a bad signature or an expired claim, nor a + * more specific key-set error) is what jose raises for a non-200 key-set response. + */ +function isKeySetUnavailable(cause: unknown): boolean { + if (!(cause instanceof joseErrors.JOSEError)) return true; + return ( + cause instanceof joseErrors.JWKSTimeout || + cause instanceof joseErrors.JWKSInvalid || + cause.constructor === joseErrors.JOSEError + ); +} + /** Verifies signature, issuer, and expiry, then re-validates the claim shape. */ export async function verifyAccessToken( token: string, @@ -36,8 +53,16 @@ export async function verifyAccessToken( ({ payload } = await jwtVerify(token, config.jwks, { issuer: config.issuer, audience: 'authenticated', + // jose treats a missing `exp` as "never expires" unless told otherwise. Supabase always + // sets both, so a token without them was not issued by it. + requiredClaims: ['exp', 'sub'], })); } catch (cause) { + if (isKeySetUnavailable(cause)) { + throw new AppError('UPSTREAM_UNAVAILABLE', 'Sign-in keys are temporarily unavailable', { + cause, + }); + } const message = cause instanceof joseErrors.JWTExpired ? 'Access token has expired' : 'Access token is invalid'; throw new AppError('UNAUTHENTICATED', message, { cause }); diff --git a/packages/auth-kit/test/bundles-e2e.test.ts b/packages/auth-kit/test/bundles-e2e.test.ts new file mode 100644 index 0000000..22ce5ff --- /dev/null +++ b/packages/auth-kit/test/bundles-e2e.test.ts @@ -0,0 +1,474 @@ +import { randomUUID } from 'node:crypto'; +import { existsSync, mkdtempSync, readdirSync, rmSync } from 'node:fs'; +import { createServer, type IncomingMessage, type Server, type ServerResponse } from 'node:http'; +import type { AddressInfo } from 'node:net'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { deflateSync } from 'node:zlib'; +import { exportJWK, generateKeyPair, SignJWT, type CryptoKey } from 'jose'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { createDatabase, type DatabaseHandle } from '../../db/src/index.js'; +import { buildDocx, buildPdf } from '../../../services/profile/test/fixtures.js'; + +/** + * The committed `api//index.js` files are what Vercel runs. Everything else in the test + * suite exercises the TypeScript sources; this boots the bundles themselves, as Vercel would (one + * default-exported request handler per file, no listening socket), behind a real HTTP server, against + * a real Postgres and a stand-in Supabase that serves a signing key. It catches what a bundle can get + * wrong that the source cannot: a dependency left out or mis-bundled, a module that fails at import, + * a route that is not wired. + */ +const testDatabaseUrl = process.env.ATLAS_TEST_DATABASE_URL; +const ROOT = fileURLToPath(new URL('../../../', import.meta.url)); +const SERVICES = ['admin', 'analytics', 'applications', 'auth', 'jobs', 'learning', 'matching', 'outreach', 'profile', 'referrals'] as const; +type Service = (typeof SERVICES)[number]; + +/** A path that needs a signed-in user, per service. */ +const PROTECTED_PATH: Record = { + admin: `/v1/admin/organizations/${randomUUID()}/students`, + analytics: '/v1/analytics/summary', + applications: '/v1/applications', + auth: '/v1/auth/me', + jobs: '/v1/jobs', + learning: '/v1/learning/metrics', + matching: '/internal/matching/drain', + outreach: '/v1/messages', + profile: '/v1/resumes', + referrals: '/v1/referrals', +}; + +// The responses are checked field by field below; their exact types are the services' business. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const read = async (response: Response): Promise => response.json(); + +describe.skipIf(!testDatabaseUrl)('the committed deploy bundles, booted for real', () => { + const adminId = randomUUID(); + const userId = randomUUID(); + const cronSecret = `cron-${randomUUID()}`; + const storageRoot = mkdtempSync(join(tmpdir(), 'atlas-bundles-')); + const servers: Server[] = []; + const bases = {} as Record; + const modules: Array<{ app?: { close(): Promise } }> = []; + const apps = {} as Record; + let issuer: Server; + let signingKey: CryptoKey; + let handle: DatabaseHandle; + let userToken: string; + let adminToken: string; + const savedEnv = { ...process.env }; + + const token = async (sub: string, email: string): Promise => + new SignJWT({ session_id: randomUUID(), email, app_metadata: {} }) + .setProtectedHeader({ alg: 'ES256', kid: 'bundle-key' }) + .setSubject(sub) + .setIssuer(`${issuerBase}/auth/v1`) + .setAudience('authenticated') + .setIssuedAt() + .setExpirationTime(Math.floor(Date.now() / 1000) + 900) + .sign(signingKey); + let issuerBase = ''; + + async function listen(handler: (req: IncomingMessage, res: ServerResponse) => unknown): Promise<{ server: Server; base: string }> { + const server = createServer((req, res) => { + Promise.resolve(handler(req, res)).catch(() => { + if (!res.headersSent) res.writeHead(500); + res.end(); + }); + }); + await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); + return { server, base: `http://127.0.0.1:${(server.address() as AddressInfo).port}` }; + } + + beforeAll(async () => { + const pair = await generateKeyPair('ES256', { extractable: true }); + signingKey = pair.privateKey; + const jwk = { ...(await exportJWK(pair.publicKey)), kid: 'bundle-key', alg: 'ES256', use: 'sig' }; + const stub = await listen((req, res) => { + res.writeHead(req.url === '/auth/v1/.well-known/jwks.json' ? 200 : 404, { 'content-type': 'application/json' }); + res.end(req.url === '/auth/v1/.well-known/jwks.json' ? JSON.stringify({ keys: [jwk] }) : '{}'); + }); + issuer = stub.server; + issuerBase = stub.base; + + handle = createDatabase({ url: testDatabaseUrl! }); + for (const [id, email] of [[adminId, `bundle-admin-${adminId}@example.com`], [userId, `bundle-user-${userId}@example.com`]] as const) { + await handle.sql` + insert into auth.users (id, instance_id, aud, role, email, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at) + values (${id}, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', ${email}, now(), '{"provider":"email"}'::jsonb, '{"full_name":"Bundle Test"}'::jsonb, now(), now()) + `; + } + userToken = await token(userId, `bundle-user-${userId}@example.com`); + adminToken = await token(adminId, `bundle-admin-${adminId}@example.com`); + + // What Vercel supplies, plus the configuration every service needs. VERCEL makes each bundle + // export its handler instead of opening a socket. + Object.assign(process.env, { + VERCEL: '1', + LOG_LEVEL: savedEnv.BUNDLE_TEST_LOG_LEVEL ?? 'fatal', + DATABASE_URL: testDatabaseUrl, + SUPABASE_URL: issuerBase, + STORAGE_LOCAL_ROOT: storageRoot, + PLATFORM_ADMIN_USER_IDS: adminId, + CRON_SECRET: cronSecret, + RATE_LIMIT_MAX: '100000', + // Every request here comes from one address; the limits are not what is under test. + PRIVACY_EXPORT_RATE_LIMIT_MAX: '1000', + PRIVACY_DELETE_RATE_LIMIT_MAX: '1000', + }); + for (const service of SERVICES) { + const file = join(ROOT, 'api', service, 'index.js'); + expect(existsSync(file), `${file} is committed`).toBe(true); + const mod = (await import(pathToFileURL(file).href)) as { default: (req: IncomingMessage, res: ServerResponse) => unknown; app?: { close(): Promise } }; + expect(typeof mod.default, `${service} bundle default-exports a handler`).toBe('function'); + modules.push(mod); + apps[service] = (mod as unknown as { app: { printRoutes(options?: object): string } }).app; + const listening = await listen(mod.default); + servers.push(listening.server); + bases[service] = listening.base; + } + }, 120_000); + + afterAll(async () => { + for (const mod of modules) await mod.app?.close().catch(() => undefined); + for (const server of [...servers, issuer]) await new Promise((resolve) => server?.close(resolve)); + if (handle) { + await handle.sql`delete from auth.users where id in (${adminId}, ${userId})`; + await handle.close(); + } + rmSync(storageRoot, { recursive: true, force: true }); + for (const key of Object.keys(process.env)) if (!(key in savedEnv)) delete process.env[key]; + Object.assign(process.env, savedEnv); + }); + + const call = (service: Service, path: string, init: RequestInit & { bearer?: string } = {}) => { + const { bearer, headers, ...rest } = init; + return fetch(`${bases[service]}${path}`, { + ...rest, + headers: { ...(bearer ? { authorization: `Bearer ${bearer}` } : {}), ...(headers as Record | undefined) }, + }); + }; + + it.each(SERVICES)('%s: answers /health, and turns an anonymous caller away from its API', async (service) => { + const health = await call(service, '/health'); + expect(health.status).toBe(200); + const anonymous = await call(service, PROTECTED_PATH[service]); + expect(anonymous.status).toBe(401); + expect((await read(anonymous)).error).toMatchObject({ code: expect.any(String), request_id: expect.any(String) }); + const forged = await call(service, PROTECTED_PATH[service], { bearer: 'not.a.token' }); + expect(forged.status).toBe(401); + }); + + /** Every `{ method, path }` a booted app serves, read from Fastify's printed route tree. */ + function routesOf(service: Service): Array<{ method: string; path: string }> { + const found: Array<{ method: string; path: string }> = []; + const stack: string[] = []; + for (const line of apps[service].printRoutes({ commonPrefix: false }).split('\n')) { + const match = /^((?:│ {3}| {4})*)(?:├── |└── )(.+?)(?: \(([A-Z, ]+)\))?$/.exec(line); + if (match === null) continue; + const depth = (match[1] ?? '').length / 4; + stack.length = depth; + stack[depth] = match[2] as string; + for (const method of (match[3] ?? '').split(', ').filter(Boolean)) found.push({ method, path: stack.join('') }); + } + return found; + } + + // The rule the whole API rests on: nothing but the probes answers a caller who has not signed in. + // Walking the routes the deployed code really registers (rather than a list someone keeps up to + // date) means a new route that forgets its authentication preHandler fails here. + it('every route of every bundle other than /health and /metrics turns an anonymous caller and a forged token away', async () => { + const probes = new Set(['/health', '/metrics']); + const boundary = 'anonymous-boundary'; + let checked = 0; + for (const service of SERVICES) { + const routes = routesOf(service).filter(({ method, path }) => !probes.has(path) && method !== 'OPTIONS' && method !== 'HEAD' && path !== '*'); + expect(routes.length, `${service} has routes to check`).toBeGreaterThan(0); + for (const { method, path } of routes) { + const url = path.replace(/:\w+/g, () => randomUUID()); + const isUpload = method === 'POST' && path === '/v1/resumes'; + const body = method === 'GET' ? undefined : isUpload ? `--${boundary}\r\nContent-Disposition: form-data; name="file"; filename="a.txt"\r\nContent-Type: text/plain\r\n\r\nhi\r\n--${boundary}--\r\n` : '{}'; + const headers = { 'content-type': isUpload ? `multipart/form-data; boundary=${boundary}` : 'application/json' }; + for (const bearer of [undefined, 'not.a.token']) { + const response = await call(service, url, { method, body, headers: { ...headers, ...(bearer ? { authorization: `Bearer ${bearer}` } : {}) } }); + expect(response.status, `${service} ${method} ${path} ${bearer ? 'with a forged token' : 'anonymously'}`).toBe(401); + } + checked += 1; + } + } + expect(checked).toBeGreaterThan(25); + }); + + it('auth: GET /v1/auth/me returns the signed-in user, and the export works', async () => { + const me = await call('auth', '/v1/auth/me', { bearer: userToken }); + expect(me.status).toBe(200); + expect(JSON.stringify(await read(me))).toContain(userId); + const exported = await call('auth', '/v1/auth/me/export', { bearer: userToken }); + expect(exported.status).toBe(200); + }); + + let jobId = ''; + it('jobs: only a platform admin can ingest; the posting is then listed and readable', async () => { + const posting = { + source: 'manual', + external_id: null, + title: `Bundle Test Engineer ${userId.slice(0, 8)}`, + company_name: `Bundle Test Co ${userId.slice(0, 8)}`, + description: 'Build services in TypeScript and PostgreSQL.', + location: 'Berlin', + remote_type: 'remote', + apply_url: 'https://example.com/jobs/1', + }; + const refused = await call('jobs', '/v1/jobs/ingest', { method: 'POST', bearer: userToken, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ postings: [posting] }) }); + expect(refused.status).toBe(403); + const ingested = await call('jobs', '/v1/jobs/ingest', { method: 'POST', bearer: adminToken, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ postings: [posting] }) }); + expect(ingested.status).toBe(200); + expect(await read(ingested)).toMatchObject({ inserted: 1, rejected: 0 }); + + const list = await call('jobs', '/v1/jobs?limit=100', { bearer: userToken }); + expect(list.status).toBe(200); + const found = ((await read(list)).items as Array<{ job_id: string; title: string; company_name: string }>).find((job) => job.title === posting.title); + expect(found?.company_name).toBe(posting.company_name); + jobId = found!.job_id; + const one = await call('jobs', `/v1/jobs/${jobId}`, { bearer: userToken }); + expect(one.status).toBe(200); + }); + + it('jobs: the scheduler route needs the secret and answers its report', async () => { + expect((await call('jobs', '/internal/jobs/ingest-sources')).status).toBe(401); + expect((await call('jobs', '/internal/jobs/ingest-sources', { bearer: 'wrong-secret-wrong-secret' })).status).toBe(401); + const run = await call('jobs', '/internal/jobs/ingest-sources?limit=1', { bearer: cronSecret }); + expect(run.status).toBe(200); + }); + + const upload = async (name: string, type: string, bytes: Buffer) => { + const form = new FormData(); + form.append('file', new Blob([new Uint8Array(bytes)], { type }), name); + return call('profile', '/v1/resumes', { method: 'POST', bearer: userToken, body: form }); + }; + let resumeId = ''; + + it('profile: reads a text resume, a PDF and a DOCX inside the bundle (the parsing libraries are really there)', async () => { + // The text resume goes last: matching scores against the latest parsed resume. + const asPdf = await upload('resume.pdf', 'application/pdf', buildPdf(['Grace Hopper', 'Compiler pioneer. TypeScript. PostgreSQL.'])); + expect(asPdf.status).toBe(201); + expect((await read(asPdf)).status, 'PDF upload').toBe('parsed'); + + const asDocx = await upload( + 'resume.docx', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + buildDocx(['Alan Turing', 'Mathematician. Python. SQL.']), + ); + expect(asDocx.status).toBe(201); + expect((await read(asDocx)).status, 'DOCX upload').toBe('parsed'); + + const text = Buffer.from( + 'Ada Lovelace\nada@example.com\n+1 555 123 4567\n\nSummary\nBackend engineer.\n\nExperience\nAcme Corp — Engineer\nJan 2019 - Present\n- Built TypeScript services serving 2M users\n\nSkills\nTypeScript, PostgreSQL, Node.js\n', + ); + const asText = await upload('resume.txt', 'text/plain', text); + expect(asText.status).toBe(201); + const textBody = await read(asText); + expect(textBody.status, 'text upload').toBe('parsed'); + resumeId = textBody.resume_id; + + const list = await call('profile', '/v1/resumes', { bearer: userToken }); + expect((await read(list)).items).toHaveLength(3); + }); + + it('profile: refuses a file that is not what it says', async () => { + const liar = await upload('resume.pdf', 'application/pdf', Buffer.from('this is plain text, not a PDF')); + expect([400, 415]).toContain(liar.status); + }); + + it('profile: a PDF decompression bomb (a 40 MB page in 40 KB) is recorded as too complex, quickly, not a crash', async () => { + const stream = deflateSync(Buffer.alloc(40 * 1024 * 1024, 0x20), { level: 9 }); + const bomb = Buffer.concat([ + Buffer.from('%PDF-1.4\n1 0 obj\n<< /Length 0 /Filter /FlateDecode >>\nstream\n', 'latin1'), + stream, + Buffer.from('\nendstream\nendobj\ntrailer\n<< /Root 1 0 R >>\n%%EOF\n', 'latin1'), + ]); + expect(bomb.length).toBeLessThan(100 * 1024); + const started = performance.now(); + const response = await upload('bomb.pdf', 'application/pdf', bomb); + expect(response.status).toBe(201); + const body = await read(response); + expect(body.status).toBe('failed'); + expect(performance.now() - started).toBeLessThan(5_000); + const stored = await read(await call('profile', `/v1/resumes/${body.resume_id}`, { bearer: userToken })); + expect(JSON.stringify(stored)).toContain('too large or complex'); + }); + + it('profile: optimizes the resume against the job', async () => { + const res = await call('profile', `/v1/resumes/${resumeId}/optimize`, { + method: 'POST', + bearer: userToken, + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ job_id: jobId }), + }); + expect(res.status).toBe(200); + }); + + it('applications: creates an application, replays it, and moves it through the lifecycle', async () => { + const create = () => + call('applications', '/v1/applications', { + method: 'POST', + bearer: userToken, + headers: { 'content-type': 'application/json', 'idempotency-key': 'bundle-e2e-key-0001' }, + body: JSON.stringify({ job_id: jobId, resume_id: resumeId, mode: 'manual' }), + }); + const first = await create(); + expect(first.status).toBe(201); + const applicationId = (await read(first)).application.application_id as string; + expect((await create()).status).toBe(200); + const moved = await call('applications', `/v1/applications/${applicationId}/events`, { + method: 'POST', + bearer: userToken, + headers: { 'content-type': 'application/json' }, + body: JSON.stringify({ to_status: 'submitted' }), + }); + expect(moved.status).toBe(200); + expect((await read(moved)).application.status).toBe('submitted'); + const mine = await call('applications', '/v1/applications', { bearer: userToken }); + expect(((await read(mine)) as { items: unknown[] }).items).toHaveLength(1); + }); + + // The product's main loop, across four deployed functions and the Postgres outbox: a resume is parsed + // (profile), a job is discovered (jobs), the matching consumer scores the pair when its drain route is + // called, and the score shows up as a recommendation (jobs again). + it('matching: after the drain, the uploaded resume produces a recommendation for the ingested job', async () => { + const drain = await call('matching', '/internal/matching/drain?limit=1000&budget_ms=20000', { method: 'POST', bearer: cronSecret }); + expect(drain.status).toBe(200); + const result = await read(drain); + expect(result.processed ?? result.delivered ?? result.handled ?? 0, JSON.stringify(result)).toBeGreaterThan(0); + + const recommendations = await call('jobs', `/v1/jobs/recommendations?user_id=${userId}&limit=50`, { bearer: userToken }); + expect(recommendations.status).toBe(200); + const items = (await read(recommendations)).items as Array<{ job: { job_id: string }; score: number; reasons: string[] }>; + const mine = items.find((item) => item.job.job_id === jobId); + expect(mine, `the ingested job is recommended (${items.length} items)`).toBeDefined(); + expect(mine!.score).toBeGreaterThan(0); + expect(mine!.reasons.join(' ')).toMatch(/typescript|postgresql/i); + }); + + it('the other consumers drain cleanly too, and a drain with the wrong secret is refused', async () => { + for (const [service, path] of [['learning', '/internal/learning/drain'], ['analytics', '/internal/analytics/drain'], ['referrals', '/internal/referrals/drain']] as const) { + expect((await call(service, path, { method: 'POST' })).status, `${service} anonymous`).toBe(401); + expect((await call(service, path, { method: 'POST', bearer: 'wrong-secret-wrong-secret' })).status, `${service} wrong secret`).toBe(401); + const drained = await call(service, `${path}?limit=1000&budget_ms=20000`, { method: 'POST', bearer: cronSecret }); + expect(drained.status, `${service} drain`).toBe(200); + } + }); + + // The university pilot, through the admin bundle: staff of a university import a roster, read it + // back, export it and see the funnel; someone who is not a member of the organization is told it does + // not exist. + it('admin: a university owner imports a roster and reads it back; a non-member gets 404', async () => { + const staffId = randomUUID(); + const organizationId = randomUUID(); + await handle.sql` + insert into auth.users (id, instance_id, aud, role, email, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at) + values (${staffId}, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', ${`bundle-staff-${staffId}@example.com`}, now(), '{"provider":"email"}'::jsonb, '{}'::jsonb, now(), now()) + `; + await handle.sql`insert into public.organizations (organization_id, name, type) values (${organizationId}, ${`Bundle University ${organizationId.slice(0, 8)}`}, 'university')`; + await handle.sql`insert into public.organization_members (organization_id, user_id, role) values (${organizationId}, ${staffId}, 'owner')`; + try { + const staffToken = await token(staffId, `bundle-staff-${staffId}@example.com`); + const base = `/v1/admin/organizations/${organizationId}`; + const studentEmail = `bundle-user-${userId}@example.com`; + + const imported = await call('admin', `${base}/students/import`, { + method: 'POST', + bearer: staffToken, + headers: { 'content-type': 'text/csv', 'idempotency-key': randomUUID() }, + body: `email,full_name,program,graduation_year\n${studentEmail},Bundle Student,Computer Science,2027\nnobody-${randomUUID()}@example.com,No Body,Physics,2026\n`, + }); + expect(imported.status, await imported.clone().text()).toBe(200); + expect(await read(imported)).toMatchObject({ total_rows: 2, created: 1, skipped: 1, skipped_breakdown: { no_platform_account: 1 } }); + + const list = await read(await call('admin', `${base}/students`, { bearer: staffToken })); + expect(list.items).toHaveLength(1); + expect(list.items[0]).toMatchObject({ email: studentEmail, program: 'Computer Science', graduation_year: 2027, sharing_enabled: false }); + // Identity only until the student joins the organization: no name, no activity. + expect(list.items[0].full_name).toBeNull(); + expect(list.items[0].insights).toBeNull(); + + const exported = await call('admin', `${base}/export.csv`, { bearer: staffToken }); + expect(exported.status).toBe(200); + expect(exported.headers.get('content-type')).toMatch(/text\/csv/); + expect(await exported.text()).toContain(studentEmail); + expect((await call('admin', `${base}/funnel`, { bearer: staffToken })).status).toBe(200); + + // The regular user is no member: the organization does not exist as far as they can tell. + for (const path of [`${base}/students`, `${base}/funnel`, `${base}/export.csv`]) { + expect((await call('admin', path, { bearer: userToken })).status, path).toBe(404); + } + } finally { + await handle.sql`delete from public.organizations where organization_id = ${organizationId}`; + await handle.sql`delete from auth.users where id = ${staffId}`; + } + }); + + // Account deletion across two deployed functions and the storage the profile one writes: the auth + // bundle must remove the files the profile bundle stored, and what a still-valid token can do afterwards. + it('auth: deleting an account removes its rows and its stored files, and the old token then gets nothing', async () => { + const leaverId = randomUUID(); + const leaverEmail = `bundle-leaver-${leaverId}@example.com`; + await handle.sql` + insert into auth.users (id, instance_id, aud, role, email, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at) + values (${leaverId}, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', ${leaverEmail}, now(), '{"provider":"email"}'::jsonb, '{"full_name":"Bundle Leaver"}'::jsonb, now(), now()) + `; + const leaverToken = await token(leaverId, leaverEmail); + const form = new FormData(); + form.append('file', new Blob([`Leaver Resume ${leaverId}\nBackend engineer\nTypeScript, PostgreSQL`], { type: 'text/plain' }), 'leaver.txt'); + const uploaded = await call('profile', '/v1/resumes', { method: 'POST', bearer: leaverToken, body: form }); + expect(uploaded.status).toBe(201); + const stored = await handle.sql>`select storage_url from public.resumes where user_id = ${leaverId}`; + expect(stored).toHaveLength(1); + // On Vercel a `local` storage driver is redirected to the temp directory (see storageOptionsFromEnv). + const file = join(tmpdir(), 'atlas-storage', stored[0]!.storage_url); + expect(existsSync(file), 'the resume file is on disk before deletion').toBe(true); + + const refused = await call('auth', '/v1/auth/me', { method: 'DELETE', bearer: leaverToken, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ confirm: 'delete' }) }); + expect(refused.status).toBe(400); + expect(existsSync(file)).toBe(true); + + const deleted = await call('auth', '/v1/auth/me', { method: 'DELETE', bearer: leaverToken, headers: { 'content-type': 'application/json' }, body: JSON.stringify({ confirm: 'DELETE' }) }); + expect(deleted.status, await deleted.clone().text()).toBe(200); + expect(existsSync(file), 'the resume file is gone after deletion').toBe(false); + const [left] = await handle.sql>` + select (select count(*) from public.resumes where user_id = ${leaverId})::int + + (select count(*) from public.users where user_id = ${leaverId})::int + + (select count(*) from auth.users where id = ${leaverId})::int as n`; + expect(left!.n).toBe(0); + + // The token is a signed statement that stays valid until it expires. It must not bring the account + // back or leave data behind: an upload is refused (never a 2xx), and lists are empty. + const again = new FormData(); + again.append('file', new Blob([`Ghost Resume ${leaverId}\nBackend engineer`], { type: 'text/plain' }), 'ghost.txt'); + const ghost = await call('profile', '/v1/resumes', { method: 'POST', bearer: leaverToken, body: again }); + expect(ghost.status, 'a deleted account cannot upload: it is told the account is gone').toBe(401); + // (The local driver removes files, not the now-empty folder.) + const folder = join(tmpdir(), 'atlas-storage', 'resumes', leaverId); + expect(existsSync(folder) ? readdirSync(folder) : [], 'and nothing is stored for it').toEqual([]); + const [ghostRows] = await handle.sql>`select count(*)::int as n from public.resumes where user_id = ${leaverId}`; + expect(ghostRows!.n).toBe(0); + const [ghostFiles] = await handle.sql>`select count(*)::int as n from public.users where user_id = ${leaverId}`; + expect(ghostFiles!.n).toBe(0); + }); + + it('a user cannot read another user\'s resume or application through the bundles', async () => { + const outsider = randomUUID(); + await handle.sql` + insert into auth.users (id, instance_id, aud, role, email, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at) + values (${outsider}, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', ${`bundle-outsider-${outsider}@example.com`}, now(), '{"provider":"email"}'::jsonb, '{}'::jsonb, now(), now()) + `; + try { + const outsiderToken = await token(outsider, `bundle-outsider-${outsider}@example.com`); + expect((await call('profile', `/v1/resumes/${resumeId}`, { bearer: outsiderToken })).status).toBe(404); + const theirs = await call('applications', '/v1/applications', { bearer: outsiderToken }); + expect(((await read(theirs)) as { items: unknown[] }).items).toHaveLength(0); + } finally { + await handle.sql`delete from auth.users where id = ${outsider}`; + } + }); +}); diff --git a/packages/auth-kit/test/tokens-attacks.test.ts b/packages/auth-kit/test/tokens-attacks.test.ts new file mode 100644 index 0000000..7774463 --- /dev/null +++ b/packages/auth-kit/test/tokens-attacks.test.ts @@ -0,0 +1,258 @@ +import { + SignJWT, + base64url, + exportJWK, + exportSPKI, + generateKeyPair, + type CryptoKey, + type JWK, +} from 'jose'; +import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import { AppError } from '@atlas/utils'; + +const SUPABASE_URL = 'https://test-project.supabase.co'; +const ISSUER = `${SUPABASE_URL}/auth/v1`; +const SUB = '11111111-1111-4111-8111-111111111111'; +const SESSION = '22222222-2222-4222-8222-222222222222'; +const ORG = '33333333-3333-4333-8333-333333333333'; + +let signingKey: CryptoKey; +let otherKey: CryptoKey; +let publicJwk: JWK; +let publicPem: string; + +/** What the stubbed JWKS endpoint does on the next fetch. */ +let jwksBehavior: () => Promise; +const serveKeys = () => + Promise.resolve( + new Response(JSON.stringify({ keys: [publicJwk] }), { + status: 200, + headers: { 'content-type': 'application/json' }, + }), + ); + +vi.stubGlobal('fetch', () => jwksBehavior()); + +const { createTokenVerifierConfig, verifyAccessToken } = await import('../src/tokens.js'); + +beforeAll(async () => { + const pair = await generateKeyPair('ES256', { extractable: true }); + signingKey = pair.privateKey; + otherKey = (await generateKeyPair('ES256')).privateKey; + publicJwk = { ...(await exportJWK(pair.publicKey)), kid: 'good-key', alg: 'ES256', use: 'sig' }; + publicPem = await exportSPKI(pair.publicKey); +}); + +beforeEach(() => { + jwksBehavior = serveKeys; +}); + +interface Options { + key?: CryptoKey; + header?: Record; + payload?: Record; + omit?: string[]; + exp?: number | null; + nbf?: number; +} + +async function token(options: Options = {}): Promise { + const now = Math.floor(Date.now() / 1000); + const payload: Record = { + session_id: SESSION, + email: 'ada@example.com', + app_metadata: {}, + ...options.payload, + }; + const jwt = new SignJWT(payload) + .setProtectedHeader({ alg: 'ES256', kid: 'good-key', ...options.header }) + .setIssuer(ISSUER) + .setAudience('authenticated') + .setIssuedAt(); + if (!options.omit?.includes('sub')) jwt.setSubject(SUB); + if (options.exp !== null) jwt.setExpirationTime(options.exp ?? now + 900); + if (options.nbf !== undefined) jwt.setNotBefore(options.nbf); + return jwt.sign(options.key ?? signingKey); +} + +function verify(jwt: string) { + // A fresh config each time: it holds the JWKS cache. + return verifyAccessToken(jwt, createTokenVerifierConfig({ SUPABASE_URL })); +} + +async function status(jwt: string): Promise<{ code: string; httpStatus: number } | 'accepted'> { + try { + await verify(jwt); + return 'accepted'; + } catch (error) { + if (error instanceof AppError) return { code: error.code, httpStatus: error.statusCode }; + throw error; + } +} + +const rejected = { code: 'UNAUTHENTICATED', httpStatus: 401 }; + +describe('forged and tampered tokens are all refused as unauthenticated', () => { + it('accepts a correctly signed token (the control for everything below)', async () => { + expect(await status(await token())).toBe('accepted'); + }); + + it('refuses alg "none", with and without a signature part', async () => { + const header = base64url.encode(JSON.stringify({ alg: 'none', typ: 'JWT' })); + const body = base64url.encode( + JSON.stringify({ + sub: SUB, + session_id: SESSION, + email: 'ada@example.com', + iss: ISSUER, + aud: 'authenticated', + exp: Math.floor(Date.now() / 1000) + 900, + app_metadata: { role: 'owner', org_id: ORG }, + }), + ); + expect(await status(`${header}.${body}.`)).toEqual(rejected); + expect(await status(`${header}.${body}`)).toEqual(rejected); + expect(await status(`${header}.${body}.AAAA`)).toEqual(rejected); + }); + + it('refuses an HS256 token whose secret is the public key (algorithm confusion)', async () => { + const claims = { session_id: SESSION, email: 'ada@example.com', app_metadata: { role: 'owner', org_id: ORG } }; + for (const secret of [publicPem, JSON.stringify(publicJwk), String(publicJwk.x) + String(publicJwk.y)]) { + const forged = await new SignJWT(claims) + .setProtectedHeader({ alg: 'HS256', kid: 'good-key' }) + .setSubject(SUB) + .setIssuer(ISSUER) + .setAudience('authenticated') + .setExpirationTime('15m') + .sign(new TextEncoder().encode(secret)); + expect(await status(forged)).toEqual(rejected); + } + }); + + it('refuses a token signed by another key, whatever kid it claims', async () => { + expect(await status(await token({ key: otherKey }))).toEqual(rejected); + expect(await status(await token({ key: otherKey, header: { kid: 'unknown-key' } }))).toEqual(rejected); + expect(await status(await token({ key: otherKey, header: { kid: undefined } }))).toEqual(rejected); + }); + + it('refuses a token carrying its own key in the header (jwk) or a key URL (jku, x5u)', async () => { + const attackerPublic = { ...(await exportJWK((await generateKeyPair('ES256', { extractable: true })).publicKey)) }; + expect(await status(await token({ key: otherKey, header: { jwk: attackerPublic } }))).toEqual(rejected); + expect( + await status(await token({ key: otherKey, header: { jku: 'https://evil.example/jwks.json' } })), + ).toEqual(rejected); + expect(await status(await token({ key: otherKey, header: { x5u: 'https://evil.example/cert.pem' } }))).toEqual( + rejected, + ); + }); + + it('refuses a payload swapped under a valid signature', async () => { + const [header, , signature] = (await token()).split('.'); + const swapped = base64url.encode( + JSON.stringify({ + sub: SUB, + session_id: SESSION, + email: 'ada@example.com', + iss: ISSUER, + aud: 'authenticated', + exp: Math.floor(Date.now() / 1000) + 900, + app_metadata: { role: 'owner', org_id: ORG }, + }), + ); + expect(await status(`${header}.${swapped}.${signature}`)).toEqual(rejected); + }); + + it('refuses wrong issuer, wrong audience (string and array), and a token that is not yet valid', async () => { + const now = Math.floor(Date.now() / 1000); + const custom = (overrides: (jwt: SignJWT) => SignJWT) => + overrides( + new SignJWT({ session_id: SESSION, email: 'ada@example.com', app_metadata: {} }) + .setProtectedHeader({ alg: 'ES256', kid: 'good-key' }) + .setSubject(SUB) + .setExpirationTime(now + 900), + ).sign(signingKey); + + expect(await status(await custom((jwt) => jwt.setIssuer('https://evil.example/auth/v1').setAudience('authenticated')))).toEqual(rejected); + expect(await status(await custom((jwt) => jwt.setIssuer(`${ISSUER}/`).setAudience('authenticated')))).toEqual(rejected); + expect(await status(await custom((jwt) => jwt.setIssuer(ISSUER).setAudience('anon')))).toEqual(rejected); + expect(await status(await custom((jwt) => jwt.setIssuer(ISSUER).setAudience(['anon', 'service_role'])))).toEqual(rejected); + expect(await status(await custom((jwt) => jwt.setIssuer(ISSUER)))).toEqual(rejected); // no audience at all + expect(await status(await custom((jwt) => jwt.setIssuer(ISSUER).setAudience('authenticated').setNotBefore(now + 3600)))).toEqual(rejected); + }); + + it('refuses garbage that is not a token, including very large input, without throwing anything but a 401', async () => { + for (const junk of ['', ' ', 'x', 'a.b', 'a.b.c', '....', '\u0000', '🔑.🔑.🔑', 'a'.repeat(1_000_000), `${'a'.repeat(2000)}.${'b'.repeat(2000)}.${'c'.repeat(2000)}`]) { + expect(await status(junk)).toEqual(rejected); + } + }); +}); + +describe('claims', () => { + it('refuses a token with no expiry', async () => { + expect(await status(await token({ exp: null }))).toEqual(rejected); + }); + + it('refuses a token with no subject, or a subject that is not a uuid', async () => { + expect(await status(await token({ omit: ['sub'] }))).toEqual(rejected); + const notUuid = new SignJWT({ session_id: SESSION, email: 'ada@example.com', app_metadata: {} }) + .setProtectedHeader({ alg: 'ES256', kid: 'good-key' }) + .setSubject("1'; drop table users;--") + .setIssuer(ISSUER) + .setAudience('authenticated') + .setExpirationTime('15m') + .sign(signingKey); + expect(await status(await notUuid)).toEqual(rejected); + }); + + it('refuses an unknown role, or an org id that is not a uuid, in app_metadata', async () => { + expect(await status(await token({ payload: { app_metadata: { role: 'superuser', org_id: ORG } } }))).toEqual(rejected); + expect(await status(await token({ payload: { app_metadata: { role: 'owner', org_id: 'not-a-uuid' } } }))).toEqual(rejected); + expect(await status(await token({ payload: { app_metadata: { role: ['owner'], org_id: ORG } } }))).toEqual(rejected); + }); + + it('takes role and organization only from app_metadata, never from user_metadata or the top level', async () => { + const claims = await verify( + await token({ + payload: { + role: 'owner', + org_id: ORG, + org: ORG, + user_metadata: { role: 'owner', org_id: ORG }, + app_metadata: {}, + }, + }), + ); + expect(claims.role).toBeNull(); + expect(claims.org).toBeNull(); + }); +}); + +describe('when the key set cannot be fetched', () => { + // A paused or unreachable project is not the caller's fault: answering 401 makes every client think + // its session died and sign the user out, where 503 tells it to try again. + const unavailable = { code: 'UPSTREAM_UNAVAILABLE', httpStatus: 503 }; + + it('answers 503 when the key endpoint cannot be reached', async () => { + jwksBehavior = () => Promise.reject(new TypeError('fetch failed')); + expect(await status(await token())).toEqual(unavailable); + }); + + it('answers 503 when the key endpoint answers with a server error or a non-key body', async () => { + jwksBehavior = () => Promise.resolve(new Response('upstream broke', { status: 502 })); + expect(await status(await token())).toEqual(unavailable); + jwksBehavior = () => Promise.resolve(new Response('paused', { status: 200 })); + expect(await status(await token())).toEqual(unavailable); + jwksBehavior = () => Promise.resolve(new Response('{"keys":"nope"}', { status: 200 })); + expect(await status(await token())).toEqual(unavailable); + }); + + it('still refuses (401) a bad token when the key endpoint is healthy but has no matching key', async () => { + jwksBehavior = () => Promise.resolve(new Response('{"keys":[]}', { status: 200 })); + expect(await status(await token())).toEqual(rejected); + }); + + it('never lets a token through when the key endpoint is down', async () => { + jwksBehavior = () => Promise.reject(new TypeError('fetch failed')); + expect(await status(await token())).not.toBe('accepted'); + }); +}); diff --git a/packages/config/src/env.ts b/packages/config/src/env.ts index 11825f8..8160a5d 100644 --- a/packages/config/src/env.ts +++ b/packages/config/src/env.ts @@ -48,25 +48,177 @@ export const storageEnvSchema = z.object({ SUPABASE_SECRET_KEY: z.string().min(1).optional(), }); +const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']); + +/** + * The project URL as an origin (`https://abc.supabase.co`), or `undefined` when it cannot be one. + * Tokens are checked against `/auth/v1` as their issuer and the signing keys are fetched from + * under it, so the value must be exact: a trailing slash (`https://abc.supabase.co/`, the way the + * dashboard shows it) makes the issuer `https://abc.supabase.co//auth/v1`, which no token carries, + * and every request is refused as unauthenticated. Plain `http` is only for a local stack, since a + * key set fetched in the clear can be swapped on the way. + */ +export function normalizeSupabaseUrl(value: string): string | undefined { + let url: URL; + try { + url = new URL(value.trim()); + } catch { + return undefined; + } + if (url.username !== '' || url.password !== '') return undefined; + const secure = url.protocol === 'https:'; + const localStack = url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname); + return secure || localStack ? url.origin : undefined; +} + +export const supabaseUrlSchema = z.string().transform((value, ctx) => { + const origin = normalizeSupabaseUrl(value); + if (origin === undefined) { + ctx.addIssue({ + code: 'custom', + message: 'SUPABASE_URL must be an https URL such as https://abc.supabase.co (http only for localhost)', + }); + return z.NEVER; + } + return origin; +}); + /** * Every service that verifies a caller's identity needs only the (non-secret) * Supabase project URL — tokens are checked against its JWKS, not a shared * secret. See packages/auth-kit/src/tokens.ts. */ export const supabaseAuthEnvSchema = z.object({ - SUPABASE_URL: z.string().url('SUPABASE_URL must be a valid URL'), + SUPABASE_URL: supabaseUrlSchema, }); +const WINDOW_UNIT_MS: Record = { + s: 1_000, + sec: 1_000, + secs: 1_000, + second: 1_000, + seconds: 1_000, + m: 60_000, + min: 60_000, + mins: 60_000, + minute: 60_000, + minutes: 60_000, + h: 3_600_000, + hr: 3_600_000, + hrs: 3_600_000, + hour: 3_600_000, + hours: 3_600_000, + d: 86_400_000, + day: 86_400_000, + days: 86_400_000, +}; + +const RATE_LIMIT_WINDOW_MIN_MS = 1_000; +const RATE_LIMIT_WINDOW_MAX_MS = 7 * 86_400_000; + +/** + * The length in milliseconds of a rate-limit window written as ` ` (`30 seconds`, + * `1 minute`, `2h`), or `undefined` when the text is not that. A bare number is refused on purpose: + * the rate-limit plugin reads `60` as 60 milliseconds, which switches limiting off in practice. + */ +export function parseRateLimitWindowMs(text: string): number | undefined { + const match = /^(\d+(?:\.\d+)?)\s*([a-z]+)$/i.exec(text.trim()); + if (match === null) return undefined; + const unit = WINDOW_UNIT_MS[(match[2] ?? '').toLowerCase()]; + if (unit === undefined) return undefined; + return Math.round(Number(match[1]) * unit); +} + +/** + * A rate-limit window such as `1 minute`. The plugin accepts any string at boot and then answers + * every request with a 500 for text it cannot read (`abc`, `1 parsec`, empty), and a negative + * window quietly turns limiting off, so the value is checked here, where a bad one stops the boot. + * Between one second and seven days: below that the limit means nothing, above it a client that + * hits the maximum is locked out for practically ever. + */ +export const rateLimitWindowSchema = z.string().refine( + (text) => { + const ms = parseRateLimitWindowMs(text); + return ms !== undefined && ms >= RATE_LIMIT_WINDOW_MIN_MS && ms <= RATE_LIMIT_WINDOW_MAX_MS; + }, + { + message: + 'must be a number and a unit between 1 second and 7 days, for example "30 seconds", "1 minute" or "1 hour"', + }, +); + +/** + * The form of an allowed origin that a browser's `Origin` header can equal: lower-case scheme and + * host, no path, no trailing slash. `undefined` for text that no browser would ever send, such as a + * host without a scheme, an entry with a path, or `null`. + */ +export function normalizeCorsOrigin(entry: string): string | undefined { + const text = entry.trim(); + let url: URL; + try { + url = new URL(text); + } catch { + return undefined; + } + if (url.protocol !== 'http:' && url.protocol !== 'https:') return undefined; + if (url.username !== '' || url.password !== '' || url.search !== '' || url.hash !== '') { + return undefined; + } + // A single trailing slash is the usual slip and is forgiven; any other path is not an origin. + if (url.pathname !== '/') return undefined; + return url.origin; +} + +function splitCorsOrigins(value: string): string[] { + return value + .split(',') + .map((origin) => origin.trim()) + .filter((origin) => origin.length > 0); +} + +/** + * `CORS_ORIGINS`: empty, `*`, or a comma-separated list of origins. An entry that can never match + * a browser's `Origin` header (`app.example.com`, `https://app.example.com/login`, `null`) is + * refused at boot: it would otherwise start fine and block every browser request. + */ +export const corsOriginsSchema = z + .string() + .default('') + .superRefine((value, ctx) => { + if (value.trim() === '*') return; + for (const entry of splitCorsOrigins(value)) { + if (normalizeCorsOrigin(entry) === undefined) { + ctx.addIssue({ + code: 'custom', + message: `"${entry}" is not an origin; use scheme and host only, such as https://app.example.com`, + }); + } + } + }); + export const httpEnvSchema = z.object({ HOST: z.string().min(1).default('0.0.0.0'), PORT: z.coerce.number().int().min(1).max(65_535), /** Comma-separated list, or `*` in development only. */ - CORS_ORIGINS: z.string().default(''), + CORS_ORIGINS: corsOriginsSchema, RATE_LIMIT_MAX: z.coerce.number().int().min(1).default(300), - RATE_LIMIT_WINDOW: z.string().default('1 minute'), + RATE_LIMIT_WINDOW: rateLimitWindowSchema.default('1 minute'), BODY_LIMIT_BYTES: z.coerce.number().int().min(1024).default(1_048_576), }); +/** + * The shared secret a scheduler presents as `Authorization: Bearer ` to the machine-only + * routes (event drains, job-board ingestion). Surrounding whitespace is dropped, because a secret + * pasted into a dashboard often keeps its trailing newline and the comparison would then never + * succeed. One with whitespace inside is refused: a header value cannot carry it, so the routes + * would answer 401 to the scheduler for ever, with nothing to say why. + */ +export const cronSecretSchema = z + .string() + .trim() + .min(16, 'CRON_SECRET must be at least 16 characters') + .regex(/^\S+$/, 'CRON_SECRET must not contain whitespace'); + export class ConfigError extends Error { constructor( readonly service: string, @@ -98,13 +250,11 @@ export function loadEnv( return result.data as z.infer; } -/** `CORS_ORIGINS` → array, with `*` preserved as a wildcard sentinel. */ +/** `CORS_ORIGINS` → array of canonical origins, with `*` preserved as a wildcard sentinel. */ export function parseCorsOrigins(value: string): string[] | true { const trimmed = value.trim(); if (trimmed === '*') return true; - if (trimmed === '') return []; - return trimmed - .split(',') - .map((origin) => origin.trim()) - .filter((origin) => origin.length > 0); + return splitCorsOrigins(trimmed) + .map(normalizeCorsOrigin) + .filter((origin): origin is string => origin !== undefined); } diff --git a/packages/config/test/cors-origins.test.ts b/packages/config/test/cors-origins.test.ts new file mode 100644 index 0000000..69ae099 --- /dev/null +++ b/packages/config/test/cors-origins.test.ts @@ -0,0 +1,71 @@ +import { describe, expect, it } from 'vitest'; +import { + corsOriginsSchema, + httpEnvSchema, + normalizeCorsOrigin, + parseCorsOrigins, +} from '../src/index.js'; + +describe('CORS_ORIGINS', () => { + it.each([ + ['https://app.example.com', 'https://app.example.com'], + ['https://app.example.com/', 'https://app.example.com'], + ['HTTPS://App.Example.COM', 'https://app.example.com'], + ['http://localhost:3000', 'http://localhost:3000'], + ['https://app.example.com:443', 'https://app.example.com'], + [' https://app.example.com ', 'https://app.example.com'], + ])('reads %j as the origin %j', (entry, origin) => { + expect(normalizeCorsOrigin(entry)).toBe(origin); + }); + + // Each of these started a service that then blocked every browser request, or matched nothing. + it.each([ + 'app.example.com', + '//app.example.com', + 'null', + 'https://app.example.com/login', + 'https://app.example.com?x=1', + 'https://app.example.com#top', + 'https://user:pass@app.example.com', + 'ftp://app.example.com', + 'javascript:alert(1)', + 'https://', + '*.example.com', + '/', + '', + ])('refuses the entry %j', (entry) => { + expect(normalizeCorsOrigin(entry)).toBeUndefined(); + }); + + it('turns the setting into canonical origins and keeps the wildcard as a sentinel', () => { + expect(parseCorsOrigins('')).toEqual([]); + expect(parseCorsOrigins(' ')).toEqual([]); + expect(parseCorsOrigins('*')).toBe(true); + expect(parseCorsOrigins(' * ')).toBe(true); + expect(parseCorsOrigins('https://a.example.com/, http://localhost:3000 ,')).toEqual([ + 'https://a.example.com', + 'http://localhost:3000', + ]); + }); + + it('accepts empty, a wildcard on its own, and a clean list; names the bad entry otherwise', () => { + expect(corsOriginsSchema.safeParse('').success).toBe(true); + expect(corsOriginsSchema.safeParse('*').success).toBe(true); + expect(corsOriginsSchema.safeParse('https://a.example.com/,https://b.example.com').success).toBe(true); + const bad = corsOriginsSchema.safeParse('https://a.example.com,app.example.com,https://b.example.com/x'); + expect(bad.success).toBe(false); + const messages = bad.success ? [] : bad.error.issues.map((issue) => issue.message); + expect(messages).toHaveLength(2); + expect(messages[0]).toContain('"app.example.com"'); + expect(messages[1]).toContain('"https://b.example.com/x"'); + }); + + it('refuses a wildcard mixed into a list, where it would be a literal that matches nothing', () => { + expect(corsOriginsSchema.safeParse('https://a.example.com,*').success).toBe(false); + }); + + it('is what the shared HTTP env validates, with an empty default', () => { + expect(httpEnvSchema.parse({ PORT: '4000' }).CORS_ORIGINS).toBe(''); + expect(httpEnvSchema.safeParse({ PORT: '4000', CORS_ORIGINS: 'app.example.com' }).success).toBe(false); + }); +}); diff --git a/packages/config/test/cron-secret.test.ts b/packages/config/test/cron-secret.test.ts new file mode 100644 index 0000000..7da7424 --- /dev/null +++ b/packages/config/test/cron-secret.test.ts @@ -0,0 +1,24 @@ +import { describe, expect, it } from 'vitest'; +import { cronSecretSchema } from '../src/index.js'; + +const SECRET = 'correct-horse-battery-staple-1234'; + +describe('CRON_SECRET', () => { + it('accepts a long secret and drops the whitespace a dashboard paste leaves around it', () => { + expect(cronSecretSchema.parse(SECRET)).toBe(SECRET); + expect(cronSecretSchema.parse(`${SECRET}\n`)).toBe(SECRET); + expect(cronSecretSchema.parse(` ${SECRET}\r\n`)).toBe(SECRET); + }); + + it.each([ + ['empty', ''], + ['only whitespace', ' '.repeat(40)], + ['too short', 'short-secret'], + ['short once trimmed', ` ${'a'.repeat(10)} `], + ['whitespace inside', 'correct horse battery staple'], + ['a tab inside', 'correct\thorse-battery-staple-1234'], + ['a newline inside', 'correct-horse\nbattery-staple-1234'], + ])('refuses a secret that is %s', (_label, value) => { + expect(cronSecretSchema.safeParse(value).success).toBe(false); + }); +}); diff --git a/packages/config/test/rate-limit-window.test.ts b/packages/config/test/rate-limit-window.test.ts new file mode 100644 index 0000000..2322c84 --- /dev/null +++ b/packages/config/test/rate-limit-window.test.ts @@ -0,0 +1,49 @@ +import { describe, expect, it } from 'vitest'; +import { httpEnvSchema, parseRateLimitWindowMs, rateLimitWindowSchema } from '../src/index.js'; + +describe('rate-limit window', () => { + it.each([ + ['1 second', 1_000], + ['30 seconds', 30_000], + ['1 minute', 60_000], + ['2 mins', 120_000], + ['5m', 300_000], + ['1 hour', 3_600_000], + ['2H', 7_200_000], + ['1 day', 86_400_000], + ['1.5 minutes', 90_000], + [' 10 seconds ', 10_000], + ])('reads %j as %d ms', (text, ms) => { + expect(parseRateLimitWindowMs(text)).toBe(ms); + expect(rateLimitWindowSchema.safeParse(text).success).toBe(true); + }); + + // Each of these booted a service that then answered every request with a 500, or one that + // never limited anything, before the value was checked at boot. + it.each([ + '', + ' ', + 'abc', + '1 parsec', + '0', + '60', + '1000', + '0 seconds', + '-5 minutes', + '1e400', + 'NaN', + '500 ms', + '8 days', + '99999 years', + '1 minute; drop table', + ])('refuses %j', (text) => { + expect(rateLimitWindowSchema.safeParse(text).success).toBe(false); + }); + + it('is what RATE_LIMIT_WINDOW is validated with, and keeps the one-minute default', () => { + const base = { PORT: '4000' }; + expect(httpEnvSchema.parse(base).RATE_LIMIT_WINDOW).toBe('1 minute'); + expect(httpEnvSchema.safeParse({ ...base, RATE_LIMIT_WINDOW: 'abc' }).success).toBe(false); + expect(httpEnvSchema.safeParse({ ...base, RATE_LIMIT_WINDOW: '-5 minutes' }).success).toBe(false); + }); +}); diff --git a/packages/config/test/supabase-url.test.ts b/packages/config/test/supabase-url.test.ts new file mode 100644 index 0000000..95449c7 --- /dev/null +++ b/packages/config/test/supabase-url.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from 'vitest'; +import { normalizeSupabaseUrl, supabaseAuthEnvSchema } from '../src/index.js'; + +describe('SUPABASE_URL', () => { + it.each([ + ['https://abc.supabase.co', 'https://abc.supabase.co'], + ['https://abc.supabase.co/', 'https://abc.supabase.co'], + [' https://abc.supabase.co/ ', 'https://abc.supabase.co'], + ['https://abc.supabase.co/rest/v1/', 'https://abc.supabase.co'], + ['HTTPS://ABC.Supabase.co', 'https://abc.supabase.co'], + ['https://auth.example.com:8443', 'https://auth.example.com:8443'], + ['http://127.0.0.1:54321', 'http://127.0.0.1:54321'], + ['http://localhost:54321/', 'http://localhost:54321'], + ])('reads %j as the origin %j', (value, origin) => { + expect(normalizeSupabaseUrl(value)).toBe(origin); + expect(supabaseAuthEnvSchema.parse({ SUPABASE_URL: value }).SUPABASE_URL).toBe(origin); + }); + + // A trailing slash is the one that matters: it used to start fine and refuse every token. + it.each([ + '', + 'abc.supabase.co', + 'http://abc.supabase.co', + 'http://evil.example', + 'ftp://abc.supabase.co', + 'javascript:alert(1)', + 'https://user:pass@abc.supabase.co', + 'https://', + 'file:///etc/passwd', + ])('refuses %j', (value) => { + expect(normalizeSupabaseUrl(value)).toBeUndefined(); + expect(supabaseAuthEnvSchema.safeParse({ SUPABASE_URL: value }).success).toBe(false); + }); + + it('gives an issuer that matches what Supabase signs, whatever slash the operator pasted', () => { + for (const pasted of ['https://abc.supabase.co', 'https://abc.supabase.co/']) { + const url = supabaseAuthEnvSchema.parse({ SUPABASE_URL: pasted }).SUPABASE_URL; + expect(`${url}/auth/v1`).toBe('https://abc.supabase.co/auth/v1'); + } + }); +}); diff --git a/packages/utils/src/errors.ts b/packages/utils/src/errors.ts index 74e6979..52c4063 100644 --- a/packages/utils/src/errors.ts +++ b/packages/utils/src/errors.ts @@ -64,9 +64,44 @@ export function isAppError(value: unknown): value is AppError { return value instanceof AppError; } +/** + * Codes that mean the database (or the pooler in front of it) could not be reached or refused the + * connection, not that the request or our code was wrong: Postgres "too many connections" and + * shutdown classes, connection-exception class 08, and what the driver and the socket report. + */ +const DATABASE_UNAVAILABLE_CODES = new Set([ + '53300', // too_many_connections + '57P01', // admin_shutdown + '57P02', // crash_shutdown + '57P03', // cannot_connect_now + '08000', + '08001', + '08003', + '08004', + '08006', + '08007', + 'CONNECTION_CLOSED', + 'CONNECTION_DESTROYED', + 'CONNECTION_ENDED', + 'CONNECT_TIMEOUT', + 'ECONNREFUSED', + 'ECONNRESET', + 'EPIPE', + 'ETIMEDOUT', + 'ENOTFOUND', + 'EAI_AGAIN', +]); + /** Normalizes any thrown value into an AppError. */ export function toAppError(value: unknown): AppError { if (isAppError(value)) return value; + // A database that cannot be reached is the platform's problem, not a bug in this request: say so + // (503, try again) so a client does not mistake it for a failure of its own and the next + // reader of the logs sees an outage rather than a crash. + const code = pgErrorCode(value); + if (code !== undefined && DATABASE_UNAVAILABLE_CODES.has(code)) { + return new AppError('UPSTREAM_UNAVAILABLE', 'The service is temporarily unavailable. Please try again shortly.', { cause: value }); + } const message = value instanceof Error ? value.message : String(value); return new AppError('INTERNAL_ERROR', message, { cause: value, exposeMessage: false }); } diff --git a/packages/utils/src/ids.ts b/packages/utils/src/ids.ts index 932e24f..0f5d057 100644 --- a/packages/utils/src/ids.ts +++ b/packages/utils/src/ids.ts @@ -1,4 +1,5 @@ import { createHash, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto'; +import { AppError } from './errors.js'; export function newUuid(): string { return randomUUID(); @@ -39,3 +40,63 @@ export function decodeCursor(cursor: string): Record | return null; } } + +// What Postgres emits for timestamptz in drizzle's string mode, e.g. 2026-10-27 12:34:56.123456+00. +const PG_TIMESTAMP = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:\.\d{1,6})?(?:Z|[+-](\d{2})(?::?(\d{2}))?)$/; +const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; +const MAX_CURSOR_SCORE = 1_000_000_000; + +/** True for a timestamp Postgres will accept (a real calendar date and clock time, a plausible year and offset). */ +function isPostgresTimestamp(text: string): boolean { + const match = PG_TIMESTAMP.exec(text); + if (match === null) return false; + const [year, month, day, hour, minute, second] = match.slice(1, 7).map(Number) as [number, number, number, number, number, number]; + const date = new Date(Date.UTC(year, month - 1, day)); + const realDate = + year >= 1000 && date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day; + const offsetHours = match[7] === undefined ? 0 : Number(match[7]); + const offsetMinutes = match[8] === undefined ? 0 : Number(match[8]); + return realDate && hour <= 23 && minute <= 59 && second <= 59 && offsetHours <= 15 && offsetMinutes <= 59; +} + +function invalidCursor(): AppError { + return new AppError('VALIDATION_ERROR', 'Invalid cursor', { + details: [{ path: 'cursor', message: 'Not a cursor this API issued' }], + }); +} + +/** + * Reads a `{ createdAt, id }` page cursor, as `encodeCursor` writes it for lists ordered by creation time. + * A cursor is opaque, but a client can send any string: one that is not exactly what this API + * issues used to reach the database as a timestamp or a uuid and come back as a 500, or was + * silently ignored. Anything else than `undefined` (no cursor, the first page) that does not check + * out is a 400. + */ +export function parseTimeCursor(cursor: string | undefined): { createdAt: string; id: string } | null { + if (cursor === undefined) return null; + const decoded = decodeCursor(cursor); + const createdAt = decoded?.createdAt; + const id = decoded?.id; + if (typeof createdAt !== 'string' || typeof id !== 'string' || !isPostgresTimestamp(createdAt) || !UUID.test(id)) { + throw invalidCursor(); + } + return { createdAt, id }; +} + +/** Reads a `{ score, id }` page cursor, for lists ordered by a score. Same rules as {@link parseTimeCursor}. */ +export function parseScoreCursor(cursor: string | undefined): { score: number; id: string } | null { + if (cursor === undefined) return null; + const decoded = decodeCursor(cursor); + const score = decoded?.score; + const id = decoded?.id; + if ( + typeof score !== 'number' || + !Number.isFinite(score) || + Math.abs(score) > MAX_CURSOR_SCORE || + typeof id !== 'string' || + !UUID.test(id) + ) { + throw invalidCursor(); + } + return { score, id }; +} diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index d249be5..ffb2710 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,4 +1,4 @@ -import { pino, type Logger } from 'pino'; +import { pino, type DestinationStream, type Logger } from 'pino'; import { REDACTED } from './redact.js'; export type { Logger }; @@ -7,14 +7,17 @@ export interface LoggerOptions { service: string; level?: string; pretty?: boolean; + /** Where lines go; stdout when omitted. For tests that read what was logged. */ + destination?: DestinationStream; } /** * Structured JSON logs with trace propagation (docs/10 § Observability). * Redaction is configured here so no service can log a secret by accident. */ -export function createLogger({ service, level = 'info', pretty = false }: LoggerOptions): Logger { - return pino({ +export function createLogger({ service, level = 'info', pretty = false, destination }: LoggerOptions): Logger { + return pino( + { level, base: { service }, redact: { @@ -32,6 +35,25 @@ export function createLogger({ service, level = 'info', pretty = false }: Logger '*.password', '*.access_token', '*.refresh_token', + // The same secrets one level down, in request-shaped objects and in a bare `headers`. + 'authorization', + 'cookie', + 'headers.authorization', + 'headers.cookie', + 'headers["x-api-key"]', + '*.authorization', + '*.cookie', + '*.headers.authorization', + '*.headers.cookie', + '*.headers["x-api-key"]', + '*.token', + '*.secret', + '*.api_key', + '*.client_secret', + '*.private_key', + // A resume's text is personal data and can be 200,000 characters of it. + 'parsed_text', + '*.parsed_text', ], censor: REDACTED, }, @@ -47,7 +69,9 @@ export function createLogger({ service, level = 'info', pretty = false }: Logger }, } : {}), - }); + }, + destination, + ); } /** A logger that discards everything. Used by tests and by dry-run workers. */ diff --git a/packages/utils/src/redact.ts b/packages/utils/src/redact.ts index 412dbcf..81877f6 100644 --- a/packages/utils/src/redact.ts +++ b/packages/utils/src/redact.ts @@ -1,6 +1,7 @@ /** - * Log redaction (docs/09 § Data protection). Applied by the shared logger so a - * service cannot accidentally opt out. + * Log redaction helpers (docs/09 § Data protection). The shared logger redacts by path (see + * `createLogger`), so a service cannot opt out of that; the functions below are for values that + * are built into a message or a response by hand and are not wired into the logger. */ /** Field names whose values are replaced wholesale wherever they appear. */ diff --git a/packages/utils/src/vercel.ts b/packages/utils/src/vercel.ts index 19ce71c..ee32f7f 100644 --- a/packages/utils/src/vercel.ts +++ b/packages/utils/src/vercel.ts @@ -51,6 +51,18 @@ export const SERVERLESS_PLACEHOLDER_PORT = '3000'; */ export const SERVERLESS_DEFAULT_MESSAGING_DRIVER = 'postgres'; +/** + * The event driver to run with on Vercel: the configured one, except that "none" (unset or empty) + * and "memory" both mean the durable outbox. `memory` is what `.env.example` shows for local work, + * so it is easily pasted into the project's settings, and there it would drop every cross-service + * event without a sound: each function is its own process and the in-memory broker only delivers + * inside one. It has no valid use on serverless, so it is not honoured there. + */ +function serverlessMessagingDriver(configured: string | undefined): string { + const driver = configured?.trim() ?? ''; + return driver === '' || driver.toLowerCase() === 'memory' ? SERVERLESS_DEFAULT_MESSAGING_DRIVER : driver; +} + /** * Env source for a service's `loadServiceEnv()`. Outside Vercel it is * `source` untouched, so local dev and tests keep strict validation; on Vercel @@ -65,6 +77,6 @@ export function withServerlessEnvDefaults( return { ...source, PORT: source.PORT ?? SERVERLESS_PLACEHOLDER_PORT, - MESSAGING_DRIVER: source.MESSAGING_DRIVER ?? SERVERLESS_DEFAULT_MESSAGING_DRIVER, + MESSAGING_DRIVER: serverlessMessagingDriver(source.MESSAGING_DRIVER), }; } diff --git a/packages/utils/test/cursors.test.ts b/packages/utils/test/cursors.test.ts new file mode 100644 index 0000000..135ee3f --- /dev/null +++ b/packages/utils/test/cursors.test.ts @@ -0,0 +1,85 @@ +import { describe, expect, it } from 'vitest'; +import { AppError, encodeCursor, parseScoreCursor, parseTimeCursor } from '../src/index.js'; + +const ID = '3f2b8c1e-5d4a-4e6f-9a7b-1c2d3e4f5a6b'; +const forged = (value: unknown): string => Buffer.from(JSON.stringify(value), 'utf8').toString('base64url'); + +function rejects(run: () => unknown): void { + try { + run(); + } catch (error) { + expect(error).toBeInstanceOf(AppError); + expect(error).toMatchObject({ code: 'VALIDATION_ERROR', statusCode: 400, message: 'Invalid cursor' }); + return; + } + throw new Error('expected the cursor to be refused'); +} + +describe('parseTimeCursor', () => { + it('means "first page" when there is no cursor', () => { + expect(parseTimeCursor(undefined)).toBeNull(); + }); + + it.each([ + '2026-10-27 12:34:56.123456+00', // what Postgres writes in drizzle's string mode + '2026-10-27 12:34:56+00', + '2026-10-27T12:34:56.123Z', + '2026-10-27T12:34:56+05:30', + '2026-10-27 12:34:56.5-0700', + '2024-02-29T00:00:00Z', // a real leap day + ])('accepts what the API itself issues: %s', (createdAt) => { + expect(parseTimeCursor(encodeCursor({ createdAt, id: ID }))).toEqual({ createdAt, id: ID }); + }); + + it.each([ + ['not a timestamp', { createdAt: 'not-a-date', id: ID }], + ['a date that does not exist (Postgres refuses it)', { createdAt: '2026-02-31T00:00:00Z', id: ID }], + ['a leap day in a common year', { createdAt: '2025-02-29T00:00:00Z', id: ID }], + ['month 13', { createdAt: '2026-13-01T00:00:00Z', id: ID }], + ['hour 24', { createdAt: '2026-10-27T24:00:00Z', id: ID }], + ['an offset of 99 hours', { createdAt: '2026-10-27T00:00:00+99:00', id: ID }], + ['five-digit years', { createdAt: '99999-99-99T99:99:99Z', id: ID }], + ['SQL in the timestamp', { createdAt: "2026-10-27'; drop table users;--", id: ID }], + ['a timestamp with no zone', { createdAt: '2026-10-27T12:34:56', id: ID }], + ['an id that is not a uuid', { createdAt: '2026-10-27T12:34:56Z', id: "1' or '1'='1" }], + ['numbers for text', { createdAt: 1_790_000_000, id: 42 }], + ['a missing id', { createdAt: '2026-10-27T12:34:56Z' }], + ['a missing timestamp', { id: ID }], + ['objects for text', { createdAt: { $gt: '' }, id: [ID] }], + ['an empty object', {}], + ])('refuses %s', (_label, payload) => { + rejects(() => parseTimeCursor(forged(payload))); + }); + + it.each([['not base64 json'], ['%%%'], ['e30'], [forged([1, 2, 3])], [forged('text')], [forged(null)], [''], [' ']])( + 'refuses something that does not decode to a cursor: %j', + (cursor) => { + rejects(() => parseTimeCursor(cursor)); + }, + ); +}); + +describe('parseScoreCursor', () => { + it('means "first page" when there is no cursor', () => { + expect(parseScoreCursor(undefined)).toBeNull(); + }); + + it.each([0, 0.5, 87, 100, -3.25])('accepts a score the API issues: %d', (score) => { + expect(parseScoreCursor(encodeCursor({ score, id: ID }))).toEqual({ score, id: ID }); + }); + + it('refuses an infinite score: the text 1e999 parses to Infinity, which JSON.stringify cannot round-trip', () => { + const raw = Buffer.from(`{"score":1e999,"id":"${ID}"}`, 'utf8').toString('base64url'); + rejects(() => parseScoreCursor(raw)); + }); + + it.each([ + ['text for the score', { score: '87', id: ID }], + ['a huge score', { score: 1e12, id: ID }], + ['a missing score', { id: ID }], + ['an id that is not a uuid', { score: 1, id: 'x' }], + ['a missing id', { score: 1 }], + ])('refuses %s', (_label, payload) => { + rejects(() => parseScoreCursor(forged(payload))); + }); +}); diff --git a/packages/utils/test/env-example.test.ts b/packages/utils/test/env-example.test.ts new file mode 100644 index 0000000..6ba3556 --- /dev/null +++ b/packages/utils/test/env-example.test.ts @@ -0,0 +1,32 @@ +import { readFileSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const ROOT = fileURLToPath(new URL('../../../', import.meta.url)); + +/** Every variable a service reads (the keys of every exported zod object in its `env.ts`). */ +async function schemaKeys(): Promise> { + const keys = new Set(); + for (const service of readdirSync(join(ROOT, 'services'), { withFileTypes: true })) { + if (!service.isDirectory()) continue; + const mod = (await import(join(ROOT, 'services', service.name, 'src/env.ts'))) as Record; + for (const value of Object.values(mod)) { + const shape = (value as { shape?: Record } | null)?.shape; + if (shape !== undefined && typeof shape === 'object') for (const key of Object.keys(shape)) keys.add(key); + } + } + return keys; +} + +describe('.env.example', () => { + // Written per service as AUTH_SERVICE_PORT, JOBS_SERVICE_PORT, ... in the "Service ports" section. + const DOCUMENTED_ELSEWHERE = new Set(['PORT']); + + it('documents every variable a service reads, so an operator can find out what exists and what it does', async () => { + const example = readFileSync(join(ROOT, '.env.example'), 'utf8'); + const documented = new Set([...example.matchAll(/^#?\s*([A-Z][A-Z0-9_]+)=/gm)].map((match) => match[1] as string)); + const missing = [...(await schemaKeys())].filter((key) => !documented.has(key) && !DOCUMENTED_ELSEWHERE.has(key)); + expect(missing.sort()).toEqual([]); + }); +}); diff --git a/packages/utils/test/logger.test.ts b/packages/utils/test/logger.test.ts new file mode 100644 index 0000000..fbdf660 --- /dev/null +++ b/packages/utils/test/logger.test.ts @@ -0,0 +1,54 @@ +import { Writable } from 'node:stream'; +import { describe, expect, it } from 'vitest'; +import { createLogger } from '../src/index.js'; + +function capture() { + const lines: string[] = []; + const destination = new Writable({ + write(chunk, _encoding, done) { + lines.push(String(chunk)); + done(); + }, + }); + const logger = createLogger({ service: 'test-service', level: 'info', destination }); + return { logger, output: () => lines.join('') }; +} + +const SECRET = 'SECRET-VALUE-MUST-NOT-APPEAR'; + +describe('createLogger redaction', () => { + it.each([ + ['a top-level password', { password: SECRET }], + ['a top-level token', { token: SECRET }], + ['the authorization header of a request', { req: { headers: { authorization: `Bearer ${SECRET}` } } }], + ['the cookie header of a request', { req: { headers: { cookie: `sb=${SECRET}` } } }], + ['a bare headers object', { headers: { authorization: `Bearer ${SECRET}`, cookie: `sb=${SECRET}`, 'x-api-key': SECRET } }], + ['headers one level down', { request: { headers: { authorization: `Bearer ${SECRET}`, 'x-api-key': SECRET } } }], + ['a nested secret and api key', { config: { secret: SECRET, api_key: SECRET, client_secret: SECRET, private_key: SECRET } }], + ['a nested token', { session: { token: SECRET, access_token: SECRET, refresh_token: SECRET } }], + ['a response cookie', { res: { headers: { 'set-cookie': [`sb=${SECRET}`] } } }], + ['a resume text', { parsed_text: SECRET }], + ['a resume text one level down', { resume: { parsed_text: SECRET } }], + ])('keeps %s out of the log', (_label, fields) => { + const { logger, output } = capture(); + logger.info(fields, 'something happened'); + expect(output()).toContain('something happened'); + expect(output()).not.toContain(SECRET); + expect(output()).toContain('[redacted]'); + }); + + it('still logs ordinary fields', () => { + const { logger, output } = capture(); + logger.info({ user_id: 'u-1', route: '/v1/resumes', status: 200 }, 'request completed'); + const entry = JSON.parse(output()) as Record; + expect(entry).toMatchObject({ service: 'test-service', user_id: 'u-1', route: '/v1/resumes', status: 200, level: 'info' }); + }); + + it('escapes line breaks and control characters in user-controlled text, so one request cannot forge a log line', () => { + const { logger, output } = capture(); + logger.info({ note: 'first\n{"level":"error","msg":"forged line"}\r\u001b[31m' }, 'user supplied a note'); + const written = output(); + expect(written.trimEnd().split('\n')).toHaveLength(1); + expect(written).not.toContain('\u001b'); + }); +}); diff --git a/packages/utils/test/utils.test.ts b/packages/utils/test/utils.test.ts index 80b3a39..88b5b23 100644 --- a/packages/utils/test/utils.test.ts +++ b/packages/utils/test/utils.test.ts @@ -4,6 +4,34 @@ import { decodeCursor, encodeCursor, secureEquals, sha256Hex } from '../src/ids. import { maskEmail, maskToken, redact, REDACTED } from '../src/redact.js'; import { backoffDelayMs, withRetry } from '../src/retry.js'; +describe('toAppError and an unreachable database', () => { + const wrapped = (code: string) => Object.assign(new Error('driver failure with the connection string postgres://user:pw@host/db'), { cause: { code } }); + + it.each([ + ['too many connections', '53300'], + ['the server shutting down', '57P01'], + ['the server not accepting connections yet', '57P03'], + ['a connection exception', '08006'], + ['a refused connection', 'ECONNREFUSED'], + ['a connection that was closed', 'CONNECTION_CLOSED'], + ['a connection that timed out', 'CONNECT_TIMEOUT'], + ['a reset connection', 'ECONNRESET'], + ['a name that does not resolve', 'ENOTFOUND'], + ])('answers 503 for %s, without the driver text', (_label, code) => { + const error = toAppError(wrapped(code)); + expect(error).toMatchObject({ code: 'UPSTREAM_UNAVAILABLE', statusCode: 503 }); + expect(JSON.stringify(error.toResponse('req-1'))).not.toContain('postgres://'); + expect(error.toResponse('req-1').error.message).toBe('The service is temporarily unavailable. Please try again shortly.'); + }); + + it.each([['23505'], ['22P02'], ['42P01'], ['23503'], ['40001']])( + 'still answers 500 for the database error %s: that one is a bug or a conflict, not an outage', + (code) => { + expect(toAppError(wrapped(code))).toMatchObject({ code: 'INTERNAL_ERROR', statusCode: 500 }); + }, + ); +}); + describe('AppError', () => { it('maps codes to status codes and serializes the documented error envelope', () => { const error = new AppError('JOB_NOT_FOUND', 'Job is unavailable'); diff --git a/packages/utils/test/vercel-routing.test.ts b/packages/utils/test/vercel-routing.test.ts new file mode 100644 index 0000000..481cb0f --- /dev/null +++ b/packages/utils/test/vercel-routing.test.ts @@ -0,0 +1,99 @@ +import { existsSync, readFileSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const ROOT = fileURLToPath(new URL('../../../', import.meta.url)); + +interface Rewrite { + source: string; + destination: string; +} +const config = JSON.parse(readFileSync(join(ROOT, 'vercel.json'), 'utf8')) as { + functions: Record; + rewrites: Rewrite[]; +}; + +/** What Vercel does with these: `/v1/jobs/:path*` matches `/v1/jobs` and everything below it, first match wins. */ +function matches(source: string, path: string): boolean { + const prefix = source.replace(/\/:path\*$/, ''); + return path === prefix || path.startsWith(`${prefix}/`); +} +function destinationOf(path: string): string | undefined { + return config.rewrites.find((rewrite) => matches(rewrite.source, path))?.destination; +} + +/** Services that are not deployed (no bundle, no rewrite): the connectors service is built and tested only. */ +const NOT_DEPLOYED = new Set(['connectors']); + +const services = readdirSync(join(ROOT, 'services'), { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .filter((name) => !NOT_DEPLOYED.has(name)); + +function sourceFiles(dir: string): string[] { + return readdirSync(dir, { withFileTypes: true }).flatMap((entry) => + entry.isDirectory() + ? sourceFiles(join(dir, entry.name)) + : entry.name.endsWith('.ts') + ? [join(dir, entry.name)] + : [], + ); +} + +/** Every quoted `/v1/...` or `/internal/...` path literal a service's code declares or mentions. */ +function pathsOf(service: string): string[] { + const found = new Set(); + for (const file of sourceFiles(join(ROOT, 'services', service, 'src'))) { + for (const match of readFileSync(file, 'utf8').matchAll(/['"`](\/(?:v1|internal)\/[^'"`\s]*)['"`]/g)) { + const path = match[1] as string; + // Outgoing request templates, doc placeholders and rewrite patterns, not routes. + if (path.includes('${') || path.includes('...') || path.includes(':path*')) continue; + found.add(path); + } + } + return [...found].sort(); +} + +describe('vercel.json routes every public path to the function that serves it', () => { + it('has a function entry and a committed bundle for every rewrite destination, and the reverse', () => { + const destinations = new Set(config.rewrites.map((rewrite) => rewrite.destination)); + const functionNames = Object.keys(config.functions).map((key) => key.replace(/^api\/(.+)\/index\.js$/, '/api/$1')); + expect([...destinations].sort()).toEqual([...functionNames].sort()); + for (const destination of destinations) { + expect(existsSync(join(ROOT, `${destination.slice(1)}/index.js`)), destination).toBe(true); + } + }); + + it('never rewrites to a service that is not deployed', () => { + for (const service of NOT_DEPLOYED) { + expect(config.rewrites.some((rewrite) => rewrite.destination === `/api/${service}`)).toBe(false); + } + }); + + it.each(services)('%s: every public route resolves to its own function', (service) => { + const own = pathsOf(service).filter( + // `/internal/drain` is the service-local path; only `/internal//...` is public. + (path) => path.startsWith('/v1/') && path !== '/v1/' || path.startsWith(`/internal/${service}/`), + ); + const wrong = own + .map((path) => ({ path, destination: destinationOf(path) })) + .filter(({ destination }) => destination !== `/api/${service}`); + expect(wrong).toEqual([]); + }); + + it('finds routes to check in every deployed service (so the extraction cannot quietly go blind)', () => { + for (const service of services) { + const routes = pathsOf(service).filter( + (path) => (path.startsWith('/v1/') && path !== '/v1/') || path.startsWith(`/internal/${service}/`), + ); + expect(routes.length, service).toBeGreaterThan(0); + } + }); + + it('leaves the service-local drain paths unrouted, so only the scheduler-facing path is public', () => { + expect(destinationOf('/internal/drain')).toBeUndefined(); + expect(destinationOf('/health')).toBeUndefined(); + expect(destinationOf('/metrics')).toBeUndefined(); + }); +}); diff --git a/packages/utils/test/vercel.test.ts b/packages/utils/test/vercel.test.ts index 9e7118b..8562604 100644 --- a/packages/utils/test/vercel.test.ts +++ b/packages/utils/test/vercel.test.ts @@ -111,6 +111,19 @@ describe('withServerlessEnvDefaults', () => { expect(withServerlessEnvDefaults({ VERCEL: '1', MESSAGING_DRIVER: 'rabbitmq' }).MESSAGING_DRIVER).toBe('rabbitmq'); }); + // `.env.example` says MESSAGING_DRIVER=memory for local work; pasted into the project's settings it + // would drop every cross-service event on Vercel, each function being its own process. + it.each([['memory'], ['MEMORY'], [' memory '], [''], [' ']])( + 'does not honour MESSAGING_DRIVER=%j on Vercel: the in-memory broker cannot cross functions', + (configured) => { + expect(withServerlessEnvDefaults({ VERCEL: '1', MESSAGING_DRIVER: configured }).MESSAGING_DRIVER).toBe('postgres'); + }, + ); + + it('still honours the memory driver outside Vercel, for local work and tests', () => { + expect(withServerlessEnvDefaults({ MESSAGING_DRIVER: 'memory' }).MESSAGING_DRIVER).toBe('memory'); + }); + it('does not default MESSAGING_DRIVER outside Vercel, so local dev and tests keep the memory broker', () => { expect(withServerlessEnvDefaults({}).MESSAGING_DRIVER).toBeUndefined(); }); diff --git a/services/admin/src/repo/roster.ts b/services/admin/src/repo/roster.ts index 96869c3..3ea5871 100644 --- a/services/admin/src/repo/roster.ts +++ b/services/admin/src/repo/roster.ts @@ -16,14 +16,12 @@ import { import { schema, type Database } from '@atlas/db'; import { emptyApplicationStatusCounts, - uuidSchema, type ApplicationStatus, type RosterFilter, type RosterStudent, type StudentInsights, } from '@atlas/types'; -import { AppError, decodeCursor, encodeCursor } from '@atlas/utils'; -import { z } from 'zod'; +import { AppError, encodeCursor, parseTimeCursor } from '@atlas/utils'; import { toIsoTimestamp } from '../lib/timestamps.js'; const { students, users, organizationMembers, resumes, applications } = schema; @@ -33,14 +31,10 @@ export function escapeLike(term: string): string { return term.replace(/[\\%_]/g, (char) => `\\${char}`); } -// What Postgres emits for timestamptz in drizzle's string mode, e.g. 2026-10-27 12:34:56.123456+00. -const PG_TIMESTAMP = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}(\.\d{1,6})?(Z|[+-]\d{2}(:?\d{2})?)$/; -const cursorSchema = z.object({ createdAt: z.string().regex(PG_TIMESTAMP), id: uuidSchema }); - export function decodeRosterCursor(cursor: string): { createdAt: string; id: string } { - const parsed = cursorSchema.safeParse(decodeCursor(cursor)); - if (!parsed.success) throw new AppError('VALIDATION_ERROR', 'Invalid cursor'); - return parsed.data; + const parsed = parseTimeCursor(cursor); + if (parsed === null) throw new AppError('VALIDATION_ERROR', 'Invalid cursor'); + return parsed; } interface RosterRow { diff --git a/services/admin/test/csv-hostile.test.ts b/services/admin/test/csv-hostile.test.ts new file mode 100644 index 0000000..9a829cd --- /dev/null +++ b/services/admin/test/csv-hostile.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import { AppError } from '@atlas/utils'; +import { csvToRawRows } from '../src/lib/import-rows.js'; + +/** + * A roster file is typed by staff but can be anything. Parsing must stay linear in its size (a + * quadratic pattern would let one 4 MB upload keep a function busy past its time limit) and must + * fail with a clean 4xx, never throw something else. Each shape runs at two sizes and the growth is + * checked rather than running the full size, so a regression fails fast instead of hanging. + */ +const SMALL = 100_000; +const LARGE = 400_000; +const HEADER = 'email,full_name\n'; +const fill = (unit: string) => (size: number) => unit.repeat(Math.ceil(size / unit.length)).slice(0, size); + +const SHAPES: ReadonlyArray string]> = [ + ['only commas', (size) => HEADER + fill(',')(size)], + ['only newlines', (size) => HEADER + fill('\n')(size)], + ['only carriage returns', (size) => HEADER + fill('\r')(size)], + ['CRLF blank lines', (size) => HEADER + fill('\r\n')(size)], + ['an open quote that never closes', (size) => `${HEADER}"${'a'.repeat(size)}`], + ['quotes inside an unquoted field', (size) => HEADER + fill('a"b,')(size)], + ['doubled quotes inside a quoted field', (size) => `${HEADER}"${fill('""')(size)}"`], + ['alternating quotes and commas', (size) => HEADER + fill('","')(size)], + ['one enormous cell', (size) => `${HEADER}a@b.co,${'x'.repeat(size)}`], + ['many tiny rows', (size) => HEADER + fill('a@b.co,N\n')(size)], + ['many columns in one row', (size) => `${HEADER}${fill('a,')(size)}`], + ['spaces and tabs', (size) => HEADER + fill(' \t')(size)], + ['a BOM repeated', (size) => HEADER + fill('')(size)], + ['NUL bytes', (size) => `${HEADER}a@b.co,${fill('\u0000')(size)}`], + ['formula prefixes', (size) => HEADER + fill('=cmd|\' /C calc\'!A0,+1\n')(size)], +]; + +function runtime(text: string): number { + const start = performance.now(); + try { + csvToRawRows(text); + } catch (error) { + // Rejecting a file is fine; throwing anything but a clean API error is not. + expect(error).toBeInstanceOf(AppError); + expect([400, 413]).toContain((error as AppError).statusCode); + } + return performance.now() - start; +} + +describe('roster CSV parsing on hostile input', () => { + it.each(SHAPES)('stays linear: %s', (_label, shape) => { + const small = Math.min(runtime(shape(SMALL)), runtime(shape(SMALL))); + const large = Math.min(runtime(shape(LARGE)), runtime(shape(LARGE))); + if (large <= 80) return; + expect(large / Math.max(small, 1), `${small.toFixed(1)} ms at ${SMALL}, ${large.toFixed(1)} ms at ${LARGE}`).toBeLessThan(9); + }); +}); diff --git a/services/analytics/src/env.ts b/services/analytics/src/env.ts index 80f6dcb..a64d7df 100644 --- a/services/analytics/src/env.ts +++ b/services/analytics/src/env.ts @@ -1,4 +1,12 @@ -import { baseEnvSchema, databaseEnvSchema, httpEnvSchema, loadEnv, messagingEnvSchema, supabaseAuthEnvSchema } from '@atlas/config'; +import { + baseEnvSchema, + cronSecretSchema, + databaseEnvSchema, + httpEnvSchema, + loadEnv, + messagingEnvSchema, + supabaseAuthEnvSchema, +} from '@atlas/config'; import { z } from 'zod'; export const analyticsServiceEnvSchema = z.object({ @@ -12,7 +20,7 @@ export const analyticsServiceEnvSchema = z.object({ * `Authorization: Bearer $CRON_SECRET` when this variable is set. Unset, the * route answers 503 and never runs a drain. */ - CRON_SECRET: z.string().min(16, 'CRON_SECRET must be at least 16 characters').optional(), + CRON_SECRET: cronSecretSchema.optional(), }); export type AnalyticsServiceEnv = z.infer; diff --git a/services/analytics/test/entrypoint.test.ts b/services/analytics/test/entrypoint.test.ts index b1543f9..be38242 100644 --- a/services/analytics/test/entrypoint.test.ts +++ b/services/analytics/test/entrypoint.test.ts @@ -142,13 +142,14 @@ describe('analytics-service Vercel entrypoint', () => { expect(anonymous.statusCode).toBe(401); // An authorized call reaches the postgres broker, which then finds no database to drain: a - // plain 500 (so Vercel Cron records a failure) rather than a hang or a silent 200. + // 503 (an unreachable database; either way a failure for Vercel Cron to record) rather than a + // hang or a silent 200. const failed = await app.inject({ method: 'POST', url: '/internal/drain', headers: { authorization: `Bearer ${secret}` }, }); - expect(failed.statusCode).toBe(500); + expect(failed.statusCode).toBe(503); }); it('keeps /internal/drain disabled on Vercel until CRON_SECRET is configured', async () => { diff --git a/services/applications/src/http/routes/append-event.ts b/services/applications/src/http/routes/append-event.ts index a79d943..2bec1fc 100644 --- a/services/applications/src/http/routes/append-event.ts +++ b/services/applications/src/http/routes/append-event.ts @@ -42,6 +42,11 @@ export function appendEventRoute(app: FastifyInstance, deps: AppDeps): void { toStatus: body.to_status, note: body.note ?? null, }); + if (updated === null) { + // Moved by another request between our read and our write (a double click, or the user and + // staff acting together). The move was validated against a status it no longer has. + throw new AppError('CONFLICT', 'This application was just changed by another request. Reload it and try again.'); + } if (body.to_status === 'submitted') { await deps.broker.publish( diff --git a/services/applications/src/http/routes/create-application.ts b/services/applications/src/http/routes/create-application.ts index ba1875e..13fd241 100644 --- a/services/applications/src/http/routes/create-application.ts +++ b/services/applications/src/http/routes/create-application.ts @@ -35,6 +35,14 @@ const idempotencyKeySchema = z.string().min(8).max(200); const AUTO_MODE_UNAVAILABLE_MESSAGE = 'Mode "auto" cannot be used: automatic submission is not available yet. Use "manual" or "review" instead.'; +/** True when `existing` was created by a request with this job, resume and mode. */ +function isSameRequest( + existing: ApplicationRow, + body: { job_id: string; resume_id: string; mode: string }, +): boolean { + return existing.jobId === body.job_id && existing.resumeId === body.resume_id && existing.mode === body.mode; +} + export function createApplicationRoute(app: FastifyInstance, deps: AppDeps): void { /** The owner's view of `row`, with the job it points at (null if the job or its company is gone). */ async function ownerView(row: ApplicationRow, knownJob?: ApplicationJobSummary | null): Promise { @@ -64,9 +72,7 @@ export function createApplicationRoute(app: FastifyInstance, deps: AppDeps): voi const existingByKey = await findByUserAndIdempotencyKey(deps.db, actor.user_id, idempotencyKey); if (existingByKey) { - const sameRequest = - existingByKey.jobId === body.job_id && existingByKey.resumeId === body.resume_id && existingByKey.mode === body.mode; - if (!sameRequest) { + if (!isSameRequest(existingByKey, body)) { throw new AppError('IDEMPOTENCY_KEY_REUSED', 'This idempotency key was already used for a different request'); } reply.status(200).send(await ownerView(existingByKey)); @@ -85,6 +91,12 @@ export function createApplicationRoute(app: FastifyInstance, deps: AppDeps): voi const existingForJob = await findByUserAndJob(deps.db, actor.user_id, body.job_id); if (existingForJob) { + // The same request sent twice at once: the first one's row was not visible to the key lookup + // above but is by now. That is a replay (200), not a second application (409). + if (existingForJob.idempotencyKey === idempotencyKey && isSameRequest(existingForJob, body)) { + reply.status(200).send(await ownerView(existingForJob)); + return; + } throw new AppError('CONFLICT', 'You already have an application for this job', { details: { existing_application_id: existingForJob.applicationId }, }); @@ -123,6 +135,10 @@ export function createApplicationRoute(app: FastifyInstance, deps: AppDeps): voi return; } const racedByJob = await findByUserAndJob(deps.db, actor.user_id, body.job_id); + if (racedByJob && racedByJob.idempotencyKey === idempotencyKey && isSameRequest(racedByJob, body)) { + reply.status(200).send(await ownerView(racedByJob)); + return; + } if (racedByJob) { throw new AppError('CONFLICT', 'You already have an application for this job', { details: { existing_application_id: racedByJob.applicationId }, diff --git a/services/applications/src/repo/applications.ts b/services/applications/src/repo/applications.ts index 8180444..d59a379 100644 --- a/services/applications/src/repo/applications.ts +++ b/services/applications/src/repo/applications.ts @@ -8,7 +8,7 @@ import type { ApplicationWithJob, PaginationQuery, } from '@atlas/types'; -import { decodeCursor, encodeCursor } from '@atlas/utils'; +import { encodeCursor, parseTimeCursor } from '@atlas/utils'; import { jobSummaryColumns, toJobSummary } from './lookups.js'; export type ApplicationRow = typeof schema.applications.$inferSelect; @@ -116,9 +116,9 @@ export interface ListForOrganizationResult { } function pageCondition(scopeCondition: SQL, pagination: PaginationQuery): SQL | undefined { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === 'string' ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === 'string' ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = [scopeCondition]; if (cursorCreatedAt && cursorId) { @@ -217,8 +217,17 @@ export interface AppendEventInput { note: string | null; } -/** Folds the new status onto `applications` and appends the trail row in one transaction. */ -export async function appendEvent(db: Database, input: AppendEventInput): Promise { +/** + * Folds the new status onto `applications` and appends the trail row in one transaction. + * + * The update only applies while the application is still in `fromStatus`, the status the caller + * validated the move against. Without that, two requests that both read "interviewing" would both + * pass validation and both write, so an application could go "rejected" and then "offer", the + * trail would show two moves out of the same status, and a duplicate "submitted" would publish + * twice. Returns `null` when the application is no longer in `fromStatus`: someone else moved it + * first, and nothing was written. + */ +export async function appendEvent(db: Database, input: AppendEventInput): Promise { return db.transaction(async (tx) => { const now = new Date().toISOString(); const [updated] = await tx @@ -228,9 +237,14 @@ export async function appendEvent(db: Database, input: AppendEventInput): Promis lastEventAt: now, submittedAt: input.toStatus === 'submitted' ? now : undefined, }) - .where(eq(schema.applications.applicationId, input.applicationId)) + .where( + and( + eq(schema.applications.applicationId, input.applicationId), + eq(schema.applications.status, input.fromStatus), + ), + ) .returning(); - if (!updated) throw new Error('appendEvent: application disappeared mid-transaction'); + if (!updated) return null; await tx.insert(schema.applicationEvents).values({ applicationId: input.applicationId, diff --git a/services/applications/test/applications-flow.test.ts b/services/applications/test/applications-flow.test.ts index d94df0b..375dff4 100644 --- a/services/applications/test/applications-flow.test.ts +++ b/services/applications/test/applications-flow.test.ts @@ -160,6 +160,27 @@ describe.skipIf(!testDatabaseUrl)('applications-service HTTP flow', () => { await dbHandle.close(); }); + // A cursor is opaque to clients, but a client can still send any string. Valid JSON that is not + // a cursor this service issued used to reach the database as a timestamp or a uuid and come back + // as a 500. + it.each([ + ['a timestamp that is not a timestamp', { createdAt: 'not-a-date', id: randomUUID() }], + ['an id that is not a uuid', { createdAt: new Date().toISOString(), id: "1' or '1'='1" }], + ['numbers where text is expected', { createdAt: 12345, id: 67890 }], + ['a missing id', { createdAt: new Date().toISOString() }], + ['a nested object', { createdAt: { $gt: '' }, id: [] }], + ['an absurd timestamp', { createdAt: '99999-99-99T99:99:99Z', id: randomUUID() }], + ])('answers 400, not 500, for a forged cursor: %s', async (_label, payload) => { + const cursor = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url'); + const res = await app.inject({ + method: 'GET', + url: `/v1/applications?cursor=${cursor}`, + headers: { authorization: `Bearer ${token}` }, + }); + expect(res.statusCode).toBe(400); + expect(res.json().error.code).toBe('VALIDATION_ERROR'); + }); + it('requires an Idempotency-Key header', async () => { const res = await app.inject({ method: 'POST', diff --git a/services/applications/test/applications-races.test.ts b/services/applications/test/applications-races.test.ts new file mode 100644 index 0000000..3d36361 --- /dev/null +++ b/services/applications/test/applications-races.test.ts @@ -0,0 +1,227 @@ +import { randomUUID } from 'node:crypto'; +import { asc, eq, inArray } from 'drizzle-orm'; +import { exportJWK, generateKeyPair, SignJWT } from 'jose'; +import type { FastifyInstance } from 'fastify'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { createTokenVerifierConfig } from '@atlas/auth-kit'; +import { createBroker } from '@atlas/messaging'; +import { createDatabase, schema, type DatabaseHandle } from '@atlas/db'; +import { createSilentLogger } from '@atlas/utils'; +import { isValidTransition } from '../src/lib/transitions.js'; +import { buildApp } from '../src/app.js'; +import { loadApplicationsServiceEnv } from '../src/env.js'; + +// DB-backed tests self-skip when ATLAS_TEST_DATABASE_URL is unset (see .env.example). +const testDatabaseUrl = process.env.ATLAS_TEST_DATABASE_URL; +const SUPABASE_URL = 'https://test-project.supabase.co'; + +/** + * Requests that arrive together: a double click, a retry racing the original, a user and a staff + * member acting on the same application. The service reads, decides, then writes, so what these + * check is that the decision was still true when the write happened. + */ +describe.skipIf(!testDatabaseUrl)('applications-service under concurrent requests', () => { + let app: FastifyInstance; + let dbHandle: DatabaseHandle; + let token: string; + const userId = randomUUID(); + const email = `applications-races-${userId}@example.com`; + const companyName = `Races Test Co ${randomUUID().slice(0, 8)}`; + let companyId: string; + let resumeId: string; + const jobIds: string[] = []; + const published: string[] = []; + + beforeAll(async () => { + const { publicKey, privateKey } = await generateKeyPair('ES256'); + const jwk = await exportJWK(publicKey); + jwk.kid = 'test-key'; + jwk.alg = 'ES256'; + jwk.use = 'sig'; + vi.stubGlobal( + 'fetch', + async () => new Response(JSON.stringify({ keys: [jwk] }), { status: 200, headers: { 'content-type': 'application/json' } }), + ); + token = await new SignJWT({ session_id: randomUUID(), email, app_metadata: {} }) + .setProtectedHeader({ alg: 'ES256', kid: 'test-key' }) + .setSubject(userId) + .setIssuer(`${SUPABASE_URL}/auth/v1`) + .setAudience('authenticated') + .setIssuedAt() + .setExpirationTime(Math.floor(Date.now() / 1000) + 900) + .sign(privateKey); + + const env = loadApplicationsServiceEnv({ + DATABASE_URL: testDatabaseUrl, + PORT: '4005', + SUPABASE_URL, + // The limiter is not what is under test here. + RATE_LIMIT_MAX: '100000', + }); + dbHandle = createDatabase({ url: env.DATABASE_URL, maxConnections: 20 }); + const broker = createBroker({ driver: 'memory', logger: createSilentLogger() }); + const publish = broker.publish.bind(broker); + broker.publish = async (envelope) => { + published.push(envelope.event_type); + return publish(envelope); + }; + app = buildApp({ + db: dbHandle.db, + sql: dbHandle.sql, + env, + logger: createSilentLogger(), + broker, + tokenVerifier: createTokenVerifierConfig(env), + }); + await app.ready(); + + await dbHandle.sql` + insert into auth.users (id, instance_id, aud, role, email, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at) + values (${userId}, '00000000-0000-0000-0000-000000000000', 'authenticated', 'authenticated', ${email}, now(), '{"provider":"email"}'::jsonb, ${JSON.stringify({ full_name: 'Races Test User' })}::jsonb, now(), now()) + `; + const [company] = await dbHandle.db + .insert(schema.companies) + .values({ name: companyName, normalizedName: companyName.toLowerCase() }) + .returning(); + companyId = company!.companyId; + for (let index = 0; index < 8; index += 1) { + const [job] = await dbHandle.db + .insert(schema.jobs) + .values({ companyId, title: `Races Job ${index}`, source: 'manual', jobHash: randomUUID().replace(/-/g, '').padEnd(64, '0'), isActive: true }) + .returning(); + jobIds.push(job!.jobId); + } + const [resume] = await dbHandle.db + .insert(schema.resumes) + .values({ userId, storageUrl: `resumes/${userId}/seed`, originalFilename: 'resume.txt', contentType: 'text/plain', byteSize: 10, contentHash: randomUUID(), status: 'parsed' }) + .returning(); + resumeId = resume!.resumeId; + }); + + afterAll(async () => { + await dbHandle.db.delete(schema.applications).where(eq(schema.applications.userId, userId)); + await dbHandle.db.delete(schema.jobs).where(eq(schema.jobs.companyId, companyId)); + await dbHandle.db.delete(schema.companies).where(eq(schema.companies.companyId, companyId)); + await dbHandle.db.delete(schema.resumes).where(eq(schema.resumes.userId, userId)); + await dbHandle.sql`delete from auth.users where id = ${userId}`; + await app.close(); + await dbHandle.close(); + }); + + // The per-address limiter (30 creates a minute) is not what is under test, so each request + // comes from its own address. + let nextAddress = 0; + const address = () => `10.${(nextAddress >> 16) & 255}.${(nextAddress >> 8) & 255}.${nextAddress++ & 255}`; + + const create = (jobId: string, key: string) => + app.inject({ + method: 'POST', + url: '/v1/applications', + headers: { authorization: `Bearer ${token}`, 'idempotency-key': key, 'x-forwarded-for': address() }, + payload: { job_id: jobId, resume_id: resumeId, mode: 'manual' }, + }); + const move = (applicationId: string, to_status: string) => + app.inject({ + method: 'POST', + url: `/v1/applications/${applicationId}/events`, + headers: { authorization: `Bearer ${token}`, 'x-forwarded-for': address() }, + payload: { to_status }, + }); + const rowsFor = (jobId: string) => + dbHandle.db.select().from(schema.applications).where(eq(schema.applications.jobId, jobId)); + const trail = (applicationId: string) => + dbHandle.db + .select() + .from(schema.applicationEvents) + .where(eq(schema.applicationEvents.applicationId, applicationId)) + .orderBy(asc(schema.applicationEvents.createdAt), asc(schema.applicationEvents.eventId)); + const spread = (statuses: number[]) => [...new Set(statuses)].sort(); + + async function applicationIn(jobIndex: number, path: string[]): Promise { + const jobId = jobIds[jobIndex]!; + const res = await create(jobId, `seed-${jobId}`); + expect(res.statusCode).toBe(201); + const applicationId = res.json().application.application_id as string; + for (const status of path) expect((await move(applicationId, status)).statusCode).toBe(200); + return applicationId; + } + + /** The trail is a chain: each event starts where the one before ended, by a legal move, and the head is its last stop. */ + async function expectConsistentTrail(applicationId: string): Promise { + const events = await trail(applicationId); + const [application] = await dbHandle.db + .select() + .from(schema.applications) + .where(eq(schema.applications.applicationId, applicationId)); + let at = 'draft'; + for (const event of events) { + expect(event.fromStatus, `event ${event.fromStatus} -> ${event.toStatus} does not start where the previous one ended (${at})`).toBe(at); + expect(isValidTransition(event.fromStatus!, event.toStatus)).toBe(true); + at = event.toStatus; + } + expect(application!.status).toBe(at); + } + + it('30 identical creates (same key, same body) make one application and no errors', async () => { + const jobId = jobIds[0]!; + const results = await Promise.all(Array.from({ length: 30 }, () => create(jobId, 'same-key-everywhere'))); + + expect(spread(results.map((res) => res.statusCode))).toEqual(expect.arrayContaining([201])); + expect(results.map((res) => res.statusCode).every((code) => code === 200 || code === 201)).toBe(true); + expect(new Set(results.map((res) => res.json().application.application_id)).size).toBe(1); + expect(await rowsFor(jobId)).toHaveLength(1); + }); + + it('30 creates for one job with different keys make one application; the rest are conflicts, never 500s', async () => { + const jobId = jobIds[1]!; + const results = await Promise.all(Array.from({ length: 30 }, (_unused, index) => create(jobId, `distinct-key-${index}`))); + + const codes = results.map((res) => res.statusCode); + expect(codes.filter((code) => code === 201)).toHaveLength(1); + expect(codes.filter((code) => code === 409)).toHaveLength(29); + expect(await rowsFor(jobId)).toHaveLength(1); + }); + + it('20 simultaneous "queued" requests move the application once and leave one event', async () => { + const applicationId = await applicationIn(2, []); + const results = await Promise.all(Array.from({ length: 20 }, () => move(applicationId, 'queued'))); + + const codes = results.map((res) => res.statusCode); + expect(codes.filter((code) => code === 200)).toHaveLength(1); + expect(codes.every((code) => code === 200 || code === 400 || code === 409)).toBe(true); + const events = await trail(applicationId); + expect(events.filter((event) => event.toStatus === 'queued')).toHaveLength(1); + await expectConsistentTrail(applicationId); + }); + + it('simultaneous "submitted" requests publish application.submitted once', async () => { + const applicationId = await applicationIn(3, ['queued', 'submitting']); + const before = published.filter((type) => type === 'application.submitted').length; + const results = await Promise.all(Array.from({ length: 15 }, () => move(applicationId, 'submitted'))); + + expect(results.filter((res) => res.statusCode === 200)).toHaveLength(1); + expect(published.filter((type) => type === 'application.submitted').length - before).toBe(1); + await expectConsistentTrail(applicationId); + }); + + it('a terminal status stays terminal when "offer" and "rejected" arrive together', async () => { + const applicationIds: string[] = []; + for (const jobIndex of [4, 5, 6, 7]) { + applicationIds.push(await applicationIn(jobIndex, ['submitted', 'interviewing'])); + } + for (const applicationId of applicationIds) { + const results = await Promise.all( + Array.from({ length: 12 }, (_unused, index) => move(applicationId, index % 2 === 0 ? 'offer' : 'rejected')), + ); + expect(results.every((res) => [200, 400, 409].includes(res.statusCode))).toBe(true); + await expectConsistentTrail(applicationId); + } + const heads = await dbHandle.db + .select({ status: schema.applications.status }) + .from(schema.applications) + .where(inArray(schema.applications.applicationId, applicationIds)); + // "rejected" has no way out: if any application ended on "offer", it got there after being rejected, + // or both moves were recorded from "interviewing" - the trail check above catches both. + expect(heads.every((head) => head.status === 'offer' || head.status === 'rejected')).toBe(true); + }); +}); diff --git a/services/applications/test/body-fuzz.test.ts b/services/applications/test/body-fuzz.test.ts new file mode 100644 index 0000000..29e84dd --- /dev/null +++ b/services/applications/test/body-fuzz.test.ts @@ -0,0 +1,213 @@ +import { randomUUID } from 'node:crypto'; +import type { FastifyInstance } from 'fastify'; +import { exportJWK, generateKeyPair, SignJWT } from 'jose'; +import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'; +import { createTokenVerifierConfig } from '@atlas/auth-kit'; +import { createDatabase, type DatabaseHandle } from '@atlas/db'; +import { createBroker } from '@atlas/messaging'; +import { createSilentLogger } from '@atlas/utils'; +import { buildApp } from '../src/app.js'; +import { loadApplicationsServiceEnv } from '../src/env.js'; + +const SUPABASE_URL = 'https://test-project.supabase.co'; +// Nothing listens on port 1. Every request below must be turned away before it needs the database: +// that is what is being checked. One that reaches the database comes back as a 500. +const UNREACHABLE_DATABASE_URL = 'postgres://atlas:atlas@127.0.0.1:1/atlas_body_fuzz'; + +/** + * Hostile request bodies and content types. A service must answer each with a clean 4xx in its + * standard error envelope: never a 500, never a stack trace or driver text, never a hang. + */ +describe('applications-service request bodies', () => { + let app: FastifyInstance; + let handle: DatabaseHandle; + let token: string; + const applicationId = randomUUID(); + let counter = 0; + + beforeAll(async () => { + const { publicKey, privateKey } = await generateKeyPair('ES256'); + const jwk = await exportJWK(publicKey); + jwk.kid = 'test-key'; + jwk.alg = 'ES256'; + jwk.use = 'sig'; + vi.stubGlobal('fetch', async () => new Response(JSON.stringify({ keys: [jwk] }), { status: 200, headers: { 'content-type': 'application/json' } })); + token = await new SignJWT({ session_id: randomUUID(), email: 'fuzz@example.com', app_metadata: {} }) + .setProtectedHeader({ alg: 'ES256', kid: 'test-key' }) + .setSubject(randomUUID()) + .setIssuer(`${SUPABASE_URL}/auth/v1`) + .setAudience('authenticated') + .setIssuedAt() + .setExpirationTime(Math.floor(Date.now() / 1000) + 900) + .sign(privateKey); + + const env = loadApplicationsServiceEnv({ + DATABASE_URL: UNREACHABLE_DATABASE_URL, + PORT: '4005', + SUPABASE_URL, + LOG_LEVEL: 'fatal', + RATE_LIMIT_MAX: '100000', + BODY_LIMIT_BYTES: '4096', + }); + handle = createDatabase({ url: env.DATABASE_URL }); + app = buildApp({ + db: handle.db, + sql: handle.sql, + env, + logger: createSilentLogger(), + broker: createBroker({ driver: 'memory', logger: createSilentLogger() }), + tokenVerifier: createTokenVerifierConfig(env), + }); + await app.ready(); + }); + + afterAll(async () => { + await app.close(); + await handle.close(); + }); + + async function send(url: string, body: string | Buffer | undefined, headers: Record = {}, method: 'POST' | 'PUT' | 'PATCH' | 'DELETE' = 'POST') { + counter += 1; + return app.inject({ + method, + url, + payload: body, + headers: { + authorization: `Bearer ${token}`, + 'idempotency-key': 'fuzz-key-0123456789', + 'x-forwarded-for': `10.1.${(counter >> 8) & 255}.${counter & 255}`, + ...headers, + }, + }); + } + const json = { 'content-type': 'application/json' }; + + const BODIES: ReadonlyArray = [ + ['an empty body', ''], + ['unterminated JSON', '{"job_id":'], + ['trailing garbage', '{"job_id":"x"} trailing'], + ['JSON null', 'null'], + ['a JSON array', '[]'], + ['a JSON string', '"text"'], + ['a JSON number', '123'], + ['JSON true', 'true'], + ['single quotes', "{'job_id':'x'}"], + ['a BOM before the object', '{"job_id":"x"}'], + ['an object of the wrong shape', '{"foo":"bar"}'], + ['wrong types', '{"job_id":123,"resume_id":false,"mode":["manual"]}'], + ['nulls for every field', '{"job_id":null,"resume_id":null,"mode":null}'], + ['prototype keys', '{"__proto__":{"admin":true},"constructor":{"prototype":{"admin":true}},"job_id":"x"}'], + ['duplicate keys', '{"mode":"manual","mode":"auto","job_id":"x","job_id":"y"}'], + ['a NUL in a string', '{"job_id":"a\\u0000b","resume_id":"x","mode":"manual"}'], + ['a huge number', '{"job_id":1e999}'], + ['an enormous exponent', '{"job_id":1E400,"resume_id":-1E400}'], + ['deep nesting (5,000 arrays)', `${'['.repeat(5000)}${']'.repeat(5000)}`], + ['deep nesting (5,000 objects)', `${'{"a":'.repeat(1500)}1${'}'.repeat(1500)}`], + ['lone surrogates', '{"job_id":"\\ud800","resume_id":"\\udfff","mode":"manual"}'], + ['a long string value', `{"job_id":"${'x'.repeat(3000)}","resume_id":"y","mode":"manual"}`], + ]; + + it.each(BODIES)('POST /v1/applications with %s is a 4xx in the standard envelope', async (_label, body) => { + const res = await send('/v1/applications', body, json); + expect(res.statusCode).toBeGreaterThanOrEqual(400); + expect(res.statusCode).toBeLessThan(500); + expect(res.headers['content-type']).toMatch(/application\/json/); + expect(res.json().error).toMatchObject({ code: expect.any(String), message: expect.any(String), request_id: expect.any(String) }); + expect(res.body).not.toMatch(/\bat \S+ \(|node_modules|postgres|ECONNREFUSED|stack/i); + }); + + it.each(BODIES)('POST /v1/applications/:id/events with %s is a 4xx in the standard envelope', async (_label, body) => { + const res = await send(`/v1/applications/${applicationId}/events`, body, json); + expect(res.statusCode).toBeGreaterThanOrEqual(400); + expect(res.statusCode).toBeLessThan(500); + expect(res.json().error.request_id).toEqual(expect.any(String)); + }); + + it.each([ + ['text/plain', 'text/plain'], + ['application/x-www-form-urlencoded', 'application/x-www-form-urlencoded'], + ['multipart/form-data with no boundary', 'multipart/form-data'], + ['application/xml', 'application/xml'], + ['a JSON type with a bogus charset', 'application/json; charset=klingon'], + ['an invalid content type', 'not a media type'], + ])('refuses a JSON body sent as %s', async (_label, contentType) => { + const res = await send('/v1/applications', '{"job_id":"x","resume_id":"y","mode":"manual"}', { 'content-type': contentType }); + expect([400, 415]).toContain(res.statusCode); + expect(res.json().error.request_id).toEqual(expect.any(String)); + }); + + it('refuses a body with no content type at all', async () => { + const res = await send('/v1/applications', '{"job_id":"x"}'); + expect(res.statusCode).toBeGreaterThanOrEqual(400); + expect(res.statusCode).toBeLessThan(500); + }); + + it('answers 413 for a body over the limit, whatever it holds', async () => { + const res = await send('/v1/applications', `{"job_id":"${'x'.repeat(8000)}"}`, json); + expect(res.statusCode).toBe(413); + expect(res.json().error.code).toBe('PAYLOAD_TOO_LARGE'); + }); + + it.each([['PUT'], ['PATCH'], ['DELETE']] as const)('answers 404 for %s on a route that does not take it', async (method) => { + const res = await send('/v1/applications', '{}', json, method); + expect(res.statusCode).toBe(404); + expect(res.json().error.code).toBe('NOT_FOUND'); + }); + + it.each([ + ['/v1/applications/not-a-uuid/events'], + ['/v1/applications/00000000-0000-0000-0000-00000000000/events'], + [`/v1/applications/${applicationId}%00/events`], + ['/v1/applications/%e0%a4%a/events'], + ['/v1/applications/..%2f..%2fetc%2fpasswd/events'], + ])('answers 4xx for a malformed id in the path: %s', async (url) => { + const res = await send(url, '{"to_status":"queued"}', json); + expect(res.statusCode).toBeGreaterThanOrEqual(400); + expect(res.statusCode).toBeLessThan(500); + }); + + // Not listed: `limit=0x10` (read as 16) and bracketed keys such as `limit[]=1` (an unknown key, ignored) + // are ordinary valid requests, not hostile ones, and would need the database. + it.each([ + ['limit=0'], + ['limit=-1'], + ['limit=101'], + ['limit=abc'], + ['limit=1e3'], + ['limit=1.5'], + ['limit=%00'], + ['limit='], + ['limit=999999999999999999999'], + ['limit=1&limit=2'], + ['cursor='], + ['cursor=a&cursor=b'], + ['job_id=not-a-uuid'], + ['job_id=1&job_id=2'], + ['scope=everything'], + ['scope=mine&scope=organization'], + ])('answers 4xx for the query string ?%s on the list endpoint', async (query) => { + const res = await send(`/v1/applications?${query}`, undefined, {}, 'POST').then(() => + app.inject({ + method: 'GET', + url: `/v1/applications?${query}`, + headers: { authorization: `Bearer ${token}`, 'x-forwarded-for': `10.2.0.${(counter += 1) & 255}` }, + }), + ); + expect(res.statusCode).toBeGreaterThanOrEqual(400); + expect(res.statusCode).toBeLessThan(500); + expect(res.json().error.request_id).toEqual(expect.any(String)); + }); + + // The database behind this app is unreachable (port 1). A caller who is signed in and whose request + // is valid should be told "try again", not that the service crashed. + it('answers 503 with the standard envelope when the database cannot be reached', async () => { + const res = await app.inject({ + method: 'GET', + url: '/v1/applications', + headers: { authorization: `Bearer ${token}`, 'x-forwarded-for': '10.3.0.1' }, + }); + expect(res.statusCode).toBe(503); + expect(res.json().error).toMatchObject({ code: 'UPSTREAM_UNAVAILABLE', request_id: expect.any(String) }); + expect(res.body).not.toMatch(/127\.0\.0\.1|ECONNREFUSED|postgres:\/\//); + }); +}); diff --git a/services/auth/src/env.ts b/services/auth/src/env.ts index 7ebee8a..2ef22b8 100644 --- a/services/auth/src/env.ts +++ b/services/auth/src/env.ts @@ -3,6 +3,7 @@ import { databaseEnvSchema, httpEnvSchema, loadEnv, + rateLimitWindowSchema, storageEnvSchema, supabaseAuthEnvSchema, } from '@atlas/config'; @@ -27,7 +28,7 @@ export const authServiceEnvSchema = z.object({ */ PRIVACY_EXPORT_RATE_LIMIT_MAX: z.coerce.number().int().min(1).default(10), PRIVACY_DELETE_RATE_LIMIT_MAX: z.coerce.number().int().min(1).default(3), - PRIVACY_RATE_LIMIT_WINDOW: z.string().min(1).default('1 hour'), + PRIVACY_RATE_LIMIT_WINDOW: rateLimitWindowSchema.default('1 hour'), }); export type AuthServiceEnv = z.infer; diff --git a/services/auth/test/delete-account.test.ts b/services/auth/test/delete-account.test.ts index 0625d24..1c68a11 100644 --- a/services/auth/test/delete-account.test.ts +++ b/services/auth/test/delete-account.test.ts @@ -201,6 +201,31 @@ describe.skipIf(!testDatabaseUrl)('DELETE /v1/auth/me', () => { expect(await tombstones(h, user.userId)).toHaveLength(1); }); + it('survives six simultaneous deletions of one account: every request succeeds, one tombstone, nothing left', async () => { + const user = await h.seedUser(); + const [job] = await h.seedJobs(1); + const data = await seedUserData(h, user, { label: 'parallel', jobIds: [job!] }); + + // Each request from its own address: the per-address limit (3 deletions an hour) is not under test. + const results = await Promise.all( + Array.from({ length: 6 }, async (_unused, index) => + h.app.inject({ + method: 'DELETE', + url: '/v1/auth/me', + headers: { ...(await h.authHeaders(user.userId)), 'x-forwarded-for': `10.9.0.${index + 1}` }, + payload: { confirm: 'DELETE' } as never, + }), + ), + ); + + expect(results.map((res) => res.statusCode)).toEqual(Array(6).fill(200)); + expect(await userExists(h, user.userId)).toBe(false); + expect(await tombstones(h, user.userId)).toHaveLength(1); + expect( + await rowsMentioning(h.handle.sql, [user.userId, user.email, user.fullName, ...Object.values(data.markers)]), + ).toEqual({}); + }); + describe('confirmation', () => { it.each([ ['no body', undefined, undefined], diff --git a/services/jobs/src/env.ts b/services/jobs/src/env.ts index 1fe1875..9861b15 100644 --- a/services/jobs/src/env.ts +++ b/services/jobs/src/env.ts @@ -1,4 +1,12 @@ -import { baseEnvSchema, databaseEnvSchema, httpEnvSchema, loadEnv, messagingEnvSchema, supabaseAuthEnvSchema } from '@atlas/config'; +import { + baseEnvSchema, + cronSecretSchema, + databaseEnvSchema, + httpEnvSchema, + loadEnv, + messagingEnvSchema, + supabaseAuthEnvSchema, +} from '@atlas/config'; import { z } from 'zod'; export const jobsServiceEnvSchema = z.object({ @@ -18,7 +26,7 @@ export const jobsServiceEnvSchema = z.object({ * ingestion (a scheduler sends `Authorization: Bearer $CRON_SECRET`). Unset, * the route answers 503 and never runs. */ - CRON_SECRET: z.string().min(16, 'CRON_SECRET must be at least 16 characters').optional(), + CRON_SECRET: cronSecretSchema.optional(), /** * An email address or URL where the operator of a job board can reach whoever * runs this reader, appended to the User-Agent it sends. Printable ASCII only diff --git a/services/jobs/src/lib/job-sources/common.ts b/services/jobs/src/lib/job-sources/common.ts index 32ec807..e197c84 100644 --- a/services/jobs/src/lib/job-sources/common.ts +++ b/services/jobs/src/lib/job-sources/common.ts @@ -37,10 +37,24 @@ export class SourcePayloadError extends Error { } } -/** Trimmed, length-capped text; null when nothing is left. */ +/** + * Characters that have no place in a posting and do harm elsewhere: NUL (Postgres cannot store it, + * so the posting would be rejected, and one rejected posting stops a board's closed roles from ever + * being deactivated), the other control characters except tab, line feed and carriage return + * (they garble logs and terminals), and the bidirectional overrides and isolates that reverse the + * text around them, which can make a title read as something else. + */ +// eslint-disable-next-line no-control-regex +const UNSAFE_TEXT_CHARS = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/g; + +export function stripUnsafeChars(text: string): string { + return text.replace(UNSAFE_TEXT_CHARS, ''); +} + +/** Cleaned, trimmed, length-capped text; null when nothing is left. */ export function clampText(value: string | null | undefined, max: number): string | null { if (typeof value !== 'string') return null; - const trimmed = value.trim(); + const trimmed = stripUnsafeChars(value).trim(); if (trimmed === '') return null; return trimmed.length > max ? trimmed.slice(0, max).trimEnd() : trimmed; } diff --git a/services/jobs/src/repo/jobs.ts b/services/jobs/src/repo/jobs.ts index 35514a4..f034b74 100644 --- a/services/jobs/src/repo/jobs.ts +++ b/services/jobs/src/repo/jobs.ts @@ -1,7 +1,7 @@ import { and, desc, eq, ilike, inArray, lt, or, sql } from 'drizzle-orm'; import { schema, type Database } from '@atlas/db'; import type { EmploymentType, Job, JobSource, PaginationQuery, RemoteType } from '@atlas/types'; -import { decodeCursor, encodeCursor } from '@atlas/utils'; +import { encodeCursor, parseTimeCursor } from '@atlas/utils'; type JobRow = typeof schema.jobs.$inferSelect; @@ -189,9 +189,9 @@ export async function listActive( filters: ListActiveFilters, pagination: PaginationQuery, ): Promise { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorCreatedAt = typeof cursorValue?.createdAt === 'string' ? cursorValue.createdAt : null; - const cursorId = typeof cursorValue?.id === 'string' ? cursorValue.id : null; + const cursor = parseTimeCursor(pagination.cursor); + const cursorCreatedAt = cursor?.createdAt ?? null; + const cursorId = cursor?.id ?? null; const conditions = []; if (filters.isActive !== undefined) conditions.push(eq(schema.jobs.isActive, filters.isActive)); diff --git a/services/jobs/src/repo/scores.ts b/services/jobs/src/repo/scores.ts index 794e147..fd262b8 100644 --- a/services/jobs/src/repo/scores.ts +++ b/services/jobs/src/repo/scores.ts @@ -1,7 +1,7 @@ import { and, desc, eq, ilike, lt, or } from 'drizzle-orm'; import { schema, type Database } from '@atlas/db'; import type { JobRecommendation, PaginationQuery, RemoteType } from '@atlas/types'; -import { decodeCursor, encodeCursor } from '@atlas/utils'; +import { encodeCursor, parseScoreCursor } from '@atlas/utils'; import { toJob } from './jobs.js'; export interface ListScoresResult { @@ -25,9 +25,9 @@ export async function listForUser( filters: ListScoresFilters, pagination: PaginationQuery, ): Promise { - const cursorValue = pagination.cursor ? decodeCursor(pagination.cursor) : null; - const cursorScore = typeof cursorValue?.score === 'number' ? cursorValue.score : null; - const cursorId = typeof cursorValue?.id === 'string' ? cursorValue.id : null; + const cursor = parseScoreCursor(pagination.cursor); + const cursorScore = cursor?.score ?? null; + const cursorId = cursor?.id ?? null; // Scores outlive the posting they were computed for: a job its source has stopped listing is // marked inactive (scheduled ingestion), and must stop being recommended along with it. diff --git a/services/jobs/test/hostile-postings.test.ts b/services/jobs/test/hostile-postings.test.ts new file mode 100644 index 0000000..b4ef832 --- /dev/null +++ b/services/jobs/test/hostile-postings.test.ts @@ -0,0 +1,112 @@ +import { randomUUID } from 'node:crypto'; +import { eq, inArray } from 'drizzle-orm'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { createDatabase, schema, type DatabaseHandle } from '@atlas/db'; +import type { EventBroker } from '@atlas/messaging'; +import { createSilentLogger } from '@atlas/utils'; +import { runSourceIngestion } from '../src/lib/run-sources.js'; +import { upsert } from '../src/repo/job-sources.js'; + +// DB-backed: self-skips when ATLAS_TEST_DATABASE_URL is unset (see .env.example). +const testDatabaseUrl = process.env.ATLAS_TEST_DATABASE_URL; + +/** + * A job board is somebody else's server, so what it returns is hostile input: the postings land in + * the shared catalog that every user reads. These feed one board a mix of hostile and ordinary + * postings and check that the ordinary ones still arrive and nothing hostile is stored as is. + */ +describe.skipIf(!testDatabaseUrl)('a job board that sends hostile postings', () => { + let dbHandle: DatabaseHandle; + const tag = randomUUID().slice(0, 8); + const companyName = `Hostile Co ${tag}`; + const sourceIds: string[] = []; + + const broker: EventBroker = { + publish: async () => undefined, + subscribe: async (options) => ({ consumer: options.consumer, stop: async () => undefined }), + isHealthy: () => true, + close: async () => undefined, + }; + + beforeAll(() => { + dbHandle = createDatabase({ url: testDatabaseUrl!, maxConnections: 4 }); + }); + + afterAll(async () => { + const [company] = await dbHandle.db.select().from(schema.companies).where(eq(schema.companies.name, companyName)); + if (company) { + await dbHandle.db.delete(schema.jobs).where(eq(schema.jobs.companyId, company.companyId)); + await dbHandle.db.delete(schema.companies).where(eq(schema.companies.companyId, company.companyId)); + } + if (sourceIds.length > 0) { + await dbHandle.db.delete(schema.jobSources).where(inArray(schema.jobSources.sourceId, sourceIds)); + } + await dbHandle.close(); + }); + + async function ingest(jobs: unknown[]) { + const { row } = await upsert(dbHandle.db, { + provider: 'greenhouse', + boardToken: `host-${tag}`, + companyName, + }); + sourceIds.push(row.sourceId); + const fetchImpl: typeof fetch = async () => + new Response(JSON.stringify({ jobs }), { status: 200, headers: { 'content-type': 'application/json' } }); + const report = await runSourceIngestion( + { db: dbHandle.db, broker, logger: createSilentLogger(), fetch: fetchImpl, userAgent: 'AtlasJobIngest/test' }, + { budgetMs: 20_000, sourceIds: [row.sourceId] }, + ); + const stored = await dbHandle.db + .select({ job: schema.jobs }) + .from(schema.jobs) + .innerJoin(schema.companies, eq(schema.jobs.companyId, schema.companies.companyId)) + .where(eq(schema.companies.name, companyName)) + .then((rows) => rows.map((entry) => entry.job)); + return { report, stored }; + } + + it('stores the ordinary postings, drops or cleans the hostile ones, and never stores a NUL or a script link', async () => { + const { report, stored } = await ingest([ + { id: 9001, title: `Good Engineer ${tag}`, content: 'Build services in TypeScript.', absolute_url: 'https://boards.greenhouse.io/x/jobs/9001', location: { name: 'Berlin' } }, + { id: 9002, title: `Nul Title\u0000 ${tag}`, content: 'Fine description', absolute_url: 'https://boards.greenhouse.io/x/jobs/9002' }, + { id: 9003, title: `Nul Body ${tag}`, content: 'Description with a \u0000 inside', location: { name: 'Ber\u0000lin' }, absolute_url: 'https://boards.greenhouse.io/x/jobs/9003' }, + { id: 9004, title: `Script Link ${tag}`, content: 'x', absolute_url: 'javascript:alert(document.cookie)' }, + { id: 9005, title: `Data Link ${tag}`, content: 'x', absolute_url: 'data:text/html,' }, + { id: 9006, title: `Control Chars ${tag} \u0007\u001b[31mred‮evil`, content: 'x​x', absolute_url: 'https://boards.greenhouse.io/x/jobs/9006' }, + { id: 9007, title: `Huge ${tag} ${'x'.repeat(100_000)}`, content: 'y'.repeat(500_000), absolute_url: 'https://boards.greenhouse.io/x/jobs/9007' }, + { id: 9008, title: `Markup ${tag} `, content: '

Real text

', absolute_url: 'https://boards.greenhouse.io/x/jobs/9008' }, + { id: 'not-a-number-but-allowed', title: `String Id ${tag}`, content: 'x', absolute_url: 'https://boards.greenhouse.io/x/jobs/9009' }, + { id: null, title: 'No id at all' }, + 'a string, not an object', + null, + { id: 9010 }, + ]); + + // The run as a whole worked: one hostile posting must not take the board down. + expect(report.failed).toBe(0); + expect(report.succeeded).toBe(1); + expect(stored.map((job) => job.title)).toContain(`Good Engineer ${tag}`); + + // A NUL used to make its posting unstorable, and a single unstorable posting stops the board's + // closed roles from ever being deactivated. It is cleaned instead, so nothing is rejected. + expect(report.rejected).toBe(0); + expect(report.sources[0]?.deactivation_skipped).not.toBe('rejected_postings'); + expect(stored.map((job) => job.title)).toContain(`Nul Title ${tag}`); + expect(stored.find((job) => job.title === `Nul Body ${tag}`)?.location).toBe('Berlin'); + + for (const job of stored) { + const strings = [job.title, job.description, job.location, job.applyUrl].filter((value): value is string => typeof value === 'string'); + for (const text of strings) expect(text.includes('\u0000')).toBe(false); + // Controls other than tab, newline and carriage return, and bidi overrides, are gone. + for (const text of [job.title, job.description ?? '', job.location ?? '']) { + // eslint-disable-next-line no-control-regex + expect(text).not.toMatch(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/); + } + if (job.applyUrl !== null) expect(job.applyUrl).toMatch(/^https?:\/\//); + expect(job.title.length).toBeLessThanOrEqual(300); + expect((job.description ?? '').length).toBeLessThanOrEqual(200_000); + expect(job.description ?? '').not.toMatch(/