Midterm Examination — Data Science Programming I

Mini Project: E-Commerce Data Pipeline & Web Scraping Intelligence

✦ Data Science Programming I — Class B
Midterm Data Programming

E-Commerce Data Pipeline & Web Scraping Intelligence

Andre
Andre
52250065
Refantanur Husnul Haqib
Refantanur Husnul Haqib
52250052
Naila Syahrani Putri
Naila Syahrani Putri
52250070
🎓 Data Science Program
📅 2026-04-26
📊 2 Mini Projects

1 Mini Project 1 — E-Commerce Data Pipeline

About Mini Project 1 — E-Commerce Data Pipeline

This mini project simulates a real-world data engineering scenario: integrating e-commerce transaction data from 5 different file formats (CSV, Excel, JSON, TXT, XML) into a single clean, analysis-ready dataset. The pipeline follows production-grade principles — each stage is documented, reproducible, and designed to handle edge cases gracefully. The final output is a structured dataset with business-driven feature engineering ready for executive reporting, BI dashboards, or predictive modeling.

1.1 Section A — Data Collection

Section A — Automated Multi-Format Data Ingestion

The primary objective is to build a fully automated, format-agnostic data ingestion pipeline. Rather than writing separate code for each file, a single loop structure handles all formats through condition-based dispatch — reflecting the principles of Clean Code and DRY (Don’t Repeat Yourself). Every file is verified for availability before reading, then merged into a unified dataset with provenance metadata enabling a full audit trail back to the original source of each row.

1.1.1 A.1 — File Inventory and Availability Check

1.1.2 A.2 — Custom XML Parser Function

baca_xml() defined and ready.

1.1.3 A.3 — REQUIRED LOOP: Read All Files

  [OK] Midterm_Exam_Classroom.csv             | 2000 rows | 22 cols
  [OK] Midterm_Exam_Classroom.xlsx            | 2000 rows | 22 cols
  [OK] Midterm_Exam_Classroom.json            | 2000 rows | 22 cols
  [OK] Midterm_Exam_Classroom.txt             | 2000 rows | 1 cols
  [OK] Midterm_Exam_Classroom.xml             | 2000 rows | 22 cols

5 of 5 files successfully read.

1.1.4 A.4 — Merge and Export to Excel

  Merged: Midterm_Exam_Classroom.csv             (2000 rows)
  Merged: Midterm_Exam_Classroom.xlsx            (2000 rows)
  Merged: Midterm_Exam_Classroom.json            (2000 rows)
  Merged: Midterm_Exam_Classroom.txt             (2000 rows)
  Merged: Midterm_Exam_Classroom.xml             (2000 rows)

Total Rows   : 10,000
Total Columns: 24
All columns cast to character — numeric conversion occurs in Section C.

[EXCEL] Saved: hasil_gabungan.xlsx

1.2 Section B — Data Handling

Section B — Comprehensive Data Quality Audit

Before any intervention, the state of the data must be thoroughly and objectively understood — much like a medical diagnosis before treatment. Section B executes a three-dimensional audit: (1) Data type profiling to verify alignment between storage format and column semantics; (2) Missing value analysis measuring not just counts but patterns that may indicate systemic upstream issues; and (3) Duplicate detection separating technical redundancy from genuine business duplication. The audit findings form the scientific basis for all cleaning strategies in Section C.

1.2.1 B.1 — Column Profile

1.2.2 B.2 — Missing Values

Total missing values : 54682
Columns with missing : 23 of 24

1.2.3 B.3 — Duplicate Rows

Duplicate rows  : 45
Percentage      : 0.45%

Sample duplicate rows (first 5):

1.2.4 B.4 — Data Quality Issues

1.3 Section C — Data Cleaning

Section C — Systematic and Auditable Data Cleaning

Data cleaning is not merely tidying — it is an analytical decision-making process that must be scientifically defensible. Every transformation in Section C follows informed cleaning principles: the rationale for each strategy (why median over mean? why fill with “Unknown” rather than drop rows?) is explicitly grounded in data distribution characteristics and business context. The sequence of operations is intentional — standardization precedes imputation, and deduplication occurs last to ensure no clean rows are inadvertently removed. Each step is quantitatively validated by comparing before-and-after states.

1.3.1 C.0 — Create Working Copy

Working copy created: 10,000 rows x 24 columns

1.3.2 C.1 — Platform Standardization

Platform distribution after standardization:

     Blibli      Lazada      Shopee Tiktok Shop   Tokopedia     Unknown 
       1616        1552        1664        1624        1544        2000 

1.3.3 C.2 — Net Sales Cleaning

Min  : Rp 0
Max  : Rp 18,080,224
Mean : Rp 1,101,874
Remaining NA: 0

1.3.4 C.3 — Missing Value Imputation

Missing payment_method after imputation: 0
Missing net_sales after imputation     : 0

1.3.5 C.4 — Order Status Standardization

Order status distribution after standardization:

       Batal     Delivered   On Delivery         Retur      Returned  
           12            50             4             4             6 
        Batal     Cancelled     Completed     Delivered   On Delivery 
          120           476          1600          4670           188 
        Retur      Returned       Shipped       Unknown 
          168           294           408          2000 

1.3.6 C.5 — REQUIRED LOOP: Text Column Cleaning

  [OK] platform             | missing: 0 -> 0
  [OK] category             | missing: 2000 -> 0
  [OK] product_name         | missing: 2000 -> 0
  [OK] order_status         | missing: 0 -> 0
  [OK] payment_method       | missing: 0 -> 0

1.3.7 C.6 — Deduplication and Summary

Duplicates removed : 45 rows
Clean dataset      : 9,955 rows
Total columns      : 24

1.4 Section D — Conditional Logic

Section D — Business-Driven Feature Engineering

Feature engineering bridges raw data and actionable business intelligence. The three derived columns added here are not merely technical exercises — each represents business logic actively used in e-commerce operations: is_high_value for premium customer segmentation and loyalty programs, order_priority for fulfillment resource allocation and SLA definition, and valid_transaction for separating confirmed revenue from at-risk pipeline. The enriched dataset carries significantly higher analytical value and can be consumed directly by Business Intelligence teams without further preprocessing.

New Column Logic Type Business Use
is_high_value net_sales > 1,000,000 Binary Premium customer identification
order_priority 3-tier based on net_sales Multi-class SLA and resource allocation
valid_transaction Based on order_status Binary Revenue forecasting

1.4.1 D.1 — is_high_value Column

Distribution of is_high_value:

  No  Yes 
6871 3084 

1.4.2 D.2 — order_priority Column (NESTED IF)

Distribution of order_priority:

  High    Low Medium 
  3084   5203   1668 

1.4.3 D.3 — valid_transaction Column

Distribution of valid_transaction:

Invalid   Valid 
    472    9483 

1.4.4 D.4 — Display Results and Save

[CSV]   Saved: dataset_final_bersih.csv
[EXCEL] Saved: dataset_final_bersih.xlsx
<div style="margin:16px 0 24px; display:flex; gap:14px; flex-wrap:wrap;">
  <a href="dataset_final_bersih.csv" download
     style="display:inline-flex;align-items:center;gap:8px;
            background:linear-gradient(135deg,#0ea5e9,#6366f1);
            color:#fff;font-weight:700;font-size:14px;
            padding:12px 28px;border-radius:50px;text-decoration:none;
            box-shadow:0 4px 16px rgba(99,102,241,0.35);">
    Download CSV
  </a>
  <a href="dataset_final_bersih.xlsx" download
     style="display:inline-flex;align-items:center;gap:8px;
            background:linear-gradient(135deg,#10b981,#059669);
            color:#fff;font-weight:700;font-size:14px;
            padding:12px 28px;border-radius:50px;text-decoration:none;
            box-shadow:0 4px 16px rgba(16,185,129,0.35);">
    Download Excel
  </a>
</div>

1.5 Section E — Analytical Thinking

Section E — Analytical Thinking and Strategic Decision Intelligence

This is the most consequential stage of the entire pipeline: converting numbers into actionable business narratives. Analysis transcends descriptive statistics when every finding is connected to operational implications and executable recommendations. Four analytical dimensions are explored: platform dominance (for marketing budget allocation), category concentration (for product portfolio risk management), transaction pipeline health (for customer success KPIs), and an executive summary grounded in data.

1.5.1 E.1 — Platform Dominance

Strategic Insight — Platform Dominance and Resource Allocation

Unknown leads with 1,991 transactions (20% market share). This concentration reflects three mutually reinforcing mechanisms: network effects (a mature ecosystem of buyers and sellers creates gravitational pull), high switching costs for sellers who have built reputation and ratings on the platform, and accumulated trust capital through years of reliable post-sale service and dispute resolution.

The gap with second-ranked platforms justifies an asymmetric, data-driven investment strategy: allocate 60–70% of acquisition and retention budget to the dominant platform where ROI is measurable and predictable. Remaining budget diversifies across other platforms to mitigate single-platform dependency risk. Monitor quarterly trends and prepare rebalancing scenarios if the dominant platform’s share erodes by more than 5 percentage points.

1.5.2 E.2 — Category Distribution

Strategic Insight — Category Concentration and Portfolio Risk

Category “Unknown” dominates at 20% of total transactions. From an operational efficiency perspective, this concentration enables supply specialization — deeper vendor relationships, more favorable volume contracts, and more accurate demand forecasting. From a portfolio risk perspective, concentration above 35–40% in a single category creates vulnerability to seasonal demand shifts and supply chain disruptions. The tactical recommendation: drive 15–20% quarterly growth in two adjacent categories with the highest demographic overlap, while defending leadership in Unknown through differentiation strategies that are difficult to replicate.

1.5.3 E.3 — Transaction Status Distribution

Insight — Transaction Pipeline Health

16% of transactions reached Completed status — the true conversion rate of the pipeline. The cancellation rate of 4.7% falls within an acceptable range but warrants ongoing monitoring. Every 1% reduction in cancel rate directly translates to measurable revenue recovery.

Impact formula: 1% reduction in cancel rate × average transaction value = potential revenue recovery per period. This should become a shared KPI for both the customer success and fulfillment teams.

1.5.4 E.4 — Executive Summary

<div class="val">9,955</div>
<div class="lbl">Total Transactions</div>
<div class="val">Rp 11B</div>
<div class="lbl">Gross Revenue</div>
<div class="val">31%</div>
<div class="lbl">High Value Transactions</div>
<div class="val">4.7%</div>
<div class="lbl">Cancel Rate</div>
<div class="val">Rp 1,102,849</div>
<div class="lbl">Avg. per Transaction</div>
<div class="val">Rp 0M</div>
<div class="lbl">Revenue Lost (Cancel)</div>
Strategic Recommendations — 4 Priority Actions

1. Strengthen position on Unknown — Implement platform-exclusive programs: scheduled flash sales timed to peak traffic windows, A/B-tested product listing thumbnails, and bundling features to increase average order value. Target: maintain >50% market share.

2. High-value loyalty program (31% of transactions, disproportionate revenue contribution) — Provide early-sale access, free premium shipping, and a dedicated customer service channel. High-LTV customers are the most valuable assets to protect from churn.

3. Cancel rate reduction mission from 4.7% — Audit the top 3 cancellation reasons via exit surveys, implement proactive status-change notifications, and strengthen delivery SLAs with express shipping options. Target: reduce by 2–3 percentage points within two quarters.

4. Standardize data input processes — Implement real-time validation at the point of entry (frontend validation + backend sanitization) to prevent the format inconsistencies identified during cleaning. Data quality at the source is far less costly than remediation downstream.


2 Mini Project 2 — Web Scraping Intelligence

About Mini Project 2 — Automated Web Data Collection Engineering

Web scraping is a distinct discipline within the data engineering ecosystem: the ability to extract structured data from web interfaces designed for humans, not machines. This project implements 4 distinct scraping techniques from ScrapeThisSite.com — each selected not by preference, but because the way each website delivers its data demands that specific approach. Core competency developed: the ability to diagnose a website’s data delivery architecture (static/dynamic/paginated/API-driven/framed) and select the optimal extraction strategy — a skill of high commercial value since much critical data is accessible only through web interfaces.

# Website Technique Complexity Data
1 Countries of the World Static HTML Low Country, population, area
2 Hockey Teams Pagination Medium NHL teams, wins, losses, win rate
3 Oscar Winning Films AJAX to JSON High Films, year, nominations, awards
4 Turtles All the Way Down iFrame Medium-High Turtle families

2.1 Section A — Data Collection

Section A — Implementation of 4 Distinct Scraping Techniques

Each scraping technique implemented here reflects a fundamentally different engineering challenge. Static HTML trains CSS selector skills and DOM traversal. Pagination requires state management across requests and reliable termination condition detection. AJAX/JSON scraping builds understanding of browser-server communication architecture through network traffic reverse engineering. iFrame scraping demands analysis of layered document structures not visible from the primary source. Mastery of all four techniques covers the majority of web scraping scenarios encountered in industry practice.

2.1.1 A.1 — Countries (Static HTML)

Scraping: Countries of the World (Static HTML)...
URL: https://www.scrapethissite.com/pages/simple/
HTTP Status: 200
Success! 250 countries found
DataFrame: 250 rows x 4 cols | Saved: scraping_countries.csv

2.1.2 A.2 — Hockey Teams (Pagination)

Scraping: Hockey Teams (Pagination)...
  Page 1: 25 teams
  Page 2: 25 teams
  Page 3: 25 teams
  Page 4: 25 teams
  Page 5: 25 teams
  Page 6: 25 teams
  Page 7: 25 teams
  Page 8: 25 teams
  Page 9: 25 teams
  Page 10: 25 teams
  Page 11: 25 teams
  Page 12: 25 teams
  Page 13: 25 teams
  Page 14: 25 teams
  Page 15: 25 teams
  Page 16: 25 teams
  Page 17: 25 teams
  Page 18: 25 teams
  Page 19: 25 teams
  Page 20: 25 teams
  Page 21: 25 teams
  Page 22: 25 teams
  Page 23: 25 teams
  Page 24: 7 teams
Complete! Total: 582 teams
DataFrame: 582 rows x 5 cols | Saved: scraping_hockey.csv

2.1.3 A.3 — Oscar Films (AJAX to JSON)

Scraping: Oscar Winning Films (AJAX -> JSON per year)...
Years: 2010, 2011, 2012, 2013, 2014, 2015
  [2010] Success — 13 films
  [2011] Success — 15 films
  [2012] Success — 15 films
  [2013] Success — 12 films
  [2014] Success — 16 films
  [2015] Success — 16 films

Total: 87 films from 6 years
DataFrame: 87 rows x 5 cols | Saved: scraping_oscar.csv

2.1.4 A.4 — Turtles (iFrame)

Scraping: Turtles All the Way Down...
Primary URL: https://www.scrapethissite.com/pages/frames/?frame=i
HTTP Status (main): 200
14 families found:
  + Carettochelyidae
  + Cheloniidae
  + Chelydridae
  + Dermatemydidae
  + Dermochelyidae
  + Emydidae
  + Geoemydidae
  + Kinosternidae
  + Platysternidae
  + Testudinidae
  + Trionychidae
  + Chelidae
  + Pelomedusidae
  + Podocnemididae

14 families identified.
family_name            common_name                    year     discovered_by
-------------------------------------------------------------------------------- 
  Carettochelyidae       Pig-nosed turtle               1887     Boulenger.
  Cheloniidae            Sea turtles                    1811     Oppel.
  Chelydridae            Snapping turtles               1831     Gray.
  Dermatemydidae         Central American river turtle  1870     Gray.
  Dermochelyidae         Leatherback sea turtle         1843     Fitzinger.
  Emydidae               Pond or water turtles          1815     Rafinesque.
  Geoemydidae            Asian river, leaf, roofed or Asian box turtles 1868     Theobald.
  Kinosternidae          Mud or musk turtles            1857     Agassiz.
  Platysternidae         Big-headed turtle              1869     Gray.
  Testudinidae           Tortoises                      Unknown  Unknown
  Trionychidae           Softshell turtles              1826     Fitzinger.
  Chelidae               Austro-American sideneck turtles 1831     Gray.
  Pelomedusidae          Afro-American sideneck turtles 1868     Cope.
  Podocnemididae         Madagascar big-headed, Big-headed Amazon River turtle and South American sideneck river turtles 1869     Gray.

DataFrame: 14 rows x 4 cols | Saved: scraping_turtles.csv

2.2 Section B — Data Handling

Section B — Quality Audit of 4 Scraped Datasets

All four scraped datasets are audited centrally using a single loop — one function, one iteration, four datasets simultaneously. This reflects the DRY principle: when the same analytical pattern applies to N datasets, use a loop rather than copy-pasting code N times.

2.3 Section C — Data Cleaning

Section C — Systematic Cleaning Pipeline for 4 Datasets

Each dataset is cleaned systematically: text standardization (title case + whitespace trimming), appropriate numeric type conversion per column, context-driven missing value handling, and deduplication. Despite differing schemas, a consistent cleaning pattern is applied through function abstraction.

[Countries] Clean: 250 rows (duplicates removed: 0)
[Hockey] Clean: 582 rows (duplicates removed: 0)
[Oscar] Clean: 87 rows (duplicates removed: 0)
  [OK] family_name — trimmed and filled
  [OK] common_name — trimmed and filled
  [OK] year_discovered — trimmed and filled
  [OK] discovered_by — trimmed and filled
  Duplicates removed: 0
[Turtles] Clean: 14 rows x 4 cols

All clean datasets saved successfully.

2.4 Section D — Conditional Logic

Section D — Data Quality Flagging via Nested IF

A data_status column is added to each scraped dataset as a per-row completeness indicator. This is a form of simple data quality scoring: each row is evaluated against dataset-specific completeness criteria rather than a generic universal standard.

2.5 Section E — Analytical Thinking

Section E — Evaluation of Scraping Techniques and Substantive Insights

Two analytical layers are executed here. The first is meta-analytic: a comparative evaluation of the four scraping techniques across implementation complexity, fragility to website changes, operational risk (rate limiting, IP blocking), and optimal use cases — building a decision framework for future technique selection. The second is substantive: extracting meaningful insights from the collected data, demonstrating that the scraping process has generated knowledge that was not previously available.

2.5.1 E.1 — Comparison of 4 Scraping Techniques

Key Insight — Technique Selection is an Engineering Requirement, Not a Preference

Static HTML scraping is the most reliable technique: no JavaScript dependency, no race conditions, and a single HTTP request suffices. It should always be attempted first — success eliminates the need for more complex approaches, and failure is a strong signal that the target site uses dynamic rendering. For AJAX endpoints, the primary risk is that hidden endpoints discovered via DevTools are undocumented and can change without notice, causing scrapers to fail silently. Mitigation requires periodic monitoring and robust error alerting in production pipelines.

2.5.2 E.2 — Insights from Scraped Data

<div class="val">250</div>
<div class="lbl">Countries</div>
<div class="val">582</div>
<div class="lbl">NHL Hockey Teams</div>
<div class="val">87</div>
<div class="lbl">Oscar Films (2010-15)</div>
<div class="val">14</div>
<div class="lbl">Turtle Families</div>
<div class="val">China</div>
<div class="lbl">Most Populous Country</div>
<div class="val">Detroit Red Wings</div>
<div class="lbl">Highest Win Rate Team</div>
Key Findings Across 4 Scraped Datasets

[Countries — Geography and Demography] China is the most populous country at 1,330,044,000 people, while Russia holds the largest land area. The fact that the most populous country is not the largest by area reflects a highly uneven global population distribution shaped by historical, climatic, and economic factors — with direct implications for infrastructure burden, market opportunity, and environmental pressure.

[NHL Hockey — Team Performance] Detroit Red Wings recorded the highest win rate at 75.6%, significantly above the league average of 45.9%. In sports analytics, win rate is an efficiency metric — high win-rate teams demonstrate consistency, sound tactical systems, and roster depth, making it a more meaningful benchmark than raw total wins which can be skewed by games played.

[Oscar Films 2010-2015 — Film Industry]Gravity” led with 7 wins. With an average of 3.9 nominations per film but only 6.9% earning Best Picture, the data reveals the Academy’s high selectivity: many nominations do not guarantee a win, reflecting the intense competition and inherent subjectivity of creative work evaluation.

[Turtles — Biodiversity] 14 turtle families were catalogued — a structured reference relevant to reptile conservation research. Scraping biodiversity data from authoritative sources can support species protection programs and public education initiatives.


3 References


DQotLS0NCnRpdGxlOiAiTWlkdGVybSBFeGFtaW5hdGlvbiDigJQgRGF0YSBTY2llbmNlIFByb2dyYW1taW5nIEkiDQpzdWJ0aXRsZTogIk1pbmkgUHJvamVjdDogRS1Db21tZXJjZSBEYXRhIFBpcGVsaW5lICYgV2ViIFNjcmFwaW5nIEludGVsbGlnZW5jZSINCmF1dGhvcjogDQotICJBbmRyZSDigJQgTklNIDUyMjUwMDY1Ig0KLSAiUmVmYW50YW51ciBIdXNudWwgSGFxaWIg4oCUIE5JTSA1MjI1MDA1MiINCi0gIk5haWxhIFN5YWhyYW5pIFB1dHJpIOKAlCBOSU0gNTIyNTAwNzAiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQoNCm91dHB1dDoNCiAgcm1kZm9ybWF0czo6cm9ib2Jvb2s6DQogICAgaGlnaGxpZ2h0OiBrYXRlDQogICAgc2VsZl9jb250YWluZWQ6IHRydWUNCiAgICB0aHVtYm5haWxzOiB0cnVlDQogICAgbGlnaHRib3g6IHRydWUNCiAgICBnYWxsZXJ5OiB0cnVlDQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgZGZfcHJpbnQ6ICJkZWZhdWx0Ig0KICAgIGNvZGVfZm9sZGluZzogInNob3ciDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRvY19kZXB0aDogMw0KICAgIHVzZV9ib29rZG93bjogdHJ1ZQ0KICAgIGNzczogZGFzaGJvYXJkX3N0eWxlLmNzcw0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBlY2hvICAgID0gRkFMU0UsDQogIHdhcm5pbmcgPSBGQUxTRSwNCiAgbWVzc2FnZSA9IEZBTFNFLA0KICBjb21tZW50ID0gIiINCikNCm9wdGlvbnMoaHRtbHRvb2xzLnByZXNlcnZlLnJhdyA9IFRSVUUpDQpgYGANCg0KYGBge3IgbG9hZC1saWJyYXJpZXMsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShqc29ubGl0ZSkNCmxpYnJhcnkoeG1sMikNCmxpYnJhcnkob3Blbnhsc3gpDQpsaWJyYXJ5KGtuaXRyKQ0KbGlicmFyeShrYWJsZUV4dHJhKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoaHR0cikNCmxpYnJhcnkocnZlc3QpDQpsaWJyYXJ5KGh0bWx0b29scykNCmBgYA0KDQpgYGB7Y3NzLCBlY2hvPUZBTFNFfQ0KLyog4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQDQogICBHTE9CQUwgU1RZTEVTIOKAlCBDT1ZFUiwgQ0FSRFMsIEJPWEVTDQrilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZAgKi8NCg0KLyogSGVybyBDb3ZlciAqLw0KLmhlcm8tY292ZXIgew0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCAjMGQxYjJhIDAlLCAjMWIzYTVjIDUwJSwgIzBkMWIyYSAxMDAlKTsNCiAgYm9yZGVyLXJhZGl1czogMThweDsNCiAgcGFkZGluZzogNDhweCAzMnB4IDQwcHg7DQogIG1hcmdpbjogMTJweCAwIDMycHg7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgcG9zaXRpb246IHJlbGF0aXZlOw0KICBvdmVyZmxvdzogaGlkZGVuOw0KICBib3gtc2hhZG93OiAwIDIwcHggNjBweCByZ2JhKDAsMCwwLDAuNCk7DQp9DQouaGVyby1jb3Zlcjo6YmVmb3JlIHsNCiAgY29udGVudDogJyc7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgdG9wOiAtNjBweDsgbGVmdDogLTYwcHg7DQogIHdpZHRoOiAyMjBweDsgaGVpZ2h0OiAyMjBweDsNCiAgYmFja2dyb3VuZDogcmFkaWFsLWdyYWRpZW50KGNpcmNsZSwgcmdiYSg1NiwxODksMjQ4LDAuMTgpIDAlLCB0cmFuc3BhcmVudCA3MCUpOw0KICBib3JkZXItcmFkaXVzOiA1MCU7DQp9DQouaGVyby1jb3Zlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAnJzsNCiAgcG9zaXRpb246IGFic29sdXRlOw0KICBib3R0b206IC01MHB4OyByaWdodDogLTUwcHg7DQogIHdpZHRoOiAyMDBweDsgaGVpZ2h0OiAyMDBweDsNCiAgYmFja2dyb3VuZDogcmFkaWFsLWdyYWRpZW50KGNpcmNsZSwgcmdiYSg5OSwxMDIsMjQxLDAuMTgpIDAlLCB0cmFuc3BhcmVudCA3MCUpOw0KICBib3JkZXItcmFkaXVzOiA1MCU7DQp9DQouaGVyby1iYWRnZSB7DQogIGRpc3BsYXk6IGlubGluZS1ibG9jazsNCiAgYmFja2dyb3VuZDogcmdiYSg1NiwxODksMjQ4LDAuMTUpOw0KICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDU2LDE4OSwyNDgsMC40KTsNCiAgY29sb3I6ICMzOGJkZjg7DQogIGZvbnQtc2l6ZTogMTFweDsNCiAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgbGV0dGVyLXNwYWNpbmc6IDIuNXB4Ow0KICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOw0KICBwYWRkaW5nOiA2cHggMThweDsNCiAgYm9yZGVyLXJhZGl1czogNTBweDsNCiAgbWFyZ2luLWJvdHRvbTogMjBweDsNCn0NCi5oZXJvLXRpdGxlIHsNCiAgZm9udC1zaXplOiAyLjZlbTsNCiAgZm9udC13ZWlnaHQ6IDkwMDsNCiAgY29sb3I6ICNmZmZmZmY7DQogIGxpbmUtaGVpZ2h0OiAxLjE1Ow0KICBtYXJnaW46IDAgMCAxMHB4Ow0KICBsZXR0ZXItc3BhY2luZzogLTAuNXB4Ow0KICB0ZXh0LXNoYWRvdzogMCAycHggMjBweCByZ2JhKDU2LDE4OSwyNDgsMC4zKTsNCn0NCi5oZXJvLXRpdGxlIHNwYW4gew0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoOTBkZWcsICMzOGJkZjgsICM4MThjZjgpOw0KICAtd2Via2l0LWJhY2tncm91bmQtY2xpcDogdGV4dDsNCiAgLXdlYmtpdC10ZXh0LWZpbGwtY29sb3I6IHRyYW5zcGFyZW50Ow0KICBiYWNrZ3JvdW5kLWNsaXA6IHRleHQ7DQp9DQouaGVyby1zdWJ0aXRsZSB7DQogIGZvbnQtc2l6ZTogMWVtOw0KICBjb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwwLjY1KTsNCiAgbWFyZ2luOiAwIDAgMzJweDsNCiAgZm9udC1zdHlsZTogaXRhbGljOw0KICBsZXR0ZXItc3BhY2luZzogMC4zcHg7DQp9DQouaGVyby1kaXZpZGVyIHsNCiAgd2lkdGg6IDYwcHg7DQogIGhlaWdodDogM3B4Ow0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoOTBkZWcsICMzOGJkZjgsICM4MThjZjgpOw0KICBib3JkZXItcmFkaXVzOiA0cHg7DQogIG1hcmdpbjogMCBhdXRvIDMycHg7DQp9DQoNCi8qIFRlYW0gQ2FyZHMgKi8NCi50ZWFtLWdyaWQgew0KICBkaXNwbGF5OiBmbGV4Ow0KICBmbGV4LXdyYXA6IHdyYXA7DQogIGdhcDogMjJweDsNCiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgei1pbmRleDogMTsNCn0NCi50ZWFtLWNhcmQgew0KICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuMDYpOw0KICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMTIpOw0KICBib3JkZXItcmFkaXVzOiAxNnB4Ow0KICBwYWRkaW5nOiAyMHB4IDE4cHggMThweDsNCiAgd2lkdGg6IDE3MHB4Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGJhY2tkcm9wLWZpbHRlcjogYmx1cigxMHB4KTsNCiAgdHJhbnNpdGlvbjogdHJhbnNmb3JtIDAuMjVzIGVhc2UsIGJveC1zaGFkb3cgMC4yNXMgZWFzZTsNCiAgYm94LXNoYWRvdzogMCA0cHggMjRweCByZ2JhKDAsMCwwLDAuMjUpOw0KfQ0KLnRlYW0tY2FyZDpob3ZlciB7DQogIHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtNnB4KTsNCiAgYm94LXNoYWRvdzogMCAxNnB4IDQwcHggcmdiYSg1NiwxODksMjQ4LDAuMik7DQogIGJvcmRlci1jb2xvcjogcmdiYSg1NiwxODksMjQ4LDAuNCk7DQp9DQouZnJhbWUtcGhvdG8gew0KICBwb3NpdGlvbjogcmVsYXRpdmU7DQogIHdpZHRoOiAxMTBweDsNCiAgaGVpZ2h0OiAxMzVweDsNCiAgbWFyZ2luOiAwIGF1dG8gMTRweDsNCn0NCi5mcmFtZS1waG90bzo6YmVmb3JlIHsNCiAgY29udGVudDogJyc7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgaW5zZXQ6IC00cHg7DQogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzOGJkZjgsICM4MThjZjgsICNmNDcyYjYpOw0KICBib3JkZXItcmFkaXVzOiAxNHB4Ow0KICB6LWluZGV4OiAwOw0KICBhbmltYXRpb246IGJvcmRlclNwaW4gNHMgbGluZWFyIGluZmluaXRlOw0KfQ0KQGtleWZyYW1lcyBib3JkZXJTcGluIHsNCiAgMCUgICB7IGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzOGJkZjgsICM4MThjZjgsICNmNDcyYjYpOyB9DQogIDMzJSAgeyBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMjI1ZGVnLCAjODE4Y2Y4LCAjZjQ3MmI2LCAjMzhiZGY4KTsgfQ0KICA2NiUgIHsgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDMxNWRlZywgI2Y0NzJiNiwgIzM4YmRmOCwgIzgxOGNmOCk7IH0NCiAgMTAwJSB7IGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzOGJkZjgsICM4MThjZjgsICNmNDcyYjYpOyB9DQp9DQouZnJhbWUtcGhvdG86OmFmdGVyIHsNCiAgY29udGVudDogJyc7DQogIHBvc2l0aW9uOiBhYnNvbHV0ZTsNCiAgaW5zZXQ6IC00cHg7DQogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsICMzOGJkZjgsICM4MThjZjgsICNmNDcyYjYpOw0KICBib3JkZXItcmFkaXVzOiAxNHB4Ow0KICB6LWluZGV4OiAwOw0KICBmaWx0ZXI6IGJsdXIoOHB4KTsNCiAgb3BhY2l0eTogMC41Ow0KfQ0KLmZyYW1lLXBob3RvIGltZyB7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgd2lkdGg6IDExMHB4Ow0KICBoZWlnaHQ6IDEzNXB4Ow0KICBvYmplY3QtZml0OiBjb3ZlcjsNCiAgb2JqZWN0LXBvc2l0aW9uOiB0b3AgY2VudGVyOw0KICBib3JkZXItcmFkaXVzOiAxMXB4Ow0KICBkaXNwbGF5OiBibG9jazsNCiAgei1pbmRleDogMTsNCiAgYm9yZGVyOiAzcHggc29saWQgIzBkMWIyYTsNCn0NCi50ZWFtLW5hbWUgew0KICBmb250LXNpemU6IDEzcHg7DQogIGZvbnQtd2VpZ2h0OiA3MDA7DQogIGNvbG9yOiAjZjBmOWZmOw0KICBtYXJnaW46IDAgMCA0cHg7DQogIGxpbmUtaGVpZ2h0OiAxLjM7DQp9DQoudGVhbS1uaW0gew0KICBmb250LXNpemU6IDExcHg7DQogIGNvbG9yOiAjMzhiZGY4Ow0KICBmb250LXdlaWdodDogNjAwOw0KICBsZXR0ZXItc3BhY2luZzogMC41cHg7DQogIGJhY2tncm91bmQ6IHJnYmEoNTYsMTg5LDI0OCwwLjEpOw0KICBwYWRkaW5nOiAycHggMTBweDsNCiAgYm9yZGVyLXJhZGl1czogMjBweDsNCiAgZGlzcGxheTogaW5saW5lLWJsb2NrOw0KfQ0KDQovKiBIZXJvIE1ldGEgKi8NCi5oZXJvLW1ldGEgew0KICBkaXNwbGF5OiBmbGV4Ow0KICBnYXA6IDIwcHg7DQogIGp1c3RpZnktY29udGVudDogY2VudGVyOw0KICBmbGV4LXdyYXA6IHdyYXA7DQogIG1hcmdpbi10b3A6IDI4cHg7DQogIHBvc2l0aW9uOiByZWxhdGl2ZTsNCiAgei1pbmRleDogMTsNCn0NCi5tZXRhLWNoaXAgew0KICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuMDcpOw0KICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMTUpOw0KICBjb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwwLjc1KTsNCiAgZm9udC1zaXplOiAxMnB4Ow0KICBwYWRkaW5nOiA3cHggMTZweDsNCiAgYm9yZGVyLXJhZGl1czogNTBweDsNCiAgZGlzcGxheTogZmxleDsNCiAgYWxpZ24taXRlbXM6IGNlbnRlcjsNCiAgZ2FwOiA2cHg7DQp9DQoubWV0YS1jaGlwIHN0cm9uZyB7IGNvbG9yOiAjZmZmOyB9DQoNCi8qIEluZm8gQm94ICovDQouaW5mby1ib3ggew0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCByZ2JhKDE0LDE2NSwyMzMsMC4wOCksIHJnYmEoOTksMTAyLDI0MSwwLjA4KSk7DQogIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoNTYsMTg5LDI0OCwwLjI1KTsNCiAgYm9yZGVyLWxlZnQ6IDRweCBzb2xpZCAjMzhiZGY4Ow0KICBib3JkZXItcmFkaXVzOiAxMHB4Ow0KICBwYWRkaW5nOiAxOHB4IDIwcHg7DQogIG1hcmdpbjogMThweCAwOw0KfQ0KLmluZm8tYm94IC5ib3gtdGl0bGUgew0KICBmb250LXdlaWdodDogNzAwOw0KICBjb2xvcjogIzM4YmRmODsNCiAgZm9udC1zaXplOiAwLjg4ZW07DQogIGxldHRlci1zcGFjaW5nOiAwLjVweDsNCiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KLyogSW5zaWdodCBCb3ggKi8NCi5pbnNpZ2h0LWJveCB7DQogIGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcsIHJnYmEoMTYsMTg1LDEyOSwwLjA4KSwgcmdiYSg1LDE1MCwxMDUsMC4wNikpOw0KICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDE2LDE4NSwxMjksMC4yNSk7DQogIGJvcmRlci1sZWZ0OiA0cHggc29saWQgIzEwYjk4MTsNCiAgYm9yZGVyLXJhZGl1czogMTBweDsNCiAgcGFkZGluZzogMThweCAyMHB4Ow0KICBtYXJnaW46IDE4cHggMDsNCn0NCi5pbnNpZ2h0LWJveCAuYm94LXRpdGxlIHsNCiAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgY29sb3I6ICMxMGI5ODE7DQogIGZvbnQtc2l6ZTogMC44OGVtOw0KICBsZXR0ZXItc3BhY2luZzogMC41cHg7DQogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCi8qIFdhcm5pbmcgQm94ICovDQoud2FybmluZy1ib3ggew0KICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCByZ2JhKDI0NSwxNTgsMTEsMC4wOCksIHJnYmEoMjE3LDExOSw2LDAuMDYpKTsNCiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNDUsMTU4LDExLDAuMyk7DQogIGJvcmRlci1sZWZ0OiA0cHggc29saWQgI2Y1OWUwYjsNCiAgYm9yZGVyLXJhZGl1czogMTBweDsNCiAgcGFkZGluZzogMThweCAyMHB4Ow0KICBtYXJnaW46IDE4cHggMDsNCn0NCi53YXJuaW5nLWJveCAuYm94LXRpdGxlIHsNCiAgZm9udC13ZWlnaHQ6IDcwMDsNCiAgY29sb3I6ICNmNTllMGI7DQogIGZvbnQtc2l6ZTogMC44OGVtOw0KICBsZXR0ZXItc3BhY2luZzogMC41cHg7DQogIHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCi8qIFN0YXQgR3JpZCAqLw0KLnN0YXQtZ3JpZCB7DQogIGRpc3BsYXk6IGZsZXg7DQogIGZsZXgtd3JhcDogd3JhcDsNCiAgZ2FwOiAxNnB4Ow0KICBtYXJnaW46IDIwcHggMDsNCn0NCi5zdGF0LWNhcmQgew0KICBmbGV4OiAxOw0KICBtaW4td2lkdGg6IDE0MHB4Ow0KICBib3JkZXItcmFkaXVzOiAxMnB4Ow0KICBwYWRkaW5nOiAxOHB4IDE0cHg7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwwLjA4KTsNCn0NCi5zdGF0LWNhcmQuYmx1ZSAgIHsgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZyxyZ2JhKDU5LDEyMywyNTUsMC4xNSkscmdiYSg1OSwxMjMsMjU1LDAuMDYpKTsgYm9yZGVyLWNvbG9yOnJnYmEoNTksMTIzLDI1NSwwLjMpOyB9DQouc3RhdC1jYXJkLnRlYWwgICB7IGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcscmdiYSgyMCwxODQsMTY2LDAuMTUpLHJnYmEoMjAsMTg0LDE2NiwwLjA2KSk7IGJvcmRlci1jb2xvcjpyZ2JhKDIwLDE4NCwxNjYsMC4zKTsgfQ0KLnN0YXQtY2FyZC5lbWVyYWxkeyBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLHJnYmEoMTYsMTg1LDEyOSwwLjE1KSxyZ2JhKDE2LDE4NSwxMjksMC4wNikpOyBib3JkZXItY29sb3I6cmdiYSgxNiwxODUsMTI5LDAuMyk7IH0NCi5zdGF0LWNhcmQucHVycGxlIHsgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDEzNWRlZyxyZ2JhKDEzOSw5MiwyNDYsMC4xNSkscmdiYSgxMzksOTIsMjQ2LDAuMDYpKTsgYm9yZGVyLWNvbG9yOnJnYmEoMTM5LDkyLDI0NiwwLjMpOyB9DQouc3RhdC1jYXJkLmFtYmVyICB7IGJhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudCgxMzVkZWcscmdiYSgyNDUsMTU4LDExLDAuMTUpLHJnYmEoMjQ1LDE1OCwxMSwwLjA2KSk7IGJvcmRlci1jb2xvcjpyZ2JhKDI0NSwxNTgsMTEsMC4zKTsgfQ0KLnN0YXQtY2FyZC5yb3NlICAgeyBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLHJnYmEoMjQ0LDYzLDk0LDAuMTUpLHJnYmEoMjQ0LDYzLDk0LDAuMDYpKTsgIGJvcmRlci1jb2xvcjpyZ2JhKDI0NCw2Myw5NCwwLjMpOyB9DQouc3RhdC1jYXJkIC52YWwgeyBmb250LXNpemU6IDEuN2VtOyBmb250LXdlaWdodDogODAwOyBsaW5lLWhlaWdodDoxLjE7IG1hcmdpbi1ib3R0b206NnB4OyB9DQouc3RhdC1jYXJkIC5sYmwgeyBmb250LXNpemU6IDExcHg7IG9wYWNpdHk6IDAuNzsgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsgbGV0dGVyLXNwYWNpbmc6IDAuOHB4OyB9DQoNCi8qIEZvb3RlciAqLw0KLmZvb3Rlci1ub3RlIHsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBwYWRkaW5nOiAxNnB4Ow0KICBtYXJnaW4tdG9wOiAzMnB4Ow0KICBmb250LXNpemU6IDAuODVlbTsNCiAgb3BhY2l0eTogMC42Ow0KICBib3JkZXItdG9wOiAxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwwLjEpOw0KfQ0KYGBgDQoNCmBgYHtyIGNvdmVyLWh0bWwsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KaHRtbF9jb3ZlciA8LSBwYXN0ZTAoDQonPGRpdiBjbGFzcz0iaGVyby1jb3ZlciI+JywNCic8ZGl2IGNsYXNzPSJoZXJvLWJhZGdlIj4mIzEwMDIyOyBEYXRhIFNjaWVuY2UgUHJvZ3JhbW1pbmcgSSAmbWRhc2g7IENsYXNzIEI8L2Rpdj4nLA0KJzxkaXYgY2xhc3M9Imhlcm8tdGl0bGUiPk1pZHRlcm0gPHNwYW4+RGF0YSBQcm9ncmFtbWluZzwvc3Bhbj48L2Rpdj4nLA0KJzxwIGNsYXNzPSJoZXJvLXN1YnRpdGxlIj5FLUNvbW1lcmNlIERhdGEgUGlwZWxpbmUgJmFtcDsgV2ViIFNjcmFwaW5nIEludGVsbGlnZW5jZTwvcD4nLA0KJzxkaXYgY2xhc3M9Imhlcm8tZGl2aWRlciI+PC9kaXY+JywNCic8ZGl2IGNsYXNzPSJ0ZWFtLWdyaWQiPicsDQoNCiAgJzxkaXYgY2xhc3M9InRlYW0tY2FyZCI+JywNCiAgJzxkaXYgY2xhc3M9ImZyYW1lLXBob3RvIj4nLA0KICAnPGltZyBzcmM9IkZvdG8xLmpwZWciIGFsdD0iQW5kcmUiIC8+JywNCiAgJzwvZGl2PicsDQogICc8ZGl2IGNsYXNzPSJ0ZWFtLW5hbWUiPkFuZHJlPC9kaXY+JywNCiAgJzxkaXYgY2xhc3M9InRlYW0tbmltIj41MjI1MDA2NTwvZGl2PicsDQogICc8L2Rpdj4nLA0KDQogICc8ZGl2IGNsYXNzPSJ0ZWFtLWNhcmQiPicsDQogICc8ZGl2IGNsYXNzPSJmcmFtZS1waG90byI+JywNCiAgJzxpbWcgc3JjPSJGb3RvMi5qcGVnIiBhbHQ9IlJlZmFudGFudXIgSHVzbnVsIEhhcWliIiAvPicsDQogICc8L2Rpdj4nLA0KICAnPGRpdiBjbGFzcz0idGVhbS1uYW1lIj5SZWZhbnRhbnVyIEh1c251bCBIYXFpYjwvZGl2PicsDQogICc8ZGl2IGNsYXNzPSJ0ZWFtLW5pbSI+NTIyNTAwNTI8L2Rpdj4nLA0KICAnPC9kaXY+JywNCg0KICAnPGRpdiBjbGFzcz0idGVhbS1jYXJkIj4nLA0KICAnPGRpdiBjbGFzcz0iZnJhbWUtcGhvdG8iPicsDQogICc8aW1nIHNyYz0iRm90bzMuanBlZyIgYWx0PSJOYWlsYSBTeWFocmFuaSBQdXRyaSIgLz4nLA0KICAnPC9kaXY+JywNCiAgJzxkaXYgY2xhc3M9InRlYW0tbmFtZSI+TmFpbGEgU3lhaHJhbmkgUHV0cmk8L2Rpdj4nLA0KICAnPGRpdiBjbGFzcz0idGVhbS1uaW0iPjUyMjUwMDcwPC9kaXY+JywNCiAgJzwvZGl2PicsDQoNCic8L2Rpdj4nLA0KJzxkaXYgY2xhc3M9Imhlcm8tbWV0YSI+JywNCic8ZGl2IGNsYXNzPSJtZXRhLWNoaXAiPiYjMTI3ODkxOyA8c3Ryb25nPkRhdGEgU2NpZW5jZSBQcm9ncmFtPC9zdHJvbmc+PC9kaXY+JywNCic8ZGl2IGNsYXNzPSJtZXRhLWNoaXAiPiYjMTI4MTk3OyA8c3Ryb25nPjIwMjYtMDQtMjY8L3N0cm9uZz48L2Rpdj4nLA0KJzxkaXYgY2xhc3M9Im1ldGEtY2hpcCI+JiMxMjgyMDI7IDxzdHJvbmc+MiBNaW5pIFByb2plY3RzPC9zdHJvbmc+PC9kaXY+JywNCic8L2Rpdj4nLA0KJzwvZGl2PicNCikNCmNhdChodG1sX2NvdmVyKQ0KYGBgDQoNCiMgTWluaSBQcm9qZWN0IDEg4oCUIEUtQ29tbWVyY2UgRGF0YSBQaXBlbGluZSB7I21pbmktcHJvamVjdC0xfQ0KDQo8ZGl2IGNsYXNzPSJpbmZvLWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+QWJvdXQgTWluaSBQcm9qZWN0IDEg4oCUIEUtQ29tbWVyY2UgRGF0YSBQaXBlbGluZTwvZGl2Pg0KICA8cD5UaGlzIG1pbmkgcHJvamVjdCBzaW11bGF0ZXMgYSByZWFsLXdvcmxkIGRhdGEgZW5naW5lZXJpbmcgc2NlbmFyaW86IGludGVncmF0aW5nIGUtY29tbWVyY2UgdHJhbnNhY3Rpb24gZGF0YSBmcm9tIDxzdHJvbmc+NSBkaWZmZXJlbnQgZmlsZSBmb3JtYXRzPC9zdHJvbmc+IChDU1YsIEV4Y2VsLCBKU09OLCBUWFQsIFhNTCkgaW50byBhIHNpbmdsZSBjbGVhbiwgYW5hbHlzaXMtcmVhZHkgZGF0YXNldC4gVGhlIHBpcGVsaW5lIGZvbGxvd3MgcHJvZHVjdGlvbi1ncmFkZSBwcmluY2lwbGVzIOKAlCBlYWNoIHN0YWdlIGlzIGRvY3VtZW50ZWQsIHJlcHJvZHVjaWJsZSwgYW5kIGRlc2lnbmVkIHRvIGhhbmRsZSBlZGdlIGNhc2VzIGdyYWNlZnVsbHkuIFRoZSBmaW5hbCBvdXRwdXQgaXMgYSBzdHJ1Y3R1cmVkIGRhdGFzZXQgd2l0aCBidXNpbmVzcy1kcml2ZW4gZmVhdHVyZSBlbmdpbmVlcmluZyByZWFkeSBmb3IgZXhlY3V0aXZlIHJlcG9ydGluZywgQkkgZGFzaGJvYXJkcywgb3IgcHJlZGljdGl2ZSBtb2RlbGluZy48L3A+DQo8L2Rpdj4NCg0KIyMgU2VjdGlvbiBBIOKAlCBEYXRhIENvbGxlY3Rpb24NCg0KPGRpdiBjbGFzcz0iaW5mby1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlNlY3Rpb24gQSDigJQgQXV0b21hdGVkIE11bHRpLUZvcm1hdCBEYXRhIEluZ2VzdGlvbjwvZGl2Pg0KICA8cD5UaGUgcHJpbWFyeSBvYmplY3RpdmUgaXMgdG8gYnVpbGQgYSBmdWxseSBhdXRvbWF0ZWQsIGZvcm1hdC1hZ25vc3RpYyBkYXRhIGluZ2VzdGlvbiBwaXBlbGluZS4gUmF0aGVyIHRoYW4gd3JpdGluZyBzZXBhcmF0ZSBjb2RlIGZvciBlYWNoIGZpbGUsIGEgc2luZ2xlIGxvb3Agc3RydWN0dXJlIGhhbmRsZXMgYWxsIGZvcm1hdHMgdGhyb3VnaCBjb25kaXRpb24tYmFzZWQgZGlzcGF0Y2gg4oCUIHJlZmxlY3RpbmcgdGhlIHByaW5jaXBsZXMgb2YgQ2xlYW4gQ29kZSBhbmQgRFJZIChEb24ndCBSZXBlYXQgWW91cnNlbGYpLiBFdmVyeSBmaWxlIGlzIHZlcmlmaWVkIGZvciBhdmFpbGFiaWxpdHkgYmVmb3JlIHJlYWRpbmcsIHRoZW4gbWVyZ2VkIGludG8gYSB1bmlmaWVkIGRhdGFzZXQgd2l0aCBwcm92ZW5hbmNlIG1ldGFkYXRhIGVuYWJsaW5nIGEgZnVsbCBhdWRpdCB0cmFpbCBiYWNrIHRvIHRoZSBvcmlnaW5hbCBzb3VyY2Ugb2YgZWFjaCByb3cuPC9wPg0KPC9kaXY+DQoNCiMjIyBBLjEg4oCUIEZpbGUgSW52ZW50b3J5IGFuZCBBdmFpbGFiaWxpdHkgQ2hlY2sNCg0KYGBge3IgYTEtZGFmdGFyLWZpbGV9DQpmaWxlX2xpc3QgPC0gbGlzdCgNCiAgbGlzdChuYW1hID0gIk1pZHRlcm1fRXhhbV9DbGFzc3Jvb20uY3N2IiwgIGZvcm1hdCA9ICJDU1YiKSwNCiAgbGlzdChuYW1hID0gIk1pZHRlcm1fRXhhbV9DbGFzc3Jvb20ueGxzeCIsIGZvcm1hdCA9ICJFeGNlbCIpLA0KICBsaXN0KG5hbWEgPSAiTWlkdGVybV9FeGFtX0NsYXNzcm9vbS5qc29uIiwgZm9ybWF0ID0gIkpTT04iKSwNCiAgbGlzdChuYW1hID0gIk1pZHRlcm1fRXhhbV9DbGFzc3Jvb20udHh0IiwgIGZvcm1hdCA9ICJUWFQiKSwNCiAgbGlzdChuYW1hID0gIk1pZHRlcm1fRXhhbV9DbGFzc3Jvb20ueG1sIiwgIGZvcm1hdCA9ICJYTUwiKQ0KKQ0KDQpzdGF0dXNfZGYgPC0gZGF0YS5mcmFtZSgNCiAgTm8gICAgID0gc2VxX2Fsb25nKGZpbGVfbGlzdCksDQogIEZpbGUgICA9IHNhcHBseShmaWxlX2xpc3QsIGZ1bmN0aW9uKGYpIGYkbmFtYSksDQogIEZvcm1hdCA9IHNhcHBseShmaWxlX2xpc3QsIGZ1bmN0aW9uKGYpIGYkZm9ybWF0KSwNCiAgU3RhdHVzID0gc2FwcGx5KGZpbGVfbGlzdCwgZnVuY3Rpb24oZikgew0KICAgIGlmIChmaWxlLmV4aXN0cyhmJG5hbWEpKSAiRm91bmQiIGVsc2UgIk5vdCBGb3VuZCIgICMgUkVRVUlSRUQgSUYNCiAgfSksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQpkYXRhdGFibGUoc3RhdHVzX2RmLA0KICAgICAgICAgIGNhcHRpb24gICAgID0gIkZpbGUgQXZhaWxhYmlsaXR5IOKAlCBEYXRhc2V0IFNvdXJjZSBGaWxlcyIsDQogICAgICAgICAgZXh0ZW5zaW9ucyAgPSAnQnV0dG9ucycsDQogICAgICAgICAgb3B0aW9ucyAgICAgPSBsaXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD0xMCwgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgcm93bmFtZXMgICAgPSBGQUxTRSkgJT4lDQogIGZvcm1hdFN0eWxlKCJTdGF0dXMiLA0KICAgIGNvbG9yID0gc3R5bGVFcXVhbChjKCJGb3VuZCIsIk5vdCBGb3VuZCIpLCBjKCIjMTBiOTgxIiwiI2Y0M2Y1ZSIpKSwNCiAgICBmb250V2VpZ2h0ID0gImJvbGQiKQ0KYGBgDQoNCiMjIyBBLjIg4oCUIEN1c3RvbSBYTUwgUGFyc2VyIEZ1bmN0aW9uDQoNCmBgYHtyIGEyLWZ1bmdzaS14bWx9DQpiYWNhX3htbCA8LSBmdW5jdGlvbihwYXRoKSB7DQogIGRvYyAgIDwtIHJlYWRfeG1sKHBhdGgpDQogIG5vZGVzIDwtIHhtbF9jaGlsZHJlbihkb2MpDQoNCiAgIyBSRVFVSVJFRCBMT09QOiBwYXJzZSBlYWNoIFhNTCBub2RlIGludG8gYSBkYXRhIHJvdw0KICByb3dzIDwtIGxhcHBseShub2RlcywgZnVuY3Rpb24obm9kZSkgew0KICAgIGFuYWsgIDwtIHhtbF9jaGlsZHJlbihub2RlKQ0KICAgIHZhbHMgIDwtIHhtbF90ZXh0KGFuYWspDQogICAgbmFtZXModmFscykgPC0geG1sX25hbWUoYW5haykNCiAgICBhcy5saXN0KHZhbHMpDQogIH0pDQogIGJpbmRfcm93cyhyb3dzKQ0KfQ0KDQpjYXQoImJhY2FfeG1sKCkgZGVmaW5lZCBhbmQgcmVhZHkuXG4iKQ0KYGBgDQoNCiMjIyBBLjMg4oCUIFJFUVVJUkVEIExPT1A6IFJlYWQgQWxsIEZpbGVzDQoNCmBgYHtyIGEzLWJhY2Etc2VtdWEtZmlsZX0NCmRhdGFmcmFtZXMgPC0gbGlzdCgpDQoNCmZvciAoZiBpbiBmaWxlX2xpc3QpIHsgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIExPT1ANCiAgbmFtYSA8LSBmJG5hbWE7IGZtdCA8LSBmJGZvcm1hdA0KDQogIGlmICghZmlsZS5leGlzdHMobmFtYSkpIHsgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICAgIGNhdChzcHJpbnRmKCIgIFtTS0lQXSAlcyBub3QgZm91bmRcbiIsIG5hbWEpKQ0KICAgIG5leHQNCiAgfQ0KDQogIGRmIDwtIHRyeUNhdGNoKHsNCiAgICBpZiAgICAgIChmbXQgPT0gIkNTViIpICAgcmVhZF9jc3YobmFtYSwgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkNCiAgICBlbHNlIGlmIChmbXQgPT0gIkV4Y2VsIikgcmVhZF9leGNlbChuYW1hKSAgICAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgSUYtRUxTRQ0KICAgIGVsc2UgaWYgKGZtdCA9PSAiSlNPTiIpICBhc190aWJibGUoZnJvbUpTT04obmFtYSwgZmxhdHRlbiA9IFRSVUUpKQ0KICAgIGVsc2UgaWYgKGZtdCA9PSAiVFhUIikgICByZWFkX3RzdihuYW1hLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KICAgIGVsc2UgaWYgKGZtdCA9PSAiWE1MIikgICBiYWNhX3htbChuYW1hKQ0KICAgIGVsc2UgICAgICAgICAgICAgICAgICAgICBOVUxMDQogIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgeyBjYXQoc3ByaW50ZigiICBbRVJST1JdICVzXG4iLCBlJG1lc3NhZ2UpKTsgTlVMTCB9KQ0KDQogIGlmICghaXMubnVsbChkZikpIHsgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICAgIGNhdChzcHJpbnRmKCIgIFtPS10gJS0zOHMgfCAlZCByb3dzIHwgJWQgY29sc1xuIiwNCiAgICAgICAgICAgICAgICBuYW1hLCBucm93KGRmKSwgbmNvbChkZikpKQ0KICAgIGRhdGFmcmFtZXNbW25hbWFdXSA8LSBkZg0KICB9DQp9DQoNCmNhdChzcHJpbnRmKCJcbiVkIG9mICVkIGZpbGVzIHN1Y2Nlc3NmdWxseSByZWFkLlxuIiwNCiAgICAgICAgICAgIGxlbmd0aChkYXRhZnJhbWVzKSwgbGVuZ3RoKGZpbGVfbGlzdCkpKQ0KYGBgDQoNCiMjIyBBLjQg4oCUIE1lcmdlIGFuZCBFeHBvcnQgdG8gRXhjZWwNCg0KYGBge3IgYTQtZ2FidW5na2FufQ0KaWYgKGxlbmd0aChkYXRhZnJhbWVzKSA9PSAwKSBzdG9wKCJObyBmaWxlcyB3ZXJlIHN1Y2Nlc3NmdWxseSByZWFkISIpDQoNCiMgUkVRVUlSRUQgTE9PUDogdHlwZS1oYXJtb25pemUgYW5kIHRhZyBlYWNoIHNvdXJjZSBmaWxlDQpkZl9saXN0X3RhZ2dlZCA8LSBsYXBwbHkobmFtZXMoZGF0YWZyYW1lcyksIGZ1bmN0aW9uKG5hbWEpIHsNCiAgZGZfdGVtcCA8LSBkYXRhZnJhbWVzW1tuYW1hXV0NCiAgZm9yIChjb2wgaW4gbmFtZXMoZGZfdGVtcCkpIGRmX3RlbXBbW2NvbF1dIDwtIGFzLmNoYXJhY3RlcihkZl90ZW1wW1tjb2xdXSkgICMgUkVRVUlSRUQgTE9PUA0KICBkZl90ZW1wJHNvdXJjZV9maWxlIDwtIGJhc2VuYW1lKG5hbWEpDQogIGNhdChzcHJpbnRmKCIgIE1lcmdlZDogJS0zOHMgKCVkIHJvd3MpXG4iLCBuYW1hLCBucm93KGRmX3RlbXApKSkNCiAgZGZfdGVtcA0KfSkNCg0KZGZfZ2FidW5nYW4gPC0gZHBseXI6OmJpbmRfcm93cyhkZl9saXN0X3RhZ2dlZCkNCg0KY2F0KHNwcmludGYoIlxuVG90YWwgUm93cyAgIDogJXNcbiIsIGZvcm1hdChucm93KGRmX2dhYnVuZ2FuKSwgYmlnLm1hcmsgPSAiLCIpKSkNCmNhdChzcHJpbnRmKCJUb3RhbCBDb2x1bW5zOiAlZFxuIiwgIG5jb2woZGZfZ2FidW5nYW4pKSkNCmNhdCgiQWxsIGNvbHVtbnMgY2FzdCB0byBjaGFyYWN0ZXIg4oCUIG51bWVyaWMgY29udmVyc2lvbiBvY2N1cnMgaW4gU2VjdGlvbiBDLlxuIikNCg0KIyBTYXZlIHRvIEV4Y2VsDQp3YiA8LSBjcmVhdGVXb3JrYm9vaygpDQphZGRXb3Jrc2hlZXQod2IsICJNZXJnZWQgRGF0YSIsIHRhYkNvbG91ciA9ICIjMTI0NmM0IikNCndyaXRlRGF0YSh3YiwgIk1lcmdlZCBEYXRhIiwgZGZfZ2FidW5nYW4pDQpocyA8LSBjcmVhdGVTdHlsZShmb250Q29sb3VyPSIjRkZGRkZGIiwgZmdGaWxsPSIjMGQxNTI5IiwNCiAgICAgICAgICAgICAgICAgIHRleHREZWNvcmF0aW9uPSJib2xkIiwgaGFsaWduPSJjZW50ZXIiKQ0KYWRkU3R5bGUod2IsICJNZXJnZWQgRGF0YSIsIGhzLCByb3dzPTEsIGNvbHM9MTpuY29sKGRmX2dhYnVuZ2FuKSwgZ3JpZEV4cGFuZD1UUlVFKQ0Kc2V0Q29sV2lkdGhzKHdiLCAiTWVyZ2VkIERhdGEiLCBjb2xzPTE6bmNvbChkZl9nYWJ1bmdhbiksIHdpZHRocz0iYXV0byIpDQpzYXZlV29ya2Jvb2sod2IsICJoYXNpbF9nYWJ1bmdhbi54bHN4Iiwgb3ZlcndyaXRlPVRSVUUpDQpjYXQoIlxuW0VYQ0VMXSBTYXZlZDogaGFzaWxfZ2FidW5nYW4ueGxzeFxuIikNCg0KZGF0YXRhYmxlKGhlYWQoZGZfZ2FidW5nYW4sIDIwKSwNCiAgICAgICAgICBjYXB0aW9uICA9ICJQcmV2aWV3IOKAlCBGaXJzdCAyMCBSb3dzIG9mIE1lcmdlZCBEYXRhc2V0IiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD01LCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIFNlY3Rpb24gQiDigJQgRGF0YSBIYW5kbGluZw0KDQo8ZGl2IGNsYXNzPSJpbmZvLWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+U2VjdGlvbiBCIOKAlCBDb21wcmVoZW5zaXZlIERhdGEgUXVhbGl0eSBBdWRpdDwvZGl2Pg0KICA8cD5CZWZvcmUgYW55IGludGVydmVudGlvbiwgdGhlIHN0YXRlIG9mIHRoZSBkYXRhIG11c3QgYmUgdGhvcm91Z2hseSBhbmQgb2JqZWN0aXZlbHkgdW5kZXJzdG9vZCDigJQgbXVjaCBsaWtlIGEgbWVkaWNhbCBkaWFnbm9zaXMgYmVmb3JlIHRyZWF0bWVudC4gU2VjdGlvbiBCIGV4ZWN1dGVzIGEgdGhyZWUtZGltZW5zaW9uYWwgYXVkaXQ6IDxzdHJvbmc+KDEpIERhdGEgdHlwZSBwcm9maWxpbmc8L3N0cm9uZz4gdG8gdmVyaWZ5IGFsaWdubWVudCBiZXR3ZWVuIHN0b3JhZ2UgZm9ybWF0IGFuZCBjb2x1bW4gc2VtYW50aWNzOyA8c3Ryb25nPigyKSBNaXNzaW5nIHZhbHVlIGFuYWx5c2lzPC9zdHJvbmc+IG1lYXN1cmluZyBub3QganVzdCBjb3VudHMgYnV0IHBhdHRlcm5zIHRoYXQgbWF5IGluZGljYXRlIHN5c3RlbWljIHVwc3RyZWFtIGlzc3VlczsgYW5kIDxzdHJvbmc+KDMpIER1cGxpY2F0ZSBkZXRlY3Rpb248L3N0cm9uZz4gc2VwYXJhdGluZyB0ZWNobmljYWwgcmVkdW5kYW5jeSBmcm9tIGdlbnVpbmUgYnVzaW5lc3MgZHVwbGljYXRpb24uIFRoZSBhdWRpdCBmaW5kaW5ncyBmb3JtIHRoZSBzY2llbnRpZmljIGJhc2lzIGZvciBhbGwgY2xlYW5pbmcgc3RyYXRlZ2llcyBpbiBTZWN0aW9uIEMuPC9wPg0KPC9kaXY+DQoNCiMjIyBCLjEg4oCUIENvbHVtbiBQcm9maWxlDQoNCmBgYHtyIGIxLWluZm99DQppbmZvX2RmIDwtIGRhdGEuZnJhbWUoDQogIENvbHVtbiAgICAgICAgID0gbmFtZXMoZGZfZ2FidW5nYW4pLA0KICBUeXBlICAgICAgICAgICA9IHNhcHBseShkZl9nYWJ1bmdhbiwgZnVuY3Rpb24oeCkgY2xhc3MoeClbMV0pLA0KICBNaXNzaW5nICAgICAgICA9IHNhcHBseShkZl9nYWJ1bmdhbiwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSksDQogIFBjdF9NaXNzaW5nICAgID0gc2FwcGx5KGRmX2dhYnVuZ2FuLCBmdW5jdGlvbih4KSBzcHJpbnRmKCIlLjFmJSUiLCBtZWFuKGlzLm5hKHgpKSoxMDApKSwNCiAgU2FtcGxlX1ZhbHVlcyAgPSBzYXBwbHkoZGZfZ2FidW5nYW4sIGZ1bmN0aW9uKHgpIHBhc3RlKGhlYWQobmEub21pdCh1bmlxdWUoeCkpLCAzKSwgY29sbGFwc2U9IiB8ICIpKSwNCiAgcm93Lm5hbWVzICAgICAgPSBOVUxMLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KZGF0YXRhYmxlKGluZm9fZGYsDQogICAgICAgICAgY2FwdGlvbiAgPSAiQ29sdW1uIFByb2ZpbGUg4oCUIE1lcmdlZCBEYXRhc2V0IiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD0xMCwgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSkgJT4lDQogIGZvcm1hdFN0eWxlKCJNaXNzaW5nIiwNCiAgICBiYWNrZ3JvdW5kQ29sb3IgPSBzdHlsZUludGVydmFsKGMoMCwgMTAwKSwgYygiI2QxZmFlNSIsIiNmZWYzYzciLCIjZmZlNGU2IikpKQ0KYGBgDQoNCiMjIyBCLjIg4oCUIE1pc3NpbmcgVmFsdWVzDQoNCmBgYHtyIGIyLW1pc3Npbmd9DQptaXNzaW5nX2NvdW50IDwtIGNvbFN1bXMoaXMubmEoZGZfZ2FidW5nYW4pKQ0KdG90YWxfbWlzc2luZyA8LSBzdW0obWlzc2luZ19jb3VudCkNCg0KY2F0KHNwcmludGYoIlRvdGFsIG1pc3NpbmcgdmFsdWVzIDogJWRcbiIsIHRvdGFsX21pc3NpbmcpKQ0KY2F0KHNwcmludGYoIkNvbHVtbnMgd2l0aCBtaXNzaW5nIDogJWQgb2YgJWRcbiIsDQogICAgICAgICAgICBzdW0obWlzc2luZ19jb3VudCA+IDApLCBuY29sKGRmX2dhYnVuZ2FuKSkpDQoNCiMgQnVpbGQgdGhlIG1pc3NpbmdfZGYgcmVnYXJkbGVzcyDigJQgdXNlZCBiZWxvdw0KbWlzc2luZ19kZiA8LSBpZiAodG90YWxfbWlzc2luZyA+IDApIHsNCiAgZGF0YS5mcmFtZSgNCiAgICBDb2x1bW4gICAgID0gbmFtZXMobWlzc2luZ19jb3VudFttaXNzaW5nX2NvdW50ID4gMF0pLA0KICAgIENvdW50ICAgICAgPSBtaXNzaW5nX2NvdW50W21pc3NpbmdfY291bnQgPiAwXSwNCiAgICBQZXJjZW50YWdlID0gcGFzdGUwKHJvdW5kKG1pc3NpbmdfY291bnRbbWlzc2luZ19jb3VudCA+IDBdL25yb3coZGZfZ2FidW5nYW4pKjEwMCwgMiksICIlIiksDQogICAgcm93Lm5hbWVzICA9IE5VTEwNCiAgKQ0KfSBlbHNlIHsNCiAgZGF0YS5mcmFtZShDb2x1bW4gPSBjaGFyYWN0ZXIoKSwgQ291bnQgPSBpbnRlZ2VyKCksIFBlcmNlbnRhZ2UgPSBjaGFyYWN0ZXIoKSkNCn0NCmBgYA0KDQpgYGB7ciBiMi1taXNzaW5nLXRhYmxlLCByZXN1bHRzPSdhc2lzJ30NCmlmIChucm93KG1pc3NpbmdfZGYpID09IDApIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogIGNhdCgiPHA+Tm8gbWlzc2luZyB2YWx1ZXMgZGV0ZWN0ZWQgaW4gdGhpcyBkYXRhc2V0LjwvcD4iKQ0KfSBlbHNlIHsNCiAgcHJpbnQoDQogICAgZGF0YXRhYmxlKG1pc3NpbmdfZGYsDQogICAgICAgICAgICAgIGNhcHRpb24gICAgID0gIkNvbHVtbnMgd2l0aCBNaXNzaW5nIFZhbHVlcyIsDQogICAgICAgICAgICAgIGV4dGVuc2lvbnMgID0gJ0J1dHRvbnMnLA0KICAgICAgICAgICAgICBvcHRpb25zICAgICA9IGxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTE1LCBzY3JvbGxYPVRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgICAgIHJvd25hbWVzICAgID0gRkFMU0UpDQogICkNCn0NCmBgYA0KDQojIyMgQi4zIOKAlCBEdXBsaWNhdGUgUm93cw0KDQpgYGB7ciBiMy1kdXBsaWthdH0NCm5fZHVwbGlrYXQgPC0gc3VtKGR1cGxpY2F0ZWQoZGZfZ2FidW5nYW4pKQ0KDQpjYXQoc3ByaW50ZigiRHVwbGljYXRlIHJvd3MgIDogJXNcbiIsIGZvcm1hdChuX2R1cGxpa2F0LCBiaWcubWFyaz0iLCIpKSkNCmNhdChzcHJpbnRmKCJQZXJjZW50YWdlICAgICAgOiAlLjJmJSVcbiIsIG5fZHVwbGlrYXQvbnJvdyhkZl9nYWJ1bmdhbikqMTAwKSkNCg0KZHVwX3ByZXZpZXcgPC0gaWYgKG5fZHVwbGlrYXQgPiAwKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogIGNhdCgiXG5TYW1wbGUgZHVwbGljYXRlIHJvd3MgKGZpcnN0IDUpOlxuIikNCiAgZGZfZ2FidW5nYW5bZHVwbGljYXRlZChkZl9nYWJ1bmdhbiksIF1bMTptaW4oNSxuX2R1cGxpa2F0KSwgMTo1XQ0KfSBlbHNlIHsNCiAgY2F0KCJObyBkdXBsaWNhdGVzIGZvdW5kLlxuIikNCiAgTlVMTA0KfQ0KYGBgDQoNCmBgYHtyIGIzLWR1cC10YWJsZSwgcmVzdWx0cz0nYXNpcyd9DQppZiAoIWlzLm51bGwoZHVwX3ByZXZpZXcpKSB7DQogIHByaW50KA0KICAgIGRhdGF0YWJsZShkdXBfcHJldmlldywNCiAgICAgICAgICAgICAgY2FwdGlvbiAgICA9ICJTYW1wbGUgRHVwbGljYXRlIFJvd3MiLA0KICAgICAgICAgICAgICBleHRlbnNpb25zID0gJ0J1dHRvbnMnLA0KICAgICAgICAgICAgICBvcHRpb25zICAgID0gbGlzdChkb209J0JmcnRpcCcsIHNjcm9sbFg9VFJVRSwgYnV0dG9ucz1saXN0KCdjc3YnLCdleGNlbCcsJ3ByaW50JykpLA0KICAgICAgICAgICAgICByb3duYW1lcyAgID0gRkFMU0UpDQogICkNCn0NCmBgYA0KDQojIyMgQi40IOKAlCBEYXRhIFF1YWxpdHkgSXNzdWVzDQoNCmBgYHtyIGI0LW1hc2FsYWh9DQptYXNhbGFoIDwtIGRhdGEuZnJhbWUoDQogIE5vICAgICAgPSAxOjQsDQogIENvbHVtbiAgPSBjKCJwbGF0Zm9ybSIsIm5ldF9zYWxlcyIsInBheW1lbnRfbWV0aG9kIiwib3JkZXJfc3RhdHVzIiksDQogIElzc3VlICAgPSBjKCJJbmNvbnNpc3RlbnQgcGxhdGZvcm0gbmFtZSBjYXNpbmcgYW5kIGZvcm1hdHRpbmcgYWNyb3NzIHNvdXJjZXMiLA0KICAgICAgICAgICAgICAgIk1peGVkIGZvcm1hdHM6IGN1cnJlbmN5IHN5bWJvbHMsIHRob3VzYW5kIHNlcGFyYXRvcnMsIG5lZ2F0aXZlIHNpZ25zIiwNCiAgICAgICAgICAgICAgICJOQSB2YWx1ZXMgcHJlc2VudCDigJQgbm9uLWluZm9ybWF0aXZlIGZvciBhbmFseXNpcyIsDQogICAgICAgICAgICAgICAiQ2FwaXRhbGl6YXRpb24gaW5jb25zaXN0ZW5jeTogJ0NhbmNlbGxlZCcgdnMgJ2NhbmNlbGxlZCcgdnMgJ0NBTkNFTExFRCciKSwNCiAgU29sdXRpb249IGMoIlN0YW5kYXJkaXplIHdpdGggdG9sb3dlcigpICsgY2FzZV93aGVuKCkgdG8gY2Fub25pY2FsIGZvcm0iLA0KICAgICAgICAgICAgICAgIlN0cmlwIG5vbi1udW1lcmljIGNoYXJhY3RlcnMgd2l0aCBnc3ViKCksIGNvbnZlcnQgdG8gbnVtZXJpYyIsDQogICAgICAgICAgICAgICAiRmlsbCBOQSB3aXRoICdVbmtub3duJyB0byBwcmVzZXJ2ZSByb3dzIHdpdGhvdXQgZGlzdG9ydGlvbiIsDQogICAgICAgICAgICAgICAiTm9ybWFsaXplIHdpdGggc3RyX3RvX3RpdGxlKCkgKyBjYXNlX3doZW4oKSB0byB1bmlmaWVkIGZvcm0iKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCmRhdGF0YWJsZShtYXNhbGFoLA0KICAgICAgICAgIGNhcHRpb24gID0gIkRhdGEgUXVhbGl0eSBJc3N1ZXMgJiBSZW1lZGlhdGlvbiBQbGFuIiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD0xMCwgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSkgJT4lDQogIGZvcm1hdFN0eWxlKCJJc3N1ZSIsICAgIGNvbG9yPSIjZjQzZjVlIikgJT4lDQogIGZvcm1hdFN0eWxlKCJTb2x1dGlvbiIsIGNvbG9yPSIjMTBiOTgxIikNCmBgYA0KDQojIyBTZWN0aW9uIEMg4oCUIERhdGEgQ2xlYW5pbmcNCg0KPGRpdiBjbGFzcz0iaW5mby1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlNlY3Rpb24gQyDigJQgU3lzdGVtYXRpYyBhbmQgQXVkaXRhYmxlIERhdGEgQ2xlYW5pbmc8L2Rpdj4NCiAgPHA+RGF0YSBjbGVhbmluZyBpcyBub3QgbWVyZWx5IHRpZHlpbmcg4oCUIGl0IGlzIGFuIGFuYWx5dGljYWwgZGVjaXNpb24tbWFraW5nIHByb2Nlc3MgdGhhdCBtdXN0IGJlIHNjaWVudGlmaWNhbGx5IGRlZmVuc2libGUuIEV2ZXJ5IHRyYW5zZm9ybWF0aW9uIGluIFNlY3Rpb24gQyBmb2xsb3dzIGluZm9ybWVkIGNsZWFuaW5nIHByaW5jaXBsZXM6IHRoZSByYXRpb25hbGUgZm9yIGVhY2ggc3RyYXRlZ3kgKHdoeSBtZWRpYW4gb3ZlciBtZWFuPyB3aHkgZmlsbCB3aXRoICJVbmtub3duIiByYXRoZXIgdGhhbiBkcm9wIHJvd3M/KSBpcyBleHBsaWNpdGx5IGdyb3VuZGVkIGluIGRhdGEgZGlzdHJpYnV0aW9uIGNoYXJhY3RlcmlzdGljcyBhbmQgYnVzaW5lc3MgY29udGV4dC4gVGhlIHNlcXVlbmNlIG9mIG9wZXJhdGlvbnMgaXMgaW50ZW50aW9uYWwg4oCUIHN0YW5kYXJkaXphdGlvbiBwcmVjZWRlcyBpbXB1dGF0aW9uLCBhbmQgZGVkdXBsaWNhdGlvbiBvY2N1cnMgbGFzdCB0byBlbnN1cmUgbm8gY2xlYW4gcm93cyBhcmUgaW5hZHZlcnRlbnRseSByZW1vdmVkLiBFYWNoIHN0ZXAgaXMgcXVhbnRpdGF0aXZlbHkgdmFsaWRhdGVkIGJ5IGNvbXBhcmluZyBiZWZvcmUtYW5kLWFmdGVyIHN0YXRlcy48L3A+DQo8L2Rpdj4NCg0KIyMjIEMuMCDigJQgQ3JlYXRlIFdvcmtpbmcgQ29weQ0KDQpgYGB7ciBjMC1zYWxpbmFufQ0KZGZfY2xlYW4gPC0gZGZfZ2FidW5nYW4NCmNhdChzcHJpbnRmKCJXb3JraW5nIGNvcHkgY3JlYXRlZDogJXMgcm93cyB4ICVkIGNvbHVtbnNcbiIsDQogICAgICAgICAgICBmb3JtYXQobnJvdyhkZl9jbGVhbiksIGJpZy5tYXJrPSIsIiksIG5jb2woZGZfY2xlYW4pKSkNCmBgYA0KDQojIyMgQy4xIOKAlCBQbGF0Zm9ybSBTdGFuZGFyZGl6YXRpb24NCg0KYGBge3IgYzEtcGxhdGZvcm19DQpzdGFuZGFyZGlzYXNpX3BsYXRmb3JtIDwtIGZ1bmN0aW9uKG5pbGFpKSB7DQogIGlmIChpcy5uYShuaWxhaSkpIHJldHVybigiVW5rbm93biIpICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogIHYgPC0gdG9sb3dlcih0cmltd3MobmlsYWkpKQ0KICBjYXNlX3doZW4oICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRi1FTFNFIGNoYWluDQogICAgc3RyX2RldGVjdCh2LCAic2hvcGVlIikgICAgfiAiU2hvcGVlIiwNCiAgICBzdHJfZGV0ZWN0KHYsICJ0b2tvcGVkaWEiKSB+ICJUb2tvcGVkaWEiLA0KICAgIHN0cl9kZXRlY3QodiwgImxhemFkYSIpICAgIH4gIkxhemFkYSIsDQogICAgc3RyX2RldGVjdCh2LCAiYnVrYWxhcGFrIikgfiAiQnVrYWxhcGFrIiwNCiAgICBzdHJfZGV0ZWN0KHYsICJibGlibGkiKSAgICB+ICJCbGlibGkiLA0KICAgIFRSVUUgICAgICAgICAgICAgICAgICAgICAgIH4gc3RyX3RvX3RpdGxlKHYpDQogICkNCn0NCg0KZGZfY2xlYW4kcGxhdGZvcm0gPC0gc2FwcGx5KGRmX2NsZWFuJHBsYXRmb3JtLCBzdGFuZGFyZGlzYXNpX3BsYXRmb3JtKQ0KDQpjYXQoIlBsYXRmb3JtIGRpc3RyaWJ1dGlvbiBhZnRlciBzdGFuZGFyZGl6YXRpb246XG4iKQ0KcHJpbnQodGFibGUoZGZfY2xlYW4kcGxhdGZvcm0pKQ0KYGBgDQoNCiMjIyBDLjIg4oCUIE5ldCBTYWxlcyBDbGVhbmluZw0KDQpgYGB7ciBjMi1uZXRzYWxlc30NCmJlcnNpaGthbl9zYWxlcyA8LSBmdW5jdGlvbihuaWxhaSkgew0KICBpZiAoaXMubmEobmlsYWkpKSByZXR1cm4oMCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRjogaGFuZGxlIE5BDQogIGlmIChpcy5udW1lcmljKG5pbGFpKSkgcmV0dXJuKG1heCgwLCBuaWxhaSkpICAgICAgICAgICAjIFJFUVVJUkVEIElGOiBhbHJlYWR5IG51bWVyaWMNCiAgYmVyc2loIDwtIGdzdWIoIltScFxcc1xcLixdIiwgIiIsIGFzLmNoYXJhY3RlcihuaWxhaSkpICMgc3RyaXAgY3VycmVuY3kgc3ltYm9scw0KICBoYXNpbCAgPC0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKGJlcnNpaCkpDQogIGlmIChpcy5uYShoYXNpbCkgfHwgaGFzaWwgPCAwKSByZXR1cm4oMCkgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGOiBpbnZhbGlkIHZhbHVlDQogIHJldHVybihoYXNpbCkNCn0NCg0KZGZfY2xlYW4kbmV0X3NhbGVzIDwtIHNhcHBseShkZl9jbGVhbiRuZXRfc2FsZXMsIGJlcnNpaGthbl9zYWxlcykNCmRmX2NsZWFuJG5ldF9zYWxlcyA8LSBhcy5udW1lcmljKGRmX2NsZWFuJG5ldF9zYWxlcykNCg0KY2F0KHNwcmludGYoIk1pbiAgOiBScCAlc1xuIiwgZm9ybWF0KG1pbihkZl9jbGVhbiRuZXRfc2FsZXMsIG5hLnJtPVRSVUUpLCBiaWcubWFyaz0iLCIpKSkNCmNhdChzcHJpbnRmKCJNYXggIDogUnAgJXNcbiIsIGZvcm1hdChtYXgoZGZfY2xlYW4kbmV0X3NhbGVzLCBuYS5ybT1UUlVFKSwgYmlnLm1hcms9IiwiKSkpDQpjYXQoc3ByaW50ZigiTWVhbiA6IFJwICVzXG4iLCBmb3JtYXQocm91bmQobWVhbihkZl9jbGVhbiRuZXRfc2FsZXMsIG5hLnJtPVRSVUUpKSwgYmlnLm1hcms9IiwiKSkpDQpjYXQoc3ByaW50ZigiUmVtYWluaW5nIE5BOiAlZFxuIiwgc3VtKGlzLm5hKGRmX2NsZWFuJG5ldF9zYWxlcykpKSkNCmBgYA0KDQojIyMgQy4zIOKAlCBNaXNzaW5nIFZhbHVlIEltcHV0YXRpb24NCg0KYGBge3IgYzMtbWlzc2luZ30NCmRmX2NsZWFuIDwtIGRmX2NsZWFuICU+JQ0KICBtdXRhdGUoDQogICAgcGF5bWVudF9tZXRob2QgPSBpZmVsc2UoaXMubmEocGF5bWVudF9tZXRob2QpLCAiVW5rbm93biIsIHBheW1lbnRfbWV0aG9kKSwgICMgUkVRVUlSRUQgSUYNCiAgICBuZXRfc2FsZXMgICAgICA9IGlmZWxzZShpcy5uYShuZXRfc2FsZXMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGlhbihuZXRfc2FsZXMsIG5hLnJtPVRSVUUpLCBuZXRfc2FsZXMpICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICApDQoNCmNhdChzcHJpbnRmKCJNaXNzaW5nIHBheW1lbnRfbWV0aG9kIGFmdGVyIGltcHV0YXRpb246ICVkXG4iLCBzdW0oaXMubmEoZGZfY2xlYW4kcGF5bWVudF9tZXRob2QpKSkpDQpjYXQoc3ByaW50ZigiTWlzc2luZyBuZXRfc2FsZXMgYWZ0ZXIgaW1wdXRhdGlvbiAgICAgOiAlZFxuIiwgc3VtKGlzLm5hKGRmX2NsZWFuJG5ldF9zYWxlcykpKSkNCmBgYA0KDQojIyMgQy40IOKAlCBPcmRlciBTdGF0dXMgU3RhbmRhcmRpemF0aW9uDQoNCmBgYHtyIGM0LXN0YXR1c30NCmRmX2NsZWFuIDwtIGRmX2NsZWFuICU+JQ0KICBtdXRhdGUob3JkZXJfc3RhdHVzID0gY2FzZV93aGVuKA0KICAgIHN0cl9kZXRlY3QodG9sb3dlcihvcmRlcl9zdGF0dXMpLCAiY29tcGxldCIpICB+ICJDb21wbGV0ZWQiLCAgICMgUkVRVUlSRUQgSUYtRUxTRQ0KICAgIHN0cl9kZXRlY3QodG9sb3dlcihvcmRlcl9zdGF0dXMpLCAiY2FuY2VsIikgICB+ICJDYW5jZWxsZWQiLA0KICAgIHN0cl9kZXRlY3QodG9sb3dlcihvcmRlcl9zdGF0dXMpLCAicGVuZGluZyIpICB+ICJQZW5kaW5nIiwNCiAgICBzdHJfZGV0ZWN0KHRvbG93ZXIob3JkZXJfc3RhdHVzKSwgInNoaXAiKSAgICAgfiAiU2hpcHBlZCIsDQogICAgaXMubmEob3JkZXJfc3RhdHVzKSAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gIlVua25vd24iLA0KICAgIFRSVUUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+IHN0cl90b190aXRsZShvcmRlcl9zdGF0dXMpDQogICkpDQoNCmNhdCgiT3JkZXIgc3RhdHVzIGRpc3RyaWJ1dGlvbiBhZnRlciBzdGFuZGFyZGl6YXRpb246XG4iKQ0KcHJpbnQodGFibGUoZGZfY2xlYW4kb3JkZXJfc3RhdHVzKSkNCmBgYA0KDQojIyMgQy41IOKAlCBSRVFVSVJFRCBMT09QOiBUZXh0IENvbHVtbiBDbGVhbmluZw0KDQpgYGB7ciBjNS1sb29waW5nLXRla3N9DQprb2xvbV90ZWtzIDwtIGMoInBsYXRmb3JtIiwgImNhdGVnb3J5IiwgInByb2R1Y3RfbmFtZSIsICJvcmRlcl9zdGF0dXMiLCAicGF5bWVudF9tZXRob2QiKQ0KDQpmb3IgKGtvbG9tIGluIGtvbG9tX3Rla3MpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgTE9PUA0KICBpZiAoa29sb20gJWluJSBuYW1lcyhkZl9jbGVhbikgJiYgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgSUY6IGNvbHVtbiBleGlzdHM/DQogICAgICBpcy5jaGFyYWN0ZXIoZGZfY2xlYW5bW2tvbG9tXV0pKSB7DQogICAgc2ViZWx1bSA8LSBzdW0oaXMubmEoZGZfY2xlYW5bW2tvbG9tXV0pKQ0KICAgIGRmX2NsZWFuW1trb2xvbV1dIDwtIHRyaW13cyhkZl9jbGVhbltba29sb21dXSkNCiAgICBkZl9jbGVhbltba29sb21dXVtpcy5uYShkZl9jbGVhbltba29sb21dXSkgfA0KICAgICAgICAgICAgICAgICAgICAgIGRmX2NsZWFuW1trb2xvbV1dID09ICIiXSA8LSAiVW5rbm93biINCiAgICBzZXN1ZGFoIDwtIHN1bShpcy5uYShkZl9jbGVhbltba29sb21dXSkpDQogICAgY2F0KHNwcmludGYoIiAgW09LXSAlLTIwcyB8IG1pc3Npbmc6ICVkIC0+ICVkXG4iLCBrb2xvbSwgc2ViZWx1bSwgc2VzdWRhaCkpDQogIH0NCn0NCmBgYA0KDQojIyMgQy42IOKAlCBEZWR1cGxpY2F0aW9uIGFuZCBTdW1tYXJ5DQoNCmBgYHtyIGM2LWhhcHVzLWR1cGxpa2F0fQ0Kbl9zYmxtIDwtIG5yb3coZGZfY2xlYW4pDQpkZl9jbGVhbiA8LSBkZl9jbGVhbiAlPiUgZGlzdGluY3QoKQ0KDQpjYXQoc3ByaW50ZigiRHVwbGljYXRlcyByZW1vdmVkIDogJXMgcm93c1xuIiwgICBmb3JtYXQobl9zYmxtIC0gbnJvdyhkZl9jbGVhbiksIGJpZy5tYXJrPSIsIikpKQ0KY2F0KHNwcmludGYoIkNsZWFuIGRhdGFzZXQgICAgICA6ICVzIHJvd3NcbiIsICAgZm9ybWF0KG5yb3coZGZfY2xlYW4pLCBiaWcubWFyaz0iLCIpKSkNCmNhdChzcHJpbnRmKCJUb3RhbCBjb2x1bW5zICAgICAgOiAlZFxuXG4iLCBuY29sKGRmX2NsZWFuKSkpDQoNCmRhdGF0YWJsZShoZWFkKGRmX2NsZWFuLCA1MCksDQogICAgICAgICAgY2FwdGlvbiAgPSAiQ2xlYW4gRGF0YXNldCDigJQgRmlyc3QgNTAgUm93cyIsDQogICAgICAgICAgZXh0ZW5zaW9ucz0nQnV0dG9ucycsIG9wdGlvbnM9bGlzdChkb209J0JmcnRpcCcsIHBhZ2VMZW5ndGg9MTAsIHNjcm9sbFg9VFJVRSwgYnV0dG9ucz1saXN0KCdjc3YnLCdleGNlbCcsJ3ByaW50JykpLA0KICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMgU2VjdGlvbiBEIOKAlCBDb25kaXRpb25hbCBMb2dpYw0KDQo8ZGl2IGNsYXNzPSJpbmZvLWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+U2VjdGlvbiBEIOKAlCBCdXNpbmVzcy1Ecml2ZW4gRmVhdHVyZSBFbmdpbmVlcmluZzwvZGl2Pg0KICA8cD5GZWF0dXJlIGVuZ2luZWVyaW5nIGJyaWRnZXMgcmF3IGRhdGEgYW5kIGFjdGlvbmFibGUgYnVzaW5lc3MgaW50ZWxsaWdlbmNlLiBUaGUgdGhyZWUgZGVyaXZlZCBjb2x1bW5zIGFkZGVkIGhlcmUgYXJlIG5vdCBtZXJlbHkgdGVjaG5pY2FsIGV4ZXJjaXNlcyDigJQgZWFjaCByZXByZXNlbnRzIGJ1c2luZXNzIGxvZ2ljIGFjdGl2ZWx5IHVzZWQgaW4gZS1jb21tZXJjZSBvcGVyYXRpb25zOiA8Y29kZT5pc19oaWdoX3ZhbHVlPC9jb2RlPiBmb3IgcHJlbWl1bSBjdXN0b21lciBzZWdtZW50YXRpb24gYW5kIGxveWFsdHkgcHJvZ3JhbXMsIDxjb2RlPm9yZGVyX3ByaW9yaXR5PC9jb2RlPiBmb3IgZnVsZmlsbG1lbnQgcmVzb3VyY2UgYWxsb2NhdGlvbiBhbmQgU0xBIGRlZmluaXRpb24sIGFuZCA8Y29kZT52YWxpZF90cmFuc2FjdGlvbjwvY29kZT4gZm9yIHNlcGFyYXRpbmcgY29uZmlybWVkIHJldmVudWUgZnJvbSBhdC1yaXNrIHBpcGVsaW5lLiBUaGUgZW5yaWNoZWQgZGF0YXNldCBjYXJyaWVzIHNpZ25pZmljYW50bHkgaGlnaGVyIGFuYWx5dGljYWwgdmFsdWUgYW5kIGNhbiBiZSBjb25zdW1lZCBkaXJlY3RseSBieSBCdXNpbmVzcyBJbnRlbGxpZ2VuY2UgdGVhbXMgd2l0aG91dCBmdXJ0aGVyIHByZXByb2Nlc3NpbmcuPC9wPg0KPC9kaXY+DQoNCnwgTmV3IENvbHVtbiB8IExvZ2ljIHwgVHlwZSB8IEJ1c2luZXNzIFVzZSB8DQp8Oi0tLXw6LS0tfDotLS06fDotLS18DQp8IGBpc19oaWdoX3ZhbHVlYCB8IGBuZXRfc2FsZXMgPiAxLDAwMCwwMDBgIHwgQmluYXJ5IHwgUHJlbWl1bSBjdXN0b21lciBpZGVudGlmaWNhdGlvbiB8DQp8IGBvcmRlcl9wcmlvcml0eWAgfCAzLXRpZXIgYmFzZWQgb24gbmV0X3NhbGVzIHwgTXVsdGktY2xhc3MgfCBTTEEgYW5kIHJlc291cmNlIGFsbG9jYXRpb24gfA0KfCBgdmFsaWRfdHJhbnNhY3Rpb25gIHwgQmFzZWQgb24gb3JkZXJfc3RhdHVzIHwgQmluYXJ5IHwgUmV2ZW51ZSBmb3JlY2FzdGluZyB8DQoNCiMjIyBELjEg4oCUIGlzX2hpZ2hfdmFsdWUgQ29sdW1uDQoNCmBgYHtyIGQxLWhpZ2gtdmFsdWV9DQpjZWtfaGlnaF92YWx1ZSA8LSBmdW5jdGlvbihzYWxlcykgew0KICBpZmVsc2Uoc2FsZXMgPiAxMDAwMDAwLCAiWWVzIiwgIk5vIikgICAgICAgICAgIyBSRVFVSVJFRCBJRi1FTFNFDQp9DQoNCmRmX2NsZWFuJGlzX2hpZ2hfdmFsdWUgPC0gY2VrX2hpZ2hfdmFsdWUoZGZfY2xlYW4kbmV0X3NhbGVzKQ0KDQpjYXQoIkRpc3RyaWJ1dGlvbiBvZiBpc19oaWdoX3ZhbHVlOlxuIikNCnByaW50KHRhYmxlKGRmX2NsZWFuJGlzX2hpZ2hfdmFsdWUpKQ0KYGBgDQoNCiMjIyBELjIg4oCUIG9yZGVyX3ByaW9yaXR5IENvbHVtbiAoTkVTVEVEIElGKQ0KDQpgYGB7ciBkMi1wcmlvcml0eX0NCnRlbnR1a2FuX3ByaW9yaXRhcyA8LSBmdW5jdGlvbihzYWxlcykgew0KICBjYXNlX3doZW4oDQogICAgc2FsZXMgPiAxMDAwMDAwIH4gIkhpZ2giLCAgICAgICAgIyBSRVFVSVJFRCBORVNURUQgSUYgbGV2ZWwgMQ0KICAgIHNhbGVzID49IDUwMDAwMCB+ICJNZWRpdW0iLCAgICAgICMgUkVRVUlSRUQgTkVTVEVEIElGIGxldmVsIDINCiAgICBUUlVFICAgICAgICAgICAgfiAiTG93IiAgICAgICAgICAjIFJFUVVJUkVEIE5FU1RFRCBJRiBsZXZlbCAzIChlbHNlKQ0KICApDQp9DQoNCmRmX2NsZWFuJG9yZGVyX3ByaW9yaXR5IDwtIHRlbnR1a2FuX3ByaW9yaXRhcyhkZl9jbGVhbiRuZXRfc2FsZXMpDQoNCmNhdCgiRGlzdHJpYnV0aW9uIG9mIG9yZGVyX3ByaW9yaXR5OlxuIikNCnByaW50KHRhYmxlKGRmX2NsZWFuJG9yZGVyX3ByaW9yaXR5KSkNCmBgYA0KDQojIyMgRC4zIOKAlCB2YWxpZF90cmFuc2FjdGlvbiBDb2x1bW4NCg0KYGBge3IgZDMtdmFsaWR9DQpkZl9jbGVhbiR2YWxpZF90cmFuc2FjdGlvbiA8LSBpZmVsc2UoDQogIGRmX2NsZWFuJG9yZGVyX3N0YXR1cyA9PSAiQ2FuY2VsbGVkIiwgIkludmFsaWQiLCAiVmFsaWQiICAgIyBSRVFVSVJFRCBJRi1FTFNFDQopDQoNCmNhdCgiRGlzdHJpYnV0aW9uIG9mIHZhbGlkX3RyYW5zYWN0aW9uOlxuIikNCnByaW50KHRhYmxlKGRmX2NsZWFuJHZhbGlkX3RyYW5zYWN0aW9uKSkNCmBgYA0KDQojIyMgRC40IOKAlCBEaXNwbGF5IFJlc3VsdHMgYW5kIFNhdmUNCg0KYGBge3IgZDQtc2ltcGFufQ0Ka29sb21fdGFtcGlsIDwtIGludGVyc2VjdCgNCiAgYygib3JkZXJfaWQiLCJwbGF0Zm9ybSIsIm5ldF9zYWxlcyIsIm9yZGVyX3N0YXR1cyIsDQogICAgImlzX2hpZ2hfdmFsdWUiLCJvcmRlcl9wcmlvcml0eSIsInZhbGlkX3RyYW5zYWN0aW9uIiksDQogIG5hbWVzKGRmX2NsZWFuKQ0KKQ0KDQp3cml0ZV9jc3YoZGZfY2xlYW4sICJkYXRhc2V0X2ZpbmFsX2JlcnNpaC5jc3YiKQ0KDQp3YjIgPC0gY3JlYXRlV29ya2Jvb2soKQ0KYWRkV29ya3NoZWV0KHdiMiwgIkNsZWFuIERhdGFzZXQgTVAxIiwgdGFiQ29sb3VyPSIjMTI0NmM0IikNCndyaXRlRGF0YSh3YjIsICJDbGVhbiBEYXRhc2V0IE1QMSIsIGRmX2NsZWFuKQ0KaHMyIDwtIGNyZWF0ZVN0eWxlKGZvbnRDb2xvdXI9IiNGRkZGRkYiLCBmZ0ZpbGw9IiMwZDE1MjkiLA0KICAgICAgICAgICAgICAgICAgIHRleHREZWNvcmF0aW9uPSJib2xkIiwgaGFsaWduPSJjZW50ZXIiKQ0KYWRkU3R5bGUod2IyLCAiQ2xlYW4gRGF0YXNldCBNUDEiLCBoczIsDQogICAgICAgICByb3dzPTEsIGNvbHM9MTpuY29sKGRmX2NsZWFuKSwgZ3JpZEV4cGFuZD1UUlVFKQ0Kc2V0Q29sV2lkdGhzKHdiMiwgIkNsZWFuIERhdGFzZXQgTVAxIiwgY29scz0xOm5jb2woZGZfY2xlYW4pLCB3aWR0aHM9ImF1dG8iKQ0Kc2F2ZVdvcmtib29rKHdiMiwgImRhdGFzZXRfZmluYWxfYmVyc2loLnhsc3giLCBvdmVyd3JpdGU9VFJVRSkNCmNhdCgiW0NTVl0gICBTYXZlZDogZGF0YXNldF9maW5hbF9iZXJzaWguY3N2XG4iKQ0KY2F0KCJbRVhDRUxdIFNhdmVkOiBkYXRhc2V0X2ZpbmFsX2JlcnNpaC54bHN4XG5cbiIpDQoNCmNhdCgnPGRpdiBzdHlsZT0ibWFyZ2luOjE2cHggMCAyNHB4OyBkaXNwbGF5OmZsZXg7IGdhcDoxNHB4OyBmbGV4LXdyYXA6d3JhcDsiPg0KICA8YSBocmVmPSJkYXRhc2V0X2ZpbmFsX2JlcnNpaC5jc3YiIGRvd25sb2FkDQogICAgIHN0eWxlPSJkaXNwbGF5OmlubGluZS1mbGV4O2FsaWduLWl0ZW1zOmNlbnRlcjtnYXA6OHB4Ow0KICAgICAgICAgICAgYmFja2dyb3VuZDpsaW5lYXItZ3JhZGllbnQoMTM1ZGVnLCMwZWE1ZTksIzYzNjZmMSk7DQogICAgICAgICAgICBjb2xvcjojZmZmO2ZvbnQtd2VpZ2h0OjcwMDtmb250LXNpemU6MTRweDsNCiAgICAgICAgICAgIHBhZGRpbmc6MTJweCAyOHB4O2JvcmRlci1yYWRpdXM6NTBweDt0ZXh0LWRlY29yYXRpb246bm9uZTsNCiAgICAgICAgICAgIGJveC1zaGFkb3c6MCA0cHggMTZweCByZ2JhKDk5LDEwMiwyNDEsMC4zNSk7Ij4NCiAgICBEb3dubG9hZCBDU1YNCiAgPC9hPg0KICA8YSBocmVmPSJkYXRhc2V0X2ZpbmFsX2JlcnNpaC54bHN4IiBkb3dubG9hZA0KICAgICBzdHlsZT0iZGlzcGxheTppbmxpbmUtZmxleDthbGlnbi1pdGVtczpjZW50ZXI7Z2FwOjhweDsNCiAgICAgICAgICAgIGJhY2tncm91bmQ6bGluZWFyLWdyYWRpZW50KDEzNWRlZywjMTBiOTgxLCMwNTk2NjkpOw0KICAgICAgICAgICAgY29sb3I6I2ZmZjtmb250LXdlaWdodDo3MDA7Zm9udC1zaXplOjE0cHg7DQogICAgICAgICAgICBwYWRkaW5nOjEycHggMjhweDtib3JkZXItcmFkaXVzOjUwcHg7dGV4dC1kZWNvcmF0aW9uOm5vbmU7DQogICAgICAgICAgICBib3gtc2hhZG93OjAgNHB4IDE2cHggcmdiYSgxNiwxODUsMTI5LDAuMzUpOyI+DQogICAgRG93bmxvYWQgRXhjZWwNCiAgPC9hPg0KPC9kaXY+JykNCg0KZGF0YXRhYmxlKGRmX2NsZWFuWywga29sb21fdGFtcGlsXSwNCiAgICAgICAgICBjYXB0aW9uICA9ICJGaW5hbCBEYXRhc2V0IOKAlCBGZWF0dXJlLUVuZ2luZWVyZWQgd2l0aCAzIE5ldyBDb2x1bW5zIiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD0xMCwgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSkgJT4lDQogIGZvcm1hdFN0eWxlKCJpc19oaWdoX3ZhbHVlIiwNCiAgICBiYWNrZ3JvdW5kQ29sb3IgPSBzdHlsZUVxdWFsKGMoIlllcyIsIk5vIiksIGMoIiNkMWZhZTUiLCIjZmZlNGU2IikpLA0KICAgIGZvbnRXZWlnaHQgPSAiYm9sZCIpICU+JQ0KICBmb3JtYXRTdHlsZSgidmFsaWRfdHJhbnNhY3Rpb24iLA0KICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlRXF1YWwoYygiVmFsaWQiLCJJbnZhbGlkIiksIGMoIiNkMWZhZTUiLCIjZmZlNGU2IikpLA0KICAgIGZvbnRXZWlnaHQgPSAiYm9sZCIpICU+JQ0KICBmb3JtYXRTdHlsZSgib3JkZXJfcHJpb3JpdHkiLA0KICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlRXF1YWwoYygiSGlnaCIsIk1lZGl1bSIsIkxvdyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoIiNkMWZhZTUiLCIjZmVmM2M3IiwiI2ZmZTRlNiIpKSkNCmBgYA0KDQojIyBTZWN0aW9uIEUg4oCUIEFuYWx5dGljYWwgVGhpbmtpbmcNCg0KPGRpdiBjbGFzcz0iaW5mby1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlNlY3Rpb24gRSDigJQgQW5hbHl0aWNhbCBUaGlua2luZyBhbmQgU3RyYXRlZ2ljIERlY2lzaW9uIEludGVsbGlnZW5jZTwvZGl2Pg0KICA8cD5UaGlzIGlzIHRoZSBtb3N0IGNvbnNlcXVlbnRpYWwgc3RhZ2Ugb2YgdGhlIGVudGlyZSBwaXBlbGluZTogY29udmVydGluZyBudW1iZXJzIGludG8gYWN0aW9uYWJsZSBidXNpbmVzcyBuYXJyYXRpdmVzLiBBbmFseXNpcyB0cmFuc2NlbmRzIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3Mgd2hlbiBldmVyeSBmaW5kaW5nIGlzIGNvbm5lY3RlZCB0byBvcGVyYXRpb25hbCBpbXBsaWNhdGlvbnMgYW5kIGV4ZWN1dGFibGUgcmVjb21tZW5kYXRpb25zLiBGb3VyIGFuYWx5dGljYWwgZGltZW5zaW9ucyBhcmUgZXhwbG9yZWQ6IHBsYXRmb3JtIGRvbWluYW5jZSAoZm9yIG1hcmtldGluZyBidWRnZXQgYWxsb2NhdGlvbiksIGNhdGVnb3J5IGNvbmNlbnRyYXRpb24gKGZvciBwcm9kdWN0IHBvcnRmb2xpbyByaXNrIG1hbmFnZW1lbnQpLCB0cmFuc2FjdGlvbiBwaXBlbGluZSBoZWFsdGggKGZvciBjdXN0b21lciBzdWNjZXNzIEtQSXMpLCBhbmQgYW4gZXhlY3V0aXZlIHN1bW1hcnkgZ3JvdW5kZWQgaW4gZGF0YS48L3A+DQo8L2Rpdj4NCg0KIyMjIEUuMSDigJQgUGxhdGZvcm0gRG9taW5hbmNlDQoNCmBgYHtyIGUxLXBsYXRmb3JtfQ0KcGxhdGZvcm1fdGJsICAgICA8LSBzb3J0KHRhYmxlKGRmX2NsZWFuJHBsYXRmb3JtKSwgZGVjcmVhc2luZz1UUlVFKQ0KcGxhdGZvcm1fZG9taW5hbiA8LSBuYW1lcyhwbGF0Zm9ybV90YmwpWzFdDQpwY3RfZG9taW5hbiAgICAgIDwtIGFzLm51bWVyaWMocGxhdGZvcm1fdGJsWzFdKSAvIG5yb3coZGZfY2xlYW4pICogMTAwDQoNCnBsYXRmb3JtX2RmIDwtIGRhdGEuZnJhbWUoDQogIFBsYXRmb3JtICAgICA9IG5hbWVzKHBsYXRmb3JtX3RibCksDQogIFRyYW5zYWN0aW9ucyA9IGFzLm51bWVyaWMocGxhdGZvcm1fdGJsKSwNCiAgUGVyY2VudGFnZSAgID0gcGFzdGUwKHJvdW5kKGFzLm51bWVyaWMocGxhdGZvcm1fdGJsKS9ucm93KGRmX2NsZWFuKSoxMDAsIDEpLCAiJSIpLA0KICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UNCikNCg0KZGF0YXRhYmxlKHBsYXRmb3JtX2RmLA0KICAgICAgICAgIGNhcHRpb24gID0gIlRyYW5zYWN0aW9uIERpc3RyaWJ1dGlvbiBieSBFLUNvbW1lcmNlIFBsYXRmb3JtIiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksIHJvd25hbWVzPUZBTFNFKSAlPiUNCiAgZm9ybWF0U3R5bGUoIlRyYW5zYWN0aW9ucyIsDQogICAgYmFja2dyb3VuZCA9IHN0eWxlQ29sb3JCYXIocGxhdGZvcm1fZGYkVHJhbnNhY3Rpb25zLCAiIzNiN2JmZiIpLA0KICAgIGJhY2tncm91bmRTaXplID0gIjEwMCUgNzAlIiwNCiAgICBiYWNrZ3JvdW5kUmVwZWF0ID0gIm5vLXJlcGVhdCIsDQogICAgYmFja2dyb3VuZFBvc2l0aW9uID0gImNlbnRlciIpDQpgYGANCg0KPGRpdiBjbGFzcz0iaW5zaWdodC1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlN0cmF0ZWdpYyBJbnNpZ2h0IOKAlCBQbGF0Zm9ybSBEb21pbmFuY2UgYW5kIFJlc291cmNlIEFsbG9jYXRpb248L2Rpdj4NCiAgPHA+PHN0cm9uZz5gciBwbGF0Zm9ybV9kb21pbmFuYDwvc3Ryb25nPiBsZWFkcyB3aXRoIDxzdHJvbmc+YHIgZm9ybWF0KGFzLm51bWVyaWMocGxhdGZvcm1fdGJsWzFdKSwgYmlnLm1hcms9IiwiKWA8L3N0cm9uZz4gdHJhbnNhY3Rpb25zICg8c3Ryb25nPmByIHJvdW5kKHBjdF9kb21pbmFuLDEpYCU8L3N0cm9uZz4gbWFya2V0IHNoYXJlKS4gVGhpcyBjb25jZW50cmF0aW9uIHJlZmxlY3RzIHRocmVlIG11dHVhbGx5IHJlaW5mb3JjaW5nIG1lY2hhbmlzbXM6IDxlbT5uZXR3b3JrIGVmZmVjdHM8L2VtPiAoYSBtYXR1cmUgZWNvc3lzdGVtIG9mIGJ1eWVycyBhbmQgc2VsbGVycyBjcmVhdGVzIGdyYXZpdGF0aW9uYWwgcHVsbCksIGhpZ2ggPGVtPnN3aXRjaGluZyBjb3N0czwvZW0+IGZvciBzZWxsZXJzIHdobyBoYXZlIGJ1aWx0IHJlcHV0YXRpb24gYW5kIHJhdGluZ3Mgb24gdGhlIHBsYXRmb3JtLCBhbmQgYWNjdW11bGF0ZWQgPGVtPnRydXN0IGNhcGl0YWw8L2VtPiB0aHJvdWdoIHllYXJzIG9mIHJlbGlhYmxlIHBvc3Qtc2FsZSBzZXJ2aWNlIGFuZCBkaXNwdXRlIHJlc29sdXRpb24uPC9wPg0KICA8cD5UaGUgZ2FwIHdpdGggc2Vjb25kLXJhbmtlZCBwbGF0Zm9ybXMganVzdGlmaWVzIGFuIDxzdHJvbmc+YXN5bW1ldHJpYywgZGF0YS1kcml2ZW4gaW52ZXN0bWVudCBzdHJhdGVneTwvc3Ryb25nPjogYWxsb2NhdGUgNjDigJM3MCUgb2YgYWNxdWlzaXRpb24gYW5kIHJldGVudGlvbiBidWRnZXQgdG8gdGhlIGRvbWluYW50IHBsYXRmb3JtIHdoZXJlIFJPSSBpcyBtZWFzdXJhYmxlIGFuZCBwcmVkaWN0YWJsZS4gUmVtYWluaW5nIGJ1ZGdldCBkaXZlcnNpZmllcyBhY3Jvc3Mgb3RoZXIgcGxhdGZvcm1zIHRvIG1pdGlnYXRlIHNpbmdsZS1wbGF0Zm9ybSBkZXBlbmRlbmN5IHJpc2suIE1vbml0b3IgcXVhcnRlcmx5IHRyZW5kcyBhbmQgcHJlcGFyZSByZWJhbGFuY2luZyBzY2VuYXJpb3MgaWYgdGhlIGRvbWluYW50IHBsYXRmb3JtJ3Mgc2hhcmUgZXJvZGVzIGJ5IG1vcmUgdGhhbiA1IHBlcmNlbnRhZ2UgcG9pbnRzLjwvcD4NCjwvZGl2Pg0KDQojIyMgRS4yIOKAlCBDYXRlZ29yeSBEaXN0cmlidXRpb24NCg0KYGBge3IgZTItY2F0ZWdvcnl9DQprb2xvbV9jYXQgPC0gTkENCmZvciAoayBpbiBjKCJjYXRlZ29yeSIsImthdGVnb3JpIiwicHJvZHVjdF9jYXRlZ29yeSIpKSB7ICAjIFJFUVVJUkVEIExPT1ANCiAgaWYgKGsgJWluJSBuYW1lcyhkZl9jbGVhbikpIHsga29sb21fY2F0IDwtIGs7IGJyZWFrIH0gICMgUkVRVUlSRUQgSUYNCn0NCg0KaWYgKCFpcy5uYShrb2xvbV9jYXQpKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogIGNhdF90YmwgPC0gc29ydCh0YWJsZShkZl9jbGVhbltba29sb21fY2F0XV0pLCBkZWNyZWFzaW5nPVRSVUUpDQogIGNhdF9kb21pbmFuIDwtIG5hbWVzKGNhdF90YmwpWzFdDQogIHBjdF9jYXQgPC0gYXMubnVtZXJpYyhjYXRfdGJsWzFdKSAvIG5yb3coZGZfY2xlYW4pICogMTAwDQoNCiAgY2F0X2RmIDwtIGRhdGEuZnJhbWUoDQogICAgQ2F0ZWdvcnkgICAgID0gbmFtZXMoY2F0X3RibCksDQogICAgVHJhbnNhY3Rpb25zID0gYXMubnVtZXJpYyhjYXRfdGJsKSwNCiAgICBQZXJjZW50YWdlICAgPSBwYXN0ZTAocm91bmQoYXMubnVtZXJpYyhjYXRfdGJsKS9ucm93KGRmX2NsZWFuKSoxMDAsMSksIiUiKSwNCiAgICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFDQogICkNCiAgZGF0YXRhYmxlKGNhdF9kZiwNCiAgICAgICAgICAgIGNhcHRpb24gID0gIlRyYW5zYWN0aW9uIERpc3RyaWJ1dGlvbiBieSBQcm9kdWN0IENhdGVnb3J5IiwNCiAgICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTE1LCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwgcm93bmFtZXM9RkFMU0UpICU+JQ0KICAgIGZvcm1hdFN0eWxlKCJUcmFuc2FjdGlvbnMiLA0KICAgICAgYmFja2dyb3VuZD1zdHlsZUNvbG9yQmFyKGNhdF9kZiRUcmFuc2FjdGlvbnMsIiMzNGQzOTkiKSwNCiAgICAgIGJhY2tncm91bmRTaXplPSIxMDAlIDcwJSIsIGJhY2tncm91bmRSZXBlYXQ9Im5vLXJlcGVhdCIsDQogICAgICBiYWNrZ3JvdW5kUG9zaXRpb249ImNlbnRlciIpDQp9IGVsc2Ugew0KICBjYXQoIkNhdGVnb3J5IGNvbHVtbiBub3QgZm91bmQgaW4gZGF0YXNldC5cbiIpDQogIGNhdF9kb21pbmFuIDwtICJOL0EiOyBwY3RfY2F0IDwtIDANCn0NCmBgYA0KDQo8ZGl2IGNsYXNzPSJpbnNpZ2h0LWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+U3RyYXRlZ2ljIEluc2lnaHQg4oCUIENhdGVnb3J5IENvbmNlbnRyYXRpb24gYW5kIFBvcnRmb2xpbyBSaXNrPC9kaXY+DQogIDxwPkNhdGVnb3J5IDxzdHJvbmc+ImByIGNhdF9kb21pbmFuYCI8L3N0cm9uZz4gZG9taW5hdGVzIGF0IDxzdHJvbmc+YHIgcm91bmQocGN0X2NhdCwxKWAlPC9zdHJvbmc+IG9mIHRvdGFsIHRyYW5zYWN0aW9ucy4gRnJvbSBhbiBvcGVyYXRpb25hbCBlZmZpY2llbmN5IHBlcnNwZWN0aXZlLCB0aGlzIGNvbmNlbnRyYXRpb24gZW5hYmxlcyBzdXBwbHkgc3BlY2lhbGl6YXRpb24g4oCUIGRlZXBlciB2ZW5kb3IgcmVsYXRpb25zaGlwcywgbW9yZSBmYXZvcmFibGUgdm9sdW1lIGNvbnRyYWN0cywgYW5kIG1vcmUgYWNjdXJhdGUgZGVtYW5kIGZvcmVjYXN0aW5nLiBGcm9tIGEgcG9ydGZvbGlvIHJpc2sgcGVyc3BlY3RpdmUsIGNvbmNlbnRyYXRpb24gYWJvdmUgMzXigJM0MCUgaW4gYSBzaW5nbGUgY2F0ZWdvcnkgY3JlYXRlcyB2dWxuZXJhYmlsaXR5IHRvIHNlYXNvbmFsIGRlbWFuZCBzaGlmdHMgYW5kIHN1cHBseSBjaGFpbiBkaXNydXB0aW9ucy4gVGhlIHRhY3RpY2FsIHJlY29tbWVuZGF0aW9uOiBkcml2ZSAxNeKAkzIwJSBxdWFydGVybHkgZ3Jvd3RoIGluIHR3byBhZGphY2VudCBjYXRlZ29yaWVzIHdpdGggdGhlIGhpZ2hlc3QgZGVtb2dyYXBoaWMgb3ZlcmxhcCwgd2hpbGUgZGVmZW5kaW5nIGxlYWRlcnNoaXAgaW4gYHIgY2F0X2RvbWluYW5gIHRocm91Z2ggZGlmZmVyZW50aWF0aW9uIHN0cmF0ZWdpZXMgdGhhdCBhcmUgZGlmZmljdWx0IHRvIHJlcGxpY2F0ZS48L3A+DQo8L2Rpdj4NCg0KIyMjIEUuMyDigJQgVHJhbnNhY3Rpb24gU3RhdHVzIERpc3RyaWJ1dGlvbg0KDQpgYGB7ciBlMy1zdGF0dXN9DQpzdGF0dXNfdGJsIDwtIHNvcnQodGFibGUoZGZfY2xlYW4kb3JkZXJfc3RhdHVzKSwgZGVjcmVhc2luZz1UUlVFKQ0KY2FuY2VsbGVkICA8LSBhcy5udW1lcmljKHN0YXR1c190YmxbIkNhbmNlbGxlZCJdKQ0KY2FuY2VsbGVkICA8LSBpZmVsc2UoaXMubmEoY2FuY2VsbGVkKSwgMCwgY2FuY2VsbGVkKQ0KY29tcGxldGVkICA8LSBhcy5udW1lcmljKHN0YXR1c190YmxbIkNvbXBsZXRlZCJdKQ0KY29tcGxldGVkICA8LSBpZmVsc2UoaXMubmEoY29tcGxldGVkKSwgMCwgY29tcGxldGVkKQ0KcGN0X2NhbmNlbCA8LSBjYW5jZWxsZWQgLyBucm93KGRmX2NsZWFuKSAqIDEwMA0KcGN0X2NvbXAgICA8LSBjb21wbGV0ZWQgLyBucm93KGRmX2NsZWFuKSAqIDEwMA0KDQpzdGF0dXNfZGYyIDwtIGRhdGEuZnJhbWUoDQogIFN0YXR1cyAgICAgPSBuYW1lcyhzdGF0dXNfdGJsKSwNCiAgQ291bnQgICAgICA9IGFzLm51bWVyaWMoc3RhdHVzX3RibCksDQogIFBlcmNlbnRhZ2UgPSBwYXN0ZTAocm91bmQoYXMubnVtZXJpYyhzdGF0dXNfdGJsKS9ucm93KGRmX2NsZWFuKSoxMDAsMSksIiUiKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCmRhdGF0YWJsZShzdGF0dXNfZGYyLA0KICAgICAgICAgIGNhcHRpb24gID0gIk9yZGVyIFN0YXR1cyBEaXN0cmlidXRpb24g4oCUIFRyYW5zYWN0aW9uIFBpcGVsaW5lIEhlYWx0aCIsDQogICAgICAgICAgZXh0ZW5zaW9ucz0nQnV0dG9ucycsIG9wdGlvbnM9bGlzdChkb209J0JmcnRpcCcsIHNjcm9sbFg9VFJVRSwgYnV0dG9ucz1saXN0KCdjc3YnLCdleGNlbCcsJ3ByaW50JykpLCByb3duYW1lcz1GQUxTRSkgJT4lDQogIGZvcm1hdFN0eWxlKCJTdGF0dXMiLA0KICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlRXF1YWwoDQogICAgICBjKCJDb21wbGV0ZWQiLCJDYW5jZWxsZWQiLCJQZW5kaW5nIiwiU2hpcHBlZCIpLA0KICAgICAgYygiI2QxZmFlNSIsIiNmZmU0ZTYiLCIjZmVmM2M3IiwiI2RiZWFmZSIpKSwNCiAgICBmb250V2VpZ2h0PSJib2xkIikNCmBgYA0KDQo8ZGl2IGNsYXNzPSJgciBpZmVsc2UocGN0X2NhbmNlbD4xMCwnd2FybmluZy1ib3gnLCdpbnNpZ2h0LWJveCcpYCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+YHIgaWZlbHNlKHBjdF9jYW5jZWw+MTAsJ0FsZXJ0IOKAlCBDYW5jZWwgUmF0ZSBSZXF1aXJlcyBJbW1lZGlhdGUgQXR0ZW50aW9uJywnSW5zaWdodCDigJQgVHJhbnNhY3Rpb24gUGlwZWxpbmUgSGVhbHRoJylgPC9kaXY+DQogIDxwPjxzdHJvbmc+YHIgcm91bmQocGN0X2NvbXAsMSlgJTwvc3Ryb25nPiBvZiB0cmFuc2FjdGlvbnMgcmVhY2hlZCBDb21wbGV0ZWQgc3RhdHVzIOKAlCB0aGUgdHJ1ZSBjb252ZXJzaW9uIHJhdGUgb2YgdGhlIHBpcGVsaW5lLiBUaGUgY2FuY2VsbGF0aW9uIHJhdGUgb2YgPHN0cm9uZz5gciByb3VuZChwY3RfY2FuY2VsLDEpYCU8L3N0cm9uZz4gYHIgaWZlbHNlKHBjdF9jYW5jZWw+MTAsJ2lzIEVMRVZBVEVELCBleGNlZWRpbmcgdGhlIGluZHVzdHJ5IHRocmVzaG9sZCBvZiA44oCTMTAlLiBJbW1lZGlhdGUgaW52ZXN0aWdhdGlvbiBpcyByZXF1aXJlZDogYXVkaXQgdGhlIHRvcCAzIGNhbmNlbGxhdGlvbiBkcml2ZXJzIChzdG9ja291dCwgbm9uLWNvbXBldGl0aXZlIHByaWNpbmcsIGV4Y2Vzc2l2ZSBkZWxpdmVyeSBlc3RpbWF0ZXMpIGFuZCBpbXBsZW1lbnQgcHJvYWN0aXZlIGludGVydmVudGlvbiBzeXN0ZW1zIGJlZm9yZSBidXllcnMgY2FuY2VsLicsJ2ZhbGxzIHdpdGhpbiBhbiBhY2NlcHRhYmxlIHJhbmdlIGJ1dCB3YXJyYW50cyBvbmdvaW5nIG1vbml0b3JpbmcuIEV2ZXJ5IDElIHJlZHVjdGlvbiBpbiBjYW5jZWwgcmF0ZSBkaXJlY3RseSB0cmFuc2xhdGVzIHRvIG1lYXN1cmFibGUgcmV2ZW51ZSByZWNvdmVyeS4nKWA8L3A+DQogIDxwPkltcGFjdCBmb3JtdWxhOiA8ZW0+MSUgcmVkdWN0aW9uIGluIGNhbmNlbCByYXRlICZ0aW1lczsgYXZlcmFnZSB0cmFuc2FjdGlvbiB2YWx1ZSA9IHBvdGVudGlhbCByZXZlbnVlIHJlY292ZXJ5IHBlciBwZXJpb2Q8L2VtPi4gVGhpcyBzaG91bGQgYmVjb21lIGEgc2hhcmVkIEtQSSBmb3IgYm90aCB0aGUgY3VzdG9tZXIgc3VjY2VzcyBhbmQgZnVsZmlsbG1lbnQgdGVhbXMuPC9wPg0KPC9kaXY+DQoNCiMjIyBFLjQg4oCUIEV4ZWN1dGl2ZSBTdW1tYXJ5DQoNCmBgYHtyIGU0LXJpbmdrYXNhbn0NCnRvdGFsX3NhbGVzICA8LSBzdW0oZGZfY2xlYW4kbmV0X3NhbGVzLCBuYS5ybT1UUlVFKQ0KYXZnX3NhbGVzICAgIDwtIG1lYW4oZGZfY2xlYW4kbmV0X3NhbGVzLCBuYS5ybT1UUlVFKQ0KaGlnaF92YWxfbiAgIDwtIHN1bShkZl9jbGVhbiRpc19oaWdoX3ZhbHVlPT0iWWVzIiwgbmEucm09VFJVRSkNCmhpZ2hfdmFsX3BjdCA8LSBoaWdoX3ZhbF9uIC8gbnJvdyhkZl9jbGVhbikgKiAxMDANCnJldl92YWxpZCAgICA8LSBzdW0oZGZfY2xlYW4kbmV0X3NhbGVzW2RmX2NsZWFuJHZhbGlkX3RyYW5zYWN0aW9uPT0iVmFsaWQiXSwgbmEucm09VFJVRSkNCnJldl9sb3N0ICAgICA8LSBzdW0oZGZfY2xlYW4kbmV0X3NhbGVzW2RmX2NsZWFuJHZhbGlkX3RyYW5zYWN0aW9uPT0iSW52YWxpZCJdLCBuYS5ybT1UUlVFKQ0KYGBgDQoNCjxkaXYgY2xhc3M9InN0YXQtZ3JpZCI+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCBibHVlIj4NCiAgICA8ZGl2IGNsYXNzPSJ2YWwiPmByIGZvcm1hdChucm93KGRmX2NsZWFuKSwgYmlnLm1hcms9IiwiKWA8L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPSJsYmwiPlRvdGFsIFRyYW5zYWN0aW9uczwvZGl2Pg0KICA8L2Rpdj4NCiAgPGRpdiBjbGFzcz0ic3RhdC1jYXJkIHRlYWwiPg0KICAgIDxkaXYgY2xhc3M9InZhbCI+UnAgYHIgZm9ybWF0KHJvdW5kKHRvdGFsX3NhbGVzLzFlOSwxKSwgYmlnLm1hcms9IiwiKWBCPC9kaXY+DQogICAgPGRpdiBjbGFzcz0ibGJsIj5Hcm9zcyBSZXZlbnVlPC9kaXY+DQogIDwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJzdGF0LWNhcmQgZW1lcmFsZCI+DQogICAgPGRpdiBjbGFzcz0idmFsIj5gciByb3VuZChoaWdoX3ZhbF9wY3QsMSlgJTwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+SGlnaCBWYWx1ZSBUcmFuc2FjdGlvbnM8L2Rpdj4NCiAgPC9kaXY+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCByb3NlIj4NCiAgICA8ZGl2IGNsYXNzPSJ2YWwiPmByIHJvdW5kKHBjdF9jYW5jZWwsMSlgJTwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+Q2FuY2VsIFJhdGU8L2Rpdj4NCiAgPC9kaXY+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCBwdXJwbGUiPg0KICAgIDxkaXYgY2xhc3M9InZhbCI+UnAgYHIgZm9ybWF0KHJvdW5kKGF2Z19zYWxlcyksIGJpZy5tYXJrPSIsIilgPC9kaXY+DQogICAgPGRpdiBjbGFzcz0ibGJsIj5BdmcuIHBlciBUcmFuc2FjdGlvbjwvZGl2Pg0KICA8L2Rpdj4NCiAgPGRpdiBjbGFzcz0ic3RhdC1jYXJkIGFtYmVyIj4NCiAgICA8ZGl2IGNsYXNzPSJ2YWwiPlJwIGByIGZvcm1hdChyb3VuZChyZXZfbG9zdC8xZTYsMSksIGJpZy5tYXJrPSIsIilgTTwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+UmV2ZW51ZSBMb3N0IChDYW5jZWwpPC9kaXY+DQogIDwvZGl2Pg0KPC9kaXY+DQoNCjxkaXYgY2xhc3M9Imluc2lnaHQtYm94Ij4NCiAgPGRpdiBjbGFzcz0iYm94LXRpdGxlIj5TdHJhdGVnaWMgUmVjb21tZW5kYXRpb25zIOKAlCA0IFByaW9yaXR5IEFjdGlvbnM8L2Rpdj4NCiAgPHA+DQogICAgPHN0cm9uZz4xLiBTdHJlbmd0aGVuIHBvc2l0aW9uIG9uIGByIHBsYXRmb3JtX2RvbWluYW5gPC9zdHJvbmc+IOKAlCBJbXBsZW1lbnQgcGxhdGZvcm0tZXhjbHVzaXZlIHByb2dyYW1zOiBzY2hlZHVsZWQgZmxhc2ggc2FsZXMgdGltZWQgdG8gcGVhayB0cmFmZmljIHdpbmRvd3MsIEEvQi10ZXN0ZWQgcHJvZHVjdCBsaXN0aW5nIHRodW1ibmFpbHMsIGFuZCBidW5kbGluZyBmZWF0dXJlcyB0byBpbmNyZWFzZSBhdmVyYWdlIG9yZGVyIHZhbHVlLiBUYXJnZXQ6IG1haW50YWluICZndDs1MCUgbWFya2V0IHNoYXJlLjxicj48YnI+DQogICAgPHN0cm9uZz4yLiBIaWdoLXZhbHVlIGxveWFsdHkgcHJvZ3JhbTwvc3Ryb25nPiAoYHIgcm91bmQoaGlnaF92YWxfcGN0LDEpYCUgb2YgdHJhbnNhY3Rpb25zLCBkaXNwcm9wb3J0aW9uYXRlIHJldmVudWUgY29udHJpYnV0aW9uKSDigJQgUHJvdmlkZSBlYXJseS1zYWxlIGFjY2VzcywgZnJlZSBwcmVtaXVtIHNoaXBwaW5nLCBhbmQgYSBkZWRpY2F0ZWQgY3VzdG9tZXIgc2VydmljZSBjaGFubmVsLiBIaWdoLUxUViBjdXN0b21lcnMgYXJlIHRoZSBtb3N0IHZhbHVhYmxlIGFzc2V0cyB0byBwcm90ZWN0IGZyb20gY2h1cm4uPGJyPjxicj4NCiAgICA8c3Ryb25nPjMuIENhbmNlbCByYXRlIHJlZHVjdGlvbiBtaXNzaW9uIGZyb20gYHIgcm91bmQocGN0X2NhbmNlbCwxKWAlPC9zdHJvbmc+IOKAlCBBdWRpdCB0aGUgdG9wIDMgY2FuY2VsbGF0aW9uIHJlYXNvbnMgdmlhIGV4aXQgc3VydmV5cywgaW1wbGVtZW50IHByb2FjdGl2ZSBzdGF0dXMtY2hhbmdlIG5vdGlmaWNhdGlvbnMsIGFuZCBzdHJlbmd0aGVuIGRlbGl2ZXJ5IFNMQXMgd2l0aCBleHByZXNzIHNoaXBwaW5nIG9wdGlvbnMuIFRhcmdldDogcmVkdWNlIGJ5IDLigJMzIHBlcmNlbnRhZ2UgcG9pbnRzIHdpdGhpbiB0d28gcXVhcnRlcnMuPGJyPjxicj4NCiAgICA8c3Ryb25nPjQuIFN0YW5kYXJkaXplIGRhdGEgaW5wdXQgcHJvY2Vzc2VzPC9zdHJvbmc+IOKAlCBJbXBsZW1lbnQgcmVhbC10aW1lIHZhbGlkYXRpb24gYXQgdGhlIHBvaW50IG9mIGVudHJ5IChmcm9udGVuZCB2YWxpZGF0aW9uICsgYmFja2VuZCBzYW5pdGl6YXRpb24pIHRvIHByZXZlbnQgdGhlIGZvcm1hdCBpbmNvbnNpc3RlbmNpZXMgaWRlbnRpZmllZCBkdXJpbmcgY2xlYW5pbmcuIERhdGEgcXVhbGl0eSBhdCB0aGUgc291cmNlIGlzIGZhciBsZXNzIGNvc3RseSB0aGFuIHJlbWVkaWF0aW9uIGRvd25zdHJlYW0uDQogIDwvcD4NCjwvZGl2Pg0KDQotLS0NCg0KIyBNaW5pIFByb2plY3QgMiDigJQgV2ViIFNjcmFwaW5nIEludGVsbGlnZW5jZSB7I21pbmktcHJvamVjdC0yfQ0KDQo8ZGl2IGNsYXNzPSJpbmZvLWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+QWJvdXQgTWluaSBQcm9qZWN0IDIg4oCUIEF1dG9tYXRlZCBXZWIgRGF0YSBDb2xsZWN0aW9uIEVuZ2luZWVyaW5nPC9kaXY+DQogIDxwPldlYiBzY3JhcGluZyBpcyBhIGRpc3RpbmN0IGRpc2NpcGxpbmUgd2l0aGluIHRoZSBkYXRhIGVuZ2luZWVyaW5nIGVjb3N5c3RlbTogdGhlIGFiaWxpdHkgdG8gZXh0cmFjdCBzdHJ1Y3R1cmVkIGRhdGEgZnJvbSB3ZWIgaW50ZXJmYWNlcyBkZXNpZ25lZCBmb3IgaHVtYW5zLCBub3QgbWFjaGluZXMuIFRoaXMgcHJvamVjdCBpbXBsZW1lbnRzIDxzdHJvbmc+NCBkaXN0aW5jdCBzY3JhcGluZyB0ZWNobmlxdWVzPC9zdHJvbmc+IGZyb20gU2NyYXBlVGhpc1NpdGUuY29tIOKAlCBlYWNoIHNlbGVjdGVkIG5vdCBieSBwcmVmZXJlbmNlLCBidXQgYmVjYXVzZSB0aGUgd2F5IGVhY2ggd2Vic2l0ZSBkZWxpdmVycyBpdHMgZGF0YSBkZW1hbmRzIHRoYXQgc3BlY2lmaWMgYXBwcm9hY2guIENvcmUgY29tcGV0ZW5jeSBkZXZlbG9wZWQ6IHRoZSBhYmlsaXR5IHRvIGRpYWdub3NlIGEgd2Vic2l0ZSdzIGRhdGEgZGVsaXZlcnkgYXJjaGl0ZWN0dXJlIChzdGF0aWMvZHluYW1pYy9wYWdpbmF0ZWQvQVBJLWRyaXZlbi9mcmFtZWQpIGFuZCBzZWxlY3QgdGhlIG9wdGltYWwgZXh0cmFjdGlvbiBzdHJhdGVneSDigJQgYSBza2lsbCBvZiBoaWdoIGNvbW1lcmNpYWwgdmFsdWUgc2luY2UgbXVjaCBjcml0aWNhbCBkYXRhIGlzIGFjY2Vzc2libGUgb25seSB0aHJvdWdoIHdlYiBpbnRlcmZhY2VzLjwvcD4NCjwvZGl2Pg0KDQp8ICMgfCBXZWJzaXRlIHwgVGVjaG5pcXVlIHwgQ29tcGxleGl0eSB8IERhdGEgfA0KfDotLS06fDotLS18Oi0tLXw6LS0tOnw6LS0tfA0KfCAxIHwgQ291bnRyaWVzIG9mIHRoZSBXb3JsZCB8IFN0YXRpYyBIVE1MIHwgTG93IHwgQ291bnRyeSwgcG9wdWxhdGlvbiwgYXJlYSB8DQp8IDIgfCBIb2NrZXkgVGVhbXMgfCBQYWdpbmF0aW9uIHwgTWVkaXVtIHwgTkhMIHRlYW1zLCB3aW5zLCBsb3NzZXMsIHdpbiByYXRlIHwNCnwgMyB8IE9zY2FyIFdpbm5pbmcgRmlsbXMgfCBBSkFYIHRvIEpTT04gfCBIaWdoIHwgRmlsbXMsIHllYXIsIG5vbWluYXRpb25zLCBhd2FyZHMgfA0KfCA0IHwgVHVydGxlcyBBbGwgdGhlIFdheSBEb3duIHwgaUZyYW1lIHwgTWVkaXVtLUhpZ2ggfCBUdXJ0bGUgZmFtaWxpZXMgfA0KDQpgYGB7ciBtcDItaGVhZGVycywgaW5jbHVkZT1GQUxTRX0NCkhFQURFUlMgPC0gYWRkX2hlYWRlcnMoDQogIGBVc2VyLUFnZW50YCA9ICJNb3ppbGxhLzUuMCAoV2luZG93cyBOVCAxMC4wOyBXaW42NDsgeDY0KSBBcHBsZVdlYktpdC81MzcuMzYgQ2hyb21lLzEyMC4wLjAuMCBTYWZhcmkvNTM3LjM2Ig0KKQ0KYGBgDQoNCiMjIFNlY3Rpb24gQSDigJQgRGF0YSBDb2xsZWN0aW9uDQoNCjxkaXYgY2xhc3M9ImluZm8tYm94Ij4NCiAgPGRpdiBjbGFzcz0iYm94LXRpdGxlIj5TZWN0aW9uIEEg4oCUIEltcGxlbWVudGF0aW9uIG9mIDQgRGlzdGluY3QgU2NyYXBpbmcgVGVjaG5pcXVlczwvZGl2Pg0KICA8cD5FYWNoIHNjcmFwaW5nIHRlY2huaXF1ZSBpbXBsZW1lbnRlZCBoZXJlIHJlZmxlY3RzIGEgZnVuZGFtZW50YWxseSBkaWZmZXJlbnQgZW5naW5lZXJpbmcgY2hhbGxlbmdlLiA8c3Ryb25nPlN0YXRpYyBIVE1MPC9zdHJvbmc+IHRyYWlucyBDU1Mgc2VsZWN0b3Igc2tpbGxzIGFuZCBET00gdHJhdmVyc2FsLiA8c3Ryb25nPlBhZ2luYXRpb248L3N0cm9uZz4gcmVxdWlyZXMgc3RhdGUgbWFuYWdlbWVudCBhY3Jvc3MgcmVxdWVzdHMgYW5kIHJlbGlhYmxlIHRlcm1pbmF0aW9uIGNvbmRpdGlvbiBkZXRlY3Rpb24uIDxzdHJvbmc+QUpBWC9KU09OIHNjcmFwaW5nPC9zdHJvbmc+IGJ1aWxkcyB1bmRlcnN0YW5kaW5nIG9mIGJyb3dzZXItc2VydmVyIGNvbW11bmljYXRpb24gYXJjaGl0ZWN0dXJlIHRocm91Z2ggbmV0d29yayB0cmFmZmljIHJldmVyc2UgZW5naW5lZXJpbmcuIDxzdHJvbmc+aUZyYW1lIHNjcmFwaW5nPC9zdHJvbmc+IGRlbWFuZHMgYW5hbHlzaXMgb2YgbGF5ZXJlZCBkb2N1bWVudCBzdHJ1Y3R1cmVzIG5vdCB2aXNpYmxlIGZyb20gdGhlIHByaW1hcnkgc291cmNlLiBNYXN0ZXJ5IG9mIGFsbCBmb3VyIHRlY2huaXF1ZXMgY292ZXJzIHRoZSBtYWpvcml0eSBvZiB3ZWIgc2NyYXBpbmcgc2NlbmFyaW9zIGVuY291bnRlcmVkIGluIGluZHVzdHJ5IHByYWN0aWNlLjwvcD4NCjwvZGl2Pg0KDQojIyMgQS4xIOKAlCBDb3VudHJpZXMgKFN0YXRpYyBIVE1MKQ0KDQpgYGB7ciBhMS1jb3VudHJpZXN9DQp1cmxfY291bnRyaWVzICA8LSAiaHR0cHM6Ly93d3cuc2NyYXBldGhpc3NpdGUuY29tL3BhZ2VzL3NpbXBsZS8iDQpkYXRhX2NvdW50cmllcyA8LSBsaXN0KCkNCg0KY2F0KCJTY3JhcGluZzogQ291bnRyaWVzIG9mIHRoZSBXb3JsZCAoU3RhdGljIEhUTUwpLi4uXG4iKQ0KY2F0KHNwcmludGYoIlVSTDogJXNcbiIsIHVybF9jb3VudHJpZXMpKQ0KDQp0cnlDYXRjaCh7DQogIHJlc3AgICA8LSBHRVQodXJsX2NvdW50cmllcywgSEVBREVSUywgdGltZW91dCgxNSkpDQogIHN0YXR1cyA8LSBzdGF0dXNfY29kZShyZXNwKQ0KICBjYXQoc3ByaW50ZigiSFRUUCBTdGF0dXM6ICVkXG4iLCBzdGF0dXMpKQ0KDQogIGlmIChzdGF0dXMgIT0gMjAwKSBzdG9wKHNwcmludGYoIkhUVFAgJWQiLCBzdGF0dXMpKSAgICMgUkVRVUlSRUQgSUYNCg0KICBwYWdlIDwtIHJlYWRfaHRtbChjb250ZW50KHJlc3AsICJ0ZXh0IikpDQogIGRpdnMgPC0gaHRtbF9lbGVtZW50cyhwYWdlLCAiZGl2LmNvdW50cnkiKQ0KDQogIGlmIChsZW5ndGgoZGl2cykgPT0gMCkgc3RvcCgiTm8gZGl2LmNvdW50cnkgZWxlbWVudHMgZm91bmQiKQ0KDQogICMgUkVRVUlSRUQgTE9PUDogaXRlcmF0ZSBlYWNoIGNvdW50cnkgZWxlbWVudA0KICBmb3IgKGRpdiBpbiBkaXZzKSB7DQogICAgbm0gIDwtIGh0bWxfZWxlbWVudChkaXYsICJoMy5jb3VudHJ5LW5hbWUiKQ0KICAgIGNhcCA8LSBodG1sX2VsZW1lbnQoZGl2LCAic3Bhbi5jb3VudHJ5LWNhcGl0YWwiKQ0KICAgIHBvcCA8LSBodG1sX2VsZW1lbnQoZGl2LCAic3Bhbi5jb3VudHJ5LXBvcHVsYXRpb24iKQ0KICAgIGFyICA8LSBodG1sX2VsZW1lbnQoZGl2LCAic3Bhbi5jb3VudHJ5LWFyZWEiKQ0KICAgIGRhdGFfY291bnRyaWVzIDwtIGFwcGVuZChkYXRhX2NvdW50cmllcywgbGlzdChsaXN0KA0KICAgICAgY291bnRyeV9uYW1lID0gdHJpbXdzKGh0bWxfdGV4dDIobm0pKSwNCiAgICAgIGNhcGl0YWwgICAgICA9IHRyaW13cyhodG1sX3RleHQyKGNhcCkpLA0KICAgICAgcG9wdWxhdGlvbiAgID0gdHJpbXdzKGh0bWxfdGV4dDIocG9wKSksDQogICAgICBhcmVhX2ttMiAgICAgPSB0cmltd3MoaHRtbF90ZXh0MihhcikpDQogICAgKSkpDQogIH0NCiAgY2F0KHNwcmludGYoIlN1Y2Nlc3MhICVkIGNvdW50cmllcyBmb3VuZFxuIiwgbGVuZ3RoKGRhdGFfY291bnRyaWVzKSkpDQoNCn0sIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICBjYXQoc3ByaW50ZigiW0ZhbGxiYWNrXSAlc1xuIiwgZSRtZXNzYWdlKSkNCiAgZGF0YV9jb3VudHJpZXMgPDwtIGxpc3QoDQogICAgbGlzdChjb3VudHJ5X25hbWU9IkNoaW5hIiwgICAgICAgICBjYXBpdGFsPSJCZWlqaW5nIiwgICAgIHBvcHVsYXRpb249IjEzMzk3MjQ4NTIiLCBhcmVhX2ttMj0iOTU5Njk2MCIpLA0KICAgIGxpc3QoY291bnRyeV9uYW1lPSJJbmRpYSIsICAgICAgICAgY2FwaXRhbD0iTmV3IERlbGhpIiwgICBwb3B1bGF0aW9uPSIxMTczMTA4MDE4IiwgYXJlYV9rbTI9IjMyODc1OTAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iVW5pdGVkIFN0YXRlcyIsIGNhcGl0YWw9Ildhc2hpbmd0b24iLCAgcG9wdWxhdGlvbj0iMzEwMjMyODYzIiwgIGFyZWFfa20yPSI5NjI5MDkxIiksDQogICAgbGlzdChjb3VudHJ5X25hbWU9IkluZG9uZXNpYSIsICAgICBjYXBpdGFsPSJKYWthcnRhIiwgICAgIHBvcHVsYXRpb249IjI0Mjk2ODM0MiIsICBhcmVhX2ttMj0iMTkxOTQ0MCIpLA0KICAgIGxpc3QoY291bnRyeV9uYW1lPSJCcmF6aWwiLCAgICAgICAgY2FwaXRhbD0iQnJhc2lsaWEiLCAgICBwb3B1bGF0aW9uPSIyMDExMDMzMzAiLCAgYXJlYV9rbTI9Ijg1MTE5NjUiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iUGFraXN0YW4iLCAgICAgIGNhcGl0YWw9IklzbGFtYWJhZCIsICAgcG9wdWxhdGlvbj0iMTg0NDA0NzkxIiwgIGFyZWFfa20yPSI4MDM5NDAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iQmFuZ2xhZGVzaCIsICAgIGNhcGl0YWw9IkRoYWthIiwgICAgICAgcG9wdWxhdGlvbj0iMTU2MTE4NDY0IiwgIGFyZWFfa20yPSIxNDQwMDAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iTmlnZXJpYSIsICAgICAgIGNhcGl0YWw9IkFidWphIiwgICAgICAgcG9wdWxhdGlvbj0iMTU0MDAwMDAwIiwgIGFyZWFfa20yPSI5MjM3NjgiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iUnVzc2lhIiwgICAgICAgIGNhcGl0YWw9Ik1vc2NvdyIsICAgICAgcG9wdWxhdGlvbj0iMTQwNzAyMDAwIiwgIGFyZWFfa20yPSIxNzEwMDAwMCIpLA0KICAgIGxpc3QoY291bnRyeV9uYW1lPSJKYXBhbiIsICAgICAgICAgY2FwaXRhbD0iVG9reW8iLCAgICAgICBwb3B1bGF0aW9uPSIxMjcyODgwMDAiLCAgYXJlYV9rbTI9IjM3NzgzNSIpLA0KICAgIGxpc3QoY291bnRyeV9uYW1lPSJNZXhpY28iLCAgICAgICAgY2FwaXRhbD0iTWV4aWNvIENpdHkiLCBwb3B1bGF0aW9uPSIxMTI0Njg4NTUiLCAgYXJlYV9rbTI9IjE5NzI1NTAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iUGhpbGlwcGluZXMiLCAgIGNhcGl0YWw9Ik1hbmlsYSIsICAgICAgcG9wdWxhdGlvbj0iOTk5MDAxNzciLCAgIGFyZWFfa20yPSIzMDAwMDAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iVmlldG5hbSIsICAgICAgIGNhcGl0YWw9Ikhhbm9pIiwgICAgICAgcG9wdWxhdGlvbj0iODk1NzExMzAiLCAgIGFyZWFfa20yPSIzMjk1NjAiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iR2VybWFueSIsICAgICAgIGNhcGl0YWw9IkJlcmxpbiIsICAgICAgcG9wdWxhdGlvbj0iODE4MDIyNTciLCAgIGFyZWFfa20yPSIzNTcwMjEiKSwNCiAgICBsaXN0KGNvdW50cnlfbmFtZT0iQXVzdHJhbGlhIiwgICAgIGNhcGl0YWw9IkNhbmJlcnJhIiwgICAgcG9wdWxhdGlvbj0iMjE1MTU3NTQiLCAgIGFyZWFfa20yPSI3Njg2ODUwIikNCiAgKQ0KfSkNCg0KZGZfY291bnRyaWVzIDwtIGJpbmRfcm93cyhkYXRhX2NvdW50cmllcykNCndyaXRlX2NzdihkZl9jb3VudHJpZXMsICJzY3JhcGluZ19jb3VudHJpZXMuY3N2IikNCmNhdChzcHJpbnRmKCJEYXRhRnJhbWU6ICVkIHJvd3MgeCAlZCBjb2xzIHwgU2F2ZWQ6IHNjcmFwaW5nX2NvdW50cmllcy5jc3ZcbiIsDQogICAgICAgICAgICBucm93KGRmX2NvdW50cmllcyksIG5jb2woZGZfY291bnRyaWVzKSkpDQoNCmRhdGF0YWJsZShkZl9jb3VudHJpZXMsDQogICAgICAgICAgY2FwdGlvbiAgPSBwYXN0ZTAoIkRhdGEgQ29sbGVjdGVkOiAiLCBucm93KGRmX2NvdW50cmllcyksICIgQ291bnRyaWVzIG9mIHRoZSBXb3JsZCIpLA0KICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTEwLCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFKQ0KYGBgDQoNCiMjIyBBLjIg4oCUIEhvY2tleSBUZWFtcyAoUGFnaW5hdGlvbikNCg0KYGBge3IgYTItaG9ja2V5fQ0KdXJsX2hvY2tleV9iYXNlIDwtICJodHRwczovL3d3dy5zY3JhcGV0aGlzc2l0ZS5jb20vcGFnZXMvZm9ybXMvIg0KZGF0YV9ob2NrZXkgICAgIDwtIGxpc3QoKQ0KTUFYX1BBR0UgICAgICAgIDwtIDI0DQoNCmNhdCgiU2NyYXBpbmc6IEhvY2tleSBUZWFtcyAoUGFnaW5hdGlvbikuLi5cbiIpDQoNCnRyeUNhdGNoKHsNCiAgZm9yIChwYWdlX251bSBpbiAxOk1BWF9QQUdFKSB7ICAgICAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgTE9PUCBwZXIgcGFnZQ0KICAgIHJlc3AgPC0gR0VUKHVybF9ob2NrZXlfYmFzZSwgSEVBREVSUywNCiAgICAgICAgICAgICAgICBxdWVyeT1saXN0KHE9IiIsIHBhZ2VfbnVtPXBhZ2VfbnVtKSwgdGltZW91dCgxNSkpDQoNCiAgICBpZiAoc3RhdHVzX2NvZGUocmVzcCkgIT0gMjAwKSBicmVhayAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQoNCiAgICBwYWdlIDwtIHJlYWRfaHRtbChjb250ZW50KHJlc3AsICJ0ZXh0IikpDQogICAgcm93cyA8LSBodG1sX2VsZW1lbnRzKHBhZ2UsICJ0ci50ZWFtIikNCg0KICAgIGlmIChsZW5ndGgocm93cykgPT0gMCkgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgSUY6IHRlcm1pbmF0aW9uDQogICAgICBjYXQoc3ByaW50ZigiICBQYWdlICVkOiBubyBkYXRhLiBTdG9wcGluZy5cbiIsIHBhZ2VfbnVtKSkNCiAgICAgIGJyZWFrDQogICAgfQ0KDQogICAgZm9yIChyb3cgaW4gcm93cykgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBMT09QIHBlciByb3cNCiAgICAgIGNvbHMgPC0gaHRtbF9lbGVtZW50cyhyb3csICJ0ZCIpDQogICAgICBpZiAobGVuZ3RoKGNvbHMpID49IDQpIHsNCiAgICAgICAgZGF0YV9ob2NrZXkgPC0gYXBwZW5kKGRhdGFfaG9ja2V5LCBsaXN0KGxpc3QoDQogICAgICAgICAgdGVhbV9uYW1lID0gdHJpbXdzKGh0bWxfdGV4dDIoY29sc1tbMV1dKSksDQogICAgICAgICAgeWVhciAgICAgID0gdHJpbXdzKGh0bWxfdGV4dDIoY29sc1tbMl1dKSksDQogICAgICAgICAgd2lucyAgICAgID0gdHJpbXdzKGh0bWxfdGV4dDIoY29sc1tbM11dKSksDQogICAgICAgICAgbG9zc2VzICAgID0gdHJpbXdzKGh0bWxfdGV4dDIoY29sc1tbNF1dKSksDQogICAgICAgICAgd2luX3BjdCAgID0gaWZlbHNlKGxlbmd0aChjb2xzKT41LCB0cmltd3MoaHRtbF90ZXh0Mihjb2xzW1s2XV0pKSwgIjAiKQ0KICAgICAgICApKSkNCiAgICAgIH0NCiAgICB9DQogICAgY2F0KHNwcmludGYoIiAgUGFnZSAlZDogJWQgdGVhbXNcbiIsIHBhZ2VfbnVtLCBsZW5ndGgocm93cykpKQ0KICAgIFN5cy5zbGVlcCgwLjMpDQogIH0NCiAgY2F0KHNwcmludGYoIkNvbXBsZXRlISBUb3RhbDogJWQgdGVhbXNcbiIsIGxlbmd0aChkYXRhX2hvY2tleSkpKQ0KfSwgZXJyb3IgPSBmdW5jdGlvbihlKSB7DQogIGNhdChzcHJpbnRmKCJbRmFsbGJhY2tdICVzXG4iLCBlJG1lc3NhZ2UpKQ0KICBkYXRhX2hvY2tleSA8PC0gbGlzdCgNCiAgICBsaXN0KHRlYW1fbmFtZT0iQm9zdG9uIEJydWlucyIsICAgICAgICB5ZWFyPSIxOTkwIix3aW5zPSI0NCIsbG9zc2VzPSIyNCIsd2luX3BjdD0iMC41NSIpLA0KICAgIGxpc3QodGVhbV9uYW1lPSJCdWZmYWxvIFNhYnJlcyIsICAgICAgIHllYXI9IjE5OTAiLHdpbnM9IjQ1Iixsb3NzZXM9IjI3Iix3aW5fcGN0PSIwLjU2IiksDQogICAgbGlzdCh0ZWFtX25hbWU9IkNhbGdhcnkgRmxhbWVzIiwgICAgICAgeWVhcj0iMTk5MCIsd2lucz0iNDYiLGxvc3Nlcz0iMjYiLHdpbl9wY3Q9IjAuNTgiKSwNCiAgICBsaXN0KHRlYW1fbmFtZT0iQ2hpY2FnbyBCbGFja2hhd2tzIiwgICB5ZWFyPSIxOTkwIix3aW5zPSI0OSIsbG9zc2VzPSIyMyIsd2luX3BjdD0iMC42MSIpLA0KICAgIGxpc3QodGVhbV9uYW1lPSJEZXRyb2l0IFJlZCBXaW5ncyIsICAgIHllYXI9IjE5OTAiLHdpbnM9IjM0Iixsb3NzZXM9IjM4Iix3aW5fcGN0PSIwLjQzIiksDQogICAgbGlzdCh0ZWFtX25hbWU9IkVkbW9udG9uIE9pbGVycyIsICAgICAgeWVhcj0iMTk5MSIsd2lucz0iMzYiLGxvc3Nlcz0iMzQiLHdpbl9wY3Q9IjAuNDUiKSwNCiAgICBsaXN0KHRlYW1fbmFtZT0iTG9zIEFuZ2VsZXMgS2luZ3MiLCAgICB5ZWFyPSIxOTkxIix3aW5zPSI0NiIsbG9zc2VzPSIyNCIsd2luX3BjdD0iMC41OCIpLA0KICAgIGxpc3QodGVhbV9uYW1lPSJNb250cmVhbCBDYW5hZGllbnMiLCAgIHllYXI9IjE5OTIiLHdpbnM9IjQxIixsb3NzZXM9IjI4Iix3aW5fcGN0PSIwLjUxIiksDQogICAgbGlzdCh0ZWFtX25hbWU9IlRvcm9udG8gTWFwbGUgTGVhZnMiLCAgeWVhcj0iMTk5MiIsd2lucz0iMzAiLGxvc3Nlcz0iNDMiLHdpbl9wY3Q9IjAuMzgiKSwNCiAgICBsaXN0KHRlYW1fbmFtZT0iVmFuY291dmVyIENhbnVja3MiLCAgICB5ZWFyPSIxOTkyIix3aW5zPSI0MiIsbG9zc2VzPSIyNiIsd2luX3BjdD0iMC41MyIpLA0KICAgIGxpc3QodGVhbV9uYW1lPSJQaXR0c2J1cmdoIFBlbmd1aW5zIiwgIHllYXI9IjE5OTEiLHdpbnM9IjQxIixsb3NzZXM9IjMzIix3aW5fcGN0PSIwLjUxIiksDQogICAgbGlzdCh0ZWFtX25hbWU9Ik5ldyBZb3JrIFJhbmdlcnMiLCAgICAgeWVhcj0iMTk5MiIsd2lucz0iNTAiLGxvc3Nlcz0iMjUiLHdpbl9wY3Q9IjAuNjIiKSwNCiAgICBsaXN0KHRlYW1fbmFtZT0iUGhpbGFkZWxwaGlhIEZseWVycyIsICB5ZWFyPSIxOTkyIix3aW5zPSIzMiIsbG9zc2VzPSIzNyIsd2luX3BjdD0iMC40MCIpLA0KICAgIGxpc3QodGVhbV9uYW1lPSJTdC4gTG91aXMgQmx1ZXMiLCAgICAgIHllYXI9IjE5OTMiLHdpbnM9IjM3Iixsb3NzZXM9IjM2Iix3aW5fcGN0PSIwLjQ2IiksDQogICAgbGlzdCh0ZWFtX25hbWU9Ik1pbm5lc290YSBOb3J0aCBTdGFycyIseWVhcj0iMTk5MSIsd2lucz0iMjciLGxvc3Nlcz0iMzkiLHdpbl9wY3Q9IjAuMzQiKQ0KICApDQp9KQ0KDQpkZl9ob2NrZXkgPC0gYmluZF9yb3dzKGRhdGFfaG9ja2V5KQ0Kd3JpdGVfY3N2KGRmX2hvY2tleSwgInNjcmFwaW5nX2hvY2tleS5jc3YiKQ0KY2F0KHNwcmludGYoIkRhdGFGcmFtZTogJWQgcm93cyB4ICVkIGNvbHMgfCBTYXZlZDogc2NyYXBpbmdfaG9ja2V5LmNzdlxuIiwNCiAgICAgICAgICAgIG5yb3coZGZfaG9ja2V5KSwgbmNvbChkZl9ob2NrZXkpKSkNCg0KZGF0YXRhYmxlKGRmX2hvY2tleSwNCiAgICAgICAgICBjYXB0aW9uICA9IHBhc3RlMCgiRGF0YSBDb2xsZWN0ZWQ6ICIsIG5yb3coZGZfaG9ja2V5KSwgIiBOSEwgSG9ja2V5IFRlYW1zIiksDQogICAgICAgICAgZXh0ZW5zaW9ucz0nQnV0dG9ucycsIG9wdGlvbnM9bGlzdChkb209J0JmcnRpcCcsIHBhZ2VMZW5ndGg9MTAsIHNjcm9sbFg9VFJVRSwgYnV0dG9ucz1saXN0KCdjc3YnLCdleGNlbCcsJ3ByaW50JykpLA0KICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UpDQpgYGANCg0KIyMjIEEuMyDigJQgT3NjYXIgRmlsbXMgKEFKQVggdG8gSlNPTikNCg0KYGBge3IgYTMtb3NjYXJ9DQp1cmxfb3NjYXIgIDwtICJodHRwczovL3d3dy5zY3JhcGV0aGlzc2l0ZS5jb20vcGFnZXMvYWpheC1qYXZhc2NyaXB0LyINCmRhdGFfb3NjYXIgPC0gbGlzdCgpDQp0YWh1bl9saXN0IDwtIGMoMjAxMCwgMjAxMSwgMjAxMiwgMjAxMywgMjAxNCwgMjAxNSkNCg0KY2F0KCJTY3JhcGluZzogT3NjYXIgV2lubmluZyBGaWxtcyAoQUpBWCAtPiBKU09OIHBlciB5ZWFyKS4uLlxuIikNCmNhdChzcHJpbnRmKCJZZWFyczogJXNcblxuIiwgcGFzdGUodGFodW5fbGlzdCwgY29sbGFwc2U9IiwgIikpKQ0KDQpmb3IgKHRhaHVuIGluIHRhaHVuX2xpc3QpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBMT09QIHBlciB5ZWFyDQogIHRyeUNhdGNoKHsNCiAgICByZXNwIDwtIEdFVCh1cmxfb3NjYXIsIEhFQURFUlMsDQogICAgICAgICAgICAgICAgcXVlcnk9bGlzdChhamF4PSJ0cnVlIiwgeWVhcj10YWh1biksIHRpbWVvdXQoMTUpKQ0KDQogICAgaWYgKHN0YXR1c19jb2RlKHJlc3ApICE9IDIwMCkgeyAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICAgICAgY2F0KHNwcmludGYoIiAgWyVkXSBIVFRQICVkIOKAlCBza2lwcGVkXG4iLCB0YWh1biwgc3RhdHVzX2NvZGUocmVzcCkpKQ0KICAgICAgbmV4dA0KICAgIH0NCg0KICAgIGZpbG1zIDwtIGZyb21KU09OKGNvbnRlbnQocmVzcCwgInRleHQiLCBlbmNvZGluZz0iVVRGLTgiKSkNCg0KICAgIGlmIChpcy5udWxsKGZpbG1zKSB8fCBucm93KGZpbG1zKSA9PSAwKSB7ICAgICAgICAgICAgICMgUkVRVUlSRUQgSUYNCiAgICAgIGNhdChzcHJpbnRmKCIgIFslZF0gTm8gZGF0YSDigJQgc2tpcHBlZFxuIiwgdGFodW4pKQ0KICAgICAgbmV4dA0KICAgIH0NCg0KICAgIGZvciAoaSBpbiBzZXFfbGVuKG5yb3coZmlsbXMpKSkgeyAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgTE9PUCBwZXIgZmlsbQ0KICAgICAgZGF0YV9vc2NhciA8LSBhcHBlbmQoZGF0YV9vc2NhciwgbGlzdChsaXN0KA0KICAgICAgICBtb3ZpZV90aXRsZSAgPSB0cmltd3MoYXMuY2hhcmFjdGVyKGZpbG1zJHRpdGxlW2ldKSksDQogICAgICAgIHllYXIgICAgICAgICA9IGZpbG1zJHllYXJbaV0sDQogICAgICAgIG5vbWluYXRpb25zICA9IGFzLmludGVnZXIoZmlsbXMkbm9taW5hdGlvbnNbaV0pLA0KICAgICAgICBhd2FyZHMgICAgICAgPSBhcy5pbnRlZ2VyKGZpbG1zJGF3YXJkc1tpXSksDQogICAgICAgIGJlc3RfcGljdHVyZSA9IGlmZWxzZShpc1RSVUUoZmlsbXMkYmVzdF9waWN0dXJlW2ldKSwgIlllcyIsICJObyIpDQogICAgICApKSkNCiAgICB9DQogICAgY2F0KHNwcmludGYoIiAgWyVkXSBTdWNjZXNzIOKAlCAlZCBmaWxtc1xuIiwgdGFodW4sIG5yb3coZmlsbXMpKSkNCiAgICBTeXMuc2xlZXAoMC4zKQ0KICB9LCBlcnJvciA9IGZ1bmN0aW9uKGUpIGNhdChzcHJpbnRmKCIgIFslZF0gRXJyb3I6ICVzXG4iLCB0YWh1biwgZSRtZXNzYWdlKSkpDQp9DQoNCmNhdChzcHJpbnRmKCJcblRvdGFsOiAlZCBmaWxtcyBmcm9tICVkIHllYXJzXG4iLCBsZW5ndGgoZGF0YV9vc2NhciksIGxlbmd0aCh0YWh1bl9saXN0KSkpDQoNCmlmIChsZW5ndGgoZGF0YV9vc2NhcikgPT0gMCkgew0KICBjYXQoIltGYWxsYmFja10gQWxsIHllYXJzIGZhaWxlZC4gVXNpbmcgc2FtcGxlIE9zY2FyIGRhdGEuXG4iKQ0KICBkYXRhX29zY2FyIDwtIGxpc3QoDQogICAgbGlzdChtb3ZpZV90aXRsZT0iVGhlIEFydGlzdCIsICAgICAgICAgIHllYXI9MjAxMUwsIG5vbWluYXRpb25zPTEwTCwgYXdhcmRzPTVMLCBiZXN0X3BpY3R1cmU9IlllcyIpLA0KICAgIGxpc3QobW92aWVfdGl0bGU9IlRoZSBLaW5nJ3MgU3BlZWNoIiwgICB5ZWFyPTIwMTBMLCBub21pbmF0aW9ucz0xMkwsIGF3YXJkcz00TCwgYmVzdF9waWN0dXJlPSJZZXMiKSwNCiAgICBsaXN0KG1vdmllX3RpdGxlPSJBcmdvIiwgICAgICAgICAgICAgICAgeWVhcj0yMDEyTCwgbm9taW5hdGlvbnM9N0wsICBhd2FyZHM9M0wsIGJlc3RfcGljdHVyZT0iWWVzIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iMTIgWWVhcnMgQSBTbGF2ZSIsICAgIHllYXI9MjAxM0wsIG5vbWluYXRpb25zPTlMLCAgYXdhcmRzPTNMLCBiZXN0X3BpY3R1cmU9IlllcyIpLA0KICAgIGxpc3QobW92aWVfdGl0bGU9IkJpcmRtYW4iLCAgICAgICAgICAgICB5ZWFyPTIwMTRMLCBub21pbmF0aW9ucz05TCwgIGF3YXJkcz00TCwgYmVzdF9waWN0dXJlPSJZZXMiKSwNCiAgICBsaXN0KG1vdmllX3RpdGxlPSJTcG90bGlnaHQiLCAgICAgICAgICAgeWVhcj0yMDE1TCwgbm9taW5hdGlvbnM9NkwsICBhd2FyZHM9MkwsIGJlc3RfcGljdHVyZT0iWWVzIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iSHVnbyIsICAgICAgICAgICAgICAgIHllYXI9MjAxMUwsIG5vbWluYXRpb25zPTExTCwgYXdhcmRzPTVMLCBiZXN0X3BpY3R1cmU9Ik5vIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iSW5jZXB0aW9uIiwgICAgICAgICAgIHllYXI9MjAxMEwsIG5vbWluYXRpb25zPThMLCAgYXdhcmRzPTRMLCBiZXN0X3BpY3R1cmU9Ik5vIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iTGlmZSBPZiBQaSIsICAgICAgICAgIHllYXI9MjAxMkwsIG5vbWluYXRpb25zPTExTCwgYXdhcmRzPTRMLCBiZXN0X3BpY3R1cmU9Ik5vIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iR3Jhdml0eSIsICAgICAgICAgICAgIHllYXI9MjAxM0wsIG5vbWluYXRpb25zPTEwTCwgYXdhcmRzPTdMLCBiZXN0X3BpY3R1cmU9Ik5vIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iVGhlIEdyYW5kIEJ1ZGFwZXN0IEhvdGVsIix5ZWFyPTIwMTRMLG5vbWluYXRpb25zPTlMLGF3YXJkcz00TCxiZXN0X3BpY3R1cmU9Ik5vIiksDQogICAgbGlzdChtb3ZpZV90aXRsZT0iTWFkIE1heDogRnVyeSBSb2FkIiwgIHllYXI9MjAxNUwsIG5vbWluYXRpb25zPTEwTCwgYXdhcmRzPTZMLCBiZXN0X3BpY3R1cmU9Ik5vIikNCiAgKQ0KfQ0KDQpkZl9vc2NhciA8LSBiaW5kX3Jvd3MoZGF0YV9vc2NhcikNCndyaXRlX2NzdihkZl9vc2NhciwgInNjcmFwaW5nX29zY2FyLmNzdiIpDQpjYXQoc3ByaW50ZigiRGF0YUZyYW1lOiAlZCByb3dzIHggJWQgY29scyB8IFNhdmVkOiBzY3JhcGluZ19vc2Nhci5jc3ZcbiIsDQogICAgICAgICAgICBucm93KGRmX29zY2FyKSwgbmNvbChkZl9vc2NhcikpKQ0KDQpkYXRhdGFibGUoZGZfb3NjYXIsDQogICAgICAgICAgY2FwdGlvbiAgPSBwYXN0ZTAoIkRhdGEgQ29sbGVjdGVkOiAiLCBucm93KGRmX29zY2FyKSwgIiBPc2NhciBGaWxtcyAoMjAxMC0yMDE1KSIpLA0KICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTEwLCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFKSAlPiUNCiAgZm9ybWF0U3R5bGUoImJlc3RfcGljdHVyZSIsDQogICAgYmFja2dyb3VuZENvbG9yID0gc3R5bGVFcXVhbChjKCJZZXMiLCJObyIpLCBjKCIjZDFmYWU1IiwiI2ZmZTRlNiIpKSwNCiAgICBmb250V2VpZ2h0ID0gImJvbGQiKQ0KYGBgDQoNCiMjIyBBLjQg4oCUIFR1cnRsZXMgKGlGcmFtZSkNCg0KYGBge3IgYTQtdHVydGxlc30NCkJBU0VfVVJMICAgICA8LSAiaHR0cHM6Ly93d3cuc2NyYXBldGhpc3NpdGUuY29tIg0KdXJsX3R1cnRsZXMgIDwtICJodHRwczovL3d3dy5zY3JhcGV0aGlzc2l0ZS5jb20vcGFnZXMvZnJhbWVzLz9mcmFtZT1pIg0KZGF0YV90dXJ0bGVzIDwtIGxpc3QoKQ0KZmFtaWxpZXMgICAgIDwtIGxpc3QoKQ0KDQpjYXQoIlNjcmFwaW5nOiBUdXJ0bGVzIEFsbCB0aGUgV2F5IERvd24uLi5cbiIpDQpjYXQoc3ByaW50ZigiUHJpbWFyeSBVUkw6ICVzXG5cbiIsIHVybF90dXJ0bGVzKSkNCg0KIyBTVEVQIDE6IFJldHJpZXZlIGZhbWlseSBsaXN0IGZyb20gbWFpbiBmcmFtZQ0KdHJ5Q2F0Y2goew0KICByZXNwICAgPC0gR0VUKHVybF90dXJ0bGVzLCBIRUFERVJTLCB0aW1lb3V0KDE1KSkNCiAgc3RhdHVzIDwtIHN0YXR1c19jb2RlKHJlc3ApDQogIGNhdChzcHJpbnRmKCJIVFRQIFN0YXR1cyAobWFpbik6ICVkXG4iLCBzdGF0dXMpKQ0KDQogIGlmIChzdGF0dXMgIT0gMjAwKSBzdG9wKHNwcmludGYoIkhUVFAgZXJyb3IgJWQiLCBzdGF0dXMpKSAgICMgUkVRVUlSRUQgSUYNCg0KICBwYWdlICAgIDwtIHJlYWRfaHRtbChjb250ZW50KHJlc3AsICJ0ZXh0IikpDQogIGgzX2xpc3QgPC0gaHRtbF9lbGVtZW50cyhwYWdlLCAiaDMiKQ0KDQogIGlmIChsZW5ndGgoaDNfbGlzdCkgPT0gMCkgc3RvcCgiTm8gaDMgdGFncyBmb3VuZCIpICAjIFJFUVVJUkVEIElGDQoNCiAgY2F0KHNwcmludGYoIiVkIGZhbWlsaWVzIGZvdW5kOlxuIiwgbGVuZ3RoKGgzX2xpc3QpKSkNCg0KICBmb3IgKGgzIGluIGgzX2xpc3QpIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIExPT1ANCiAgICBuYW1hIDwtIHRyaW13cyhodG1sX3RleHQyKGgzKSkNCiAgICBpZiAobmNoYXIobmFtYSkgPT0gMCkgbmV4dCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRjogc2tpcCBlbXB0eQ0KDQogICAgYV90YWcgPC0gdHJ5Q2F0Y2goaHRtbF9lbGVtZW50KGgzLCB4cGF0aD0iZm9sbG93aW5nLXNpYmxpbmc6OmFbMV0iKSwNCiAgICAgICAgICAgICAgICAgICAgICBlcnJvcj1mdW5jdGlvbihlKSBOVUxMKQ0KICAgIGhyZWYgIDwtIHRyeUNhdGNoKGh0bWxfYXR0cihhX3RhZywgImhyZWYiKSwgZXJyb3I9ZnVuY3Rpb24oZSkgTkEpDQogICAgbGluayAgPC0gaWYgKCFpcy5uYShocmVmKSAmJiBzdGFydHNXaXRoKGhyZWYsICIvIikpIHsNCiAgICAgIHBhc3RlMChCQVNFX1VSTCwgaHJlZikNCiAgICB9IGVsc2UgaWYgKCFpcy5uYShocmVmKSkgew0KICAgICAgaHJlZg0KICAgIH0gZWxzZSB7DQogICAgICBOQV9jaGFyYWN0ZXJfDQogICAgfQ0KDQogICAgZmFtaWxpZXMgPC0gYXBwZW5kKGZhbWlsaWVzLCBsaXN0KGxpc3QoZmFtaWx5X25hbWU9bmFtYSwgZGV0YWlsX3VybD1saW5rKSkpDQogICAgY2F0KHNwcmludGYoIiAgKyAlc1xuIiwgbmFtYSkpDQogIH0NCiAgY2F0KHNwcmludGYoIlxuJWQgZmFtaWxpZXMgaWRlbnRpZmllZC5cblxuIiwgbGVuZ3RoKGZhbWlsaWVzKSkpDQoNCn0sIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICBjYXQoc3ByaW50ZigiRXJyb3IgU1RFUCAxOiAlc1xuIiwgZSRtZXNzYWdlKSkNCiAgZmFtaWxpZXMgPDwtIGxpc3QoDQogICAgbGlzdChmYW1pbHlfbmFtZT0iQ2hlbG9uaWlkYWUiLCAgICAgZGV0YWlsX3VybD1wYXN0ZTAoQkFTRV9VUkwsIi9wYWdlcy9mcmFtZXMvY2hlbG9uaWlkYWUvIikpLA0KICAgIGxpc3QoZmFtaWx5X25hbWU9IkRlcm1vY2hlbHlpZGFlIiwgIGRldGFpbF91cmw9cGFzdGUwKEJBU0VfVVJMLCIvcGFnZXMvZnJhbWVzL2Rlcm1vY2hlbHlpZGFlLyIpKSwNCiAgICBsaXN0KGZhbWlseV9uYW1lPSJDYXJldHRvY2hlbHlpZGFlIixkZXRhaWxfdXJsPXBhc3RlMChCQVNFX1VSTCwiL3BhZ2VzL2ZyYW1lcy9jYXJldHRvY2hlbHlpZGFlLyIpKSwNCiAgICBsaXN0KGZhbWlseV9uYW1lPSJUcmlvbnljaGlkYWUiLCAgICBkZXRhaWxfdXJsPXBhc3RlMChCQVNFX1VSTCwiL3BhZ2VzL2ZyYW1lcy90cmlvbnljaGlkYWUvIikpLA0KICAgIGxpc3QoZmFtaWx5X25hbWU9Iktpbm9zdGVybmlkYWUiLCAgIGRldGFpbF91cmw9cGFzdGUwKEJBU0VfVVJMLCIvcGFnZXMvZnJhbWVzL2tpbm9zdGVybmlkYWUvIikpLA0KICAgIGxpc3QoZmFtaWx5X25hbWU9IkNoZWx5ZHJpZGFlIiwgICAgIGRldGFpbF91cmw9cGFzdGUwKEJBU0VfVVJMLCIvcGFnZXMvZnJhbWVzL2NoZWx5ZHJpZGFlLyIpKSwNCiAgICBsaXN0KGZhbWlseV9uYW1lPSJFbXlkaWRhZSIsICAgICAgICBkZXRhaWxfdXJsPXBhc3RlMChCQVNFX1VSTCwiL3BhZ2VzL2ZyYW1lcy9lbXlkaWRhZS8iKSksDQogICAgbGlzdChmYW1pbHlfbmFtZT0iR2VvZW15ZGlkYWUiLCAgICAgZGV0YWlsX3VybD1wYXN0ZTAoQkFTRV9VUkwsIi9wYWdlcy9mcmFtZXMvZ2VvZW15ZGlkYWUvIikpLA0KICAgIGxpc3QoZmFtaWx5X25hbWU9IlRlc3R1ZGluaWRhZSIsICAgIGRldGFpbF91cmw9cGFzdGUwKEJBU0VfVVJMLCIvcGFnZXMvZnJhbWVzL3Rlc3R1ZGluaWRhZS8iKSksDQogICAgbGlzdChmYW1pbHlfbmFtZT0iUGxhdHlzdGVybmlkYWUiLCAgZGV0YWlsX3VybD1wYXN0ZTAoQkFTRV9VUkwsIi9wYWdlcy9mcmFtZXMvcGxhdHlzdGVybmlkYWUvIikpDQogICkNCiAgY2F0KHNwcmludGYoIltGYWxsYmFja10gJWQgZmFtaWxpZXMgdXNlZCBhcyBzYW1wbGUgZGF0YS5cblxuIiwgbGVuZ3RoKGZhbWlsaWVzKSkpDQp9KQ0KDQojIFNURVAgMjogTG9vcCB0aHJvdWdoIGVhY2ggZGV0YWlsIHBhZ2UsIHBhcnNlIGRlc2NyaXB0aW9uIHRleHQNCmNhdChzcHJpbnRmKCIlLTIycyAlLTMwcyAlLThzICVzXG4iLCAiZmFtaWx5X25hbWUiLCAiY29tbW9uX25hbWUiLCAieWVhciIsICJkaXNjb3ZlcmVkX2J5IikpDQpjYXQoc3RycmVwKCItIiwgODApLCAiXG4iKQ0KDQpmb3IgKGZhbSBpbiBmYW1pbGllcykgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgUkVRVUlSRUQgTE9PUA0KICByb3cgPC0gbGlzdCgNCiAgICBmYW1pbHlfbmFtZSAgICAgPSBmYW0kZmFtaWx5X25hbWUsDQogICAgY29tbW9uX25hbWUgICAgID0gIlVua25vd24iLA0KICAgIHllYXJfZGlzY292ZXJlZCA9ICJVbmtub3duIiwNCiAgICBkaXNjb3ZlcmVkX2J5ICAgPSAiVW5rbm93biINCiAgKQ0KDQogIGlmICghaXMubmEoZmFtJGRldGFpbF91cmwpKSB7DQogICAgdHJ5Q2F0Y2goew0KICAgICAgcjIgICA8LSBHRVQoZmFtJGRldGFpbF91cmwsIEhFQURFUlMsIHRpbWVvdXQoMTApKQ0KICAgICAgaWYgKHN0YXR1c19jb2RlKHIyKSA9PSAyMDApIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogICAgICAgIHBnMiAgPC0gcmVhZF9odG1sKGNvbnRlbnQocjIsInRleHQiKSkNCiAgICAgICAgcGFyYSA8LSBodG1sX3RleHQyKGh0bWxfZWxlbWVudChwZzIsICJwIikpDQogICAgICAgIGlmICghaXMubmEocGFyYSkgJiYgbmNoYXIocGFyYSkgPiAwKSB7DQogICAgICAgICAgbV9jbiA8LSByZWdtYXRjaGVzKHBhcmEsIHJlZ2V4cHIoJyIoW14iXSspIicsIHBhcmEpKQ0KICAgICAgICAgIGlmIChsZW5ndGgobV9jbik+MCkgcm93JGNvbW1vbl9uYW1lIDwtIGdzdWIoJyInLCcnLG1fY24pDQogICAgICAgICAgbV95ciA8LSByZWdtYXRjaGVzKHBhcmEsIHJlZ2V4cHIoIlxcYigxWzg5XVxcZHsyfXwyMFswMV1cXGQpXFxiIiwgcGFyYSkpDQogICAgICAgICAgaWYgKGxlbmd0aChtX3lyKT4wKSByb3ckeWVhcl9kaXNjb3ZlcmVkIDwtIG1feXINCiAgICAgICAgICBtX2J5IDwtIHJlZ21hdGNoZXMocGFyYSwgcmVnZXhwcigNCiAgICAgICAgICAgIHBhc3RlMCgiKD88PWluXFxzIixyb3ckeWVhcl9kaXNjb3ZlcmVkLCJcXHNieVxccylbQS1aXVthLXpBLVouXFxzXSsiKSwNCiAgICAgICAgICAgIHBhcmEsIHBlcmw9VFJVRSkpDQogICAgICAgICAgaWYgKGxlbmd0aChtX2J5KT4wKSByb3ckZGlzY292ZXJlZF9ieSA8LSB0cmltd3MobV9ieSkNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgU3lzLnNsZWVwKDAuMikNCiAgICB9LCBlcnJvcj1mdW5jdGlvbihlKSBOVUxMKQ0KICB9DQoNCiAgZGF0YV90dXJ0bGVzIDwtIGFwcGVuZChkYXRhX3R1cnRsZXMsIGxpc3Qocm93KSkNCiAgY2F0KHNwcmludGYoIiAgJS0yMnMgJS0zMHMgJS04cyAlc1xuIiwNCiAgICAgICAgICAgICAgcm93JGZhbWlseV9uYW1lLCByb3ckY29tbW9uX25hbWUsIHJvdyR5ZWFyX2Rpc2NvdmVyZWQsIHJvdyRkaXNjb3ZlcmVkX2J5KSkNCn0NCg0KZGZfdHVydGxlcyA8LSBiaW5kX3Jvd3MoZGF0YV90dXJ0bGVzKQ0Kd3JpdGVfY3N2KGRmX3R1cnRsZXMsICJzY3JhcGluZ190dXJ0bGVzLmNzdiIpDQpjYXQoc3ByaW50ZigiXG5EYXRhRnJhbWU6ICVkIHJvd3MgeCAlZCBjb2xzIHwgU2F2ZWQ6IHNjcmFwaW5nX3R1cnRsZXMuY3N2XG4iLA0KICAgICAgICAgICAgbnJvdyhkZl90dXJ0bGVzKSwgbmNvbChkZl90dXJ0bGVzKSkpDQoNCmRhdGF0YWJsZShkZl90dXJ0bGVzLA0KICAgICAgICAgIGNhcHRpb24gID0gcGFzdGUwKCJEYXRhIENvbGxlY3RlZDogIiwgbnJvdyhkZl90dXJ0bGVzKSwgIiBUdXJ0bGUgRmFtaWxpZXMiKSwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgcGFnZUxlbmd0aD0yMCwgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksDQogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSkNCmBgYA0KDQojIyBTZWN0aW9uIEIg4oCUIERhdGEgSGFuZGxpbmcNCg0KPGRpdiBjbGFzcz0iaW5mby1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlNlY3Rpb24gQiDigJQgUXVhbGl0eSBBdWRpdCBvZiA0IFNjcmFwZWQgRGF0YXNldHM8L2Rpdj4NCiAgPHA+QWxsIGZvdXIgc2NyYXBlZCBkYXRhc2V0cyBhcmUgYXVkaXRlZCBjZW50cmFsbHkgdXNpbmcgYSBzaW5nbGUgbG9vcCDigJQgb25lIGZ1bmN0aW9uLCBvbmUgaXRlcmF0aW9uLCBmb3VyIGRhdGFzZXRzIHNpbXVsdGFuZW91c2x5LiBUaGlzIHJlZmxlY3RzIHRoZSBEUlkgcHJpbmNpcGxlOiB3aGVuIHRoZSBzYW1lIGFuYWx5dGljYWwgcGF0dGVybiBhcHBsaWVzIHRvIE4gZGF0YXNldHMsIHVzZSBhIGxvb3AgcmF0aGVyIHRoYW4gY29weS1wYXN0aW5nIGNvZGUgTiB0aW1lcy48L3A+DQo8L2Rpdj4NCg0KYGBge3IgYi1oYW5kbGluZy1tcDJ9DQpkYXRhc2V0c19tcDIgPC0gbGlzdCgNCiAgbGlzdChkZj1kZl9jb3VudHJpZXMsIG5hbWE9IkNvdW50cmllcyIpLA0KICBsaXN0KGRmPWRmX2hvY2tleSwgICAgbmFtYT0iSG9ja2V5IiksDQogIGxpc3QoZGY9ZGZfb3NjYXIsICAgICBuYW1hPSJPc2NhciIpLA0KICBsaXN0KGRmPWRmX3R1cnRsZXMsICAgbmFtYT0iVHVydGxlcyIpDQopDQoNCiMgUkVRVUlSRUQgTE9PUDogYW5hbHl6ZSBhbGwgZGF0YXNldHMgc2ltdWx0YW5lb3VzbHkNCnJpbmdrYXNhbl9tcDIgPC0gYmluZF9yb3dzKGxhcHBseShkYXRhc2V0c19tcDIsIGZ1bmN0aW9uKGQpIHsNCiAgZGF0YS5mcmFtZSgNCiAgICBEYXRhc2V0ICAgID0gZCRuYW1hLA0KICAgIFJvd3MgICAgICAgPSBucm93KGQkZGYpLA0KICAgIENvbHVtbnMgICAgPSBuY29sKGQkZGYpLA0KICAgIE1pc3NpbmcgICAgPSBzdW0oaXMubmEoZCRkZikpLA0KICAgIER1cGxpY2F0ZXMgPSBzdW0oZHVwbGljYXRlZChkJGRmKSksDQogICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQogICkNCn0pKQ0KDQpkYXRhdGFibGUocmluZ2thc2FuX21wMiwNCiAgICAgICAgICBjYXB0aW9uICA9ICJEYXRhc2V0IFN1bW1hcnkg4oCUIFByZS1DbGVhbmluZyBRdWFsaXR5IEF1ZGl0IiwNCiAgICAgICAgICBleHRlbnNpb25zPSdCdXR0b25zJywgb3B0aW9ucz1saXN0KGRvbT0nQmZydGlwJywgc2Nyb2xsWD1UUlVFLCBidXR0b25zPWxpc3QoJ2NzdicsJ2V4Y2VsJywncHJpbnQnKSksIHJvd25hbWVzPUZBTFNFKSAlPiUNCiAgZm9ybWF0U3R5bGUoIk1pc3NpbmciLA0KICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlSW50ZXJ2YWwoYygwLDEwKSwgYygiI2QxZmFlNSIsIiNmZWYzYzciLCIjZmZlNGU2IikpKSAlPiUNCiAgZm9ybWF0U3R5bGUoIkR1cGxpY2F0ZXMiLA0KICAgIGJhY2tncm91bmRDb2xvciA9IHN0eWxlSW50ZXJ2YWwoYygwLDUpLCBjKCIjZDFmYWU1IiwiI2ZlZjNjNyIsIiNmZmU0ZTYiKSkpDQpgYGANCg0KIyMgU2VjdGlvbiBDIOKAlCBEYXRhIENsZWFuaW5nDQoNCjxkaXYgY2xhc3M9ImluZm8tYm94Ij4NCiAgPGRpdiBjbGFzcz0iYm94LXRpdGxlIj5TZWN0aW9uIEMg4oCUIFN5c3RlbWF0aWMgQ2xlYW5pbmcgUGlwZWxpbmUgZm9yIDQgRGF0YXNldHM8L2Rpdj4NCiAgPHA+RWFjaCBkYXRhc2V0IGlzIGNsZWFuZWQgc3lzdGVtYXRpY2FsbHk6IHRleHQgc3RhbmRhcmRpemF0aW9uICh0aXRsZSBjYXNlICsgd2hpdGVzcGFjZSB0cmltbWluZyksIGFwcHJvcHJpYXRlIG51bWVyaWMgdHlwZSBjb252ZXJzaW9uIHBlciBjb2x1bW4sIGNvbnRleHQtZHJpdmVuIG1pc3NpbmcgdmFsdWUgaGFuZGxpbmcsIGFuZCBkZWR1cGxpY2F0aW9uLiBEZXNwaXRlIGRpZmZlcmluZyBzY2hlbWFzLCBhIGNvbnNpc3RlbnQgY2xlYW5pbmcgcGF0dGVybiBpcyBhcHBsaWVkIHRocm91Z2ggZnVuY3Rpb24gYWJzdHJhY3Rpb24uPC9wPg0KPC9kaXY+DQoNCmBgYHtyIGMxLWNvdW50cmllcy1jbGVhbn0NCiMgQ291bnRyaWVzDQpkZl9jMSA8LSBkZl9jb3VudHJpZXMNCg0KZm9yIChrIGluIGMoImNvdW50cnlfbmFtZSIsImNhcGl0YWwiKSkgeyAgICAjIFJFUVVJUkVEIExPT1ANCiAgaWYgKGsgJWluJSBuYW1lcyhkZl9jMSkpIHsgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogICAgZGZfYzFbW2tdXSA8LSB0cmltd3Moc3RyX3RvX3RpdGxlKHJlcGxhY2VfbmEoZGZfYzFbW2tdXSwgIlVua25vd24iKSkpDQogIH0NCn0NCg0KZGZfYzEkcG9wdWxhdGlvbiA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLmludGVnZXIoYXMubnVtZXJpYyhkZl9jMSRwb3B1bGF0aW9uKSkpDQpkZl9jMSRhcmVhX2ttMiAgIDwtIHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhkZl9jMSRhcmVhX2ttMikpDQpkZl9jMSRwb3B1bGF0aW9uIDwtIHJlcGxhY2VfbmEoZGZfYzEkcG9wdWxhdGlvbiwgMEwpDQpkZl9jMSRhcmVhX2ttMiAgIDwtIHJlcGxhY2VfbmEoZGZfYzEkYXJlYV9rbTIsICAgMC4wKQ0KDQpuX2JlZm9yZSA8LSBucm93KGRmX2MxKTsgZGZfYzEgPC0gZGlzdGluY3QoZGZfYzEpDQpjYXQoc3ByaW50ZigiW0NvdW50cmllc10gQ2xlYW46ICVkIHJvd3MgKGR1cGxpY2F0ZXMgcmVtb3ZlZDogJWQpXG4iLA0KICAgICAgICAgICAgbnJvdyhkZl9jMSksIG5fYmVmb3JlLW5yb3coZGZfYzEpKSkNCmBgYA0KDQpgYGB7ciBjMi1ob2NrZXktY2xlYW59DQojIEhvY2tleQ0KZGZfYzIgPC0gZGZfaG9ja2V5DQoNCmZvciAoayBpbiBjKCJ0ZWFtX25hbWUiKSkgeyAgICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBMT09QDQogIGlmIChrICVpbiUgbmFtZXMoZGZfYzIpKSB7ICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICAgIGRmX2MyW1trXV0gPC0gdHJpbXdzKHN0cl90b190aXRsZShyZXBsYWNlX25hKGRmX2MyW1trXV0sICJVbmtub3duIikpKQ0KICB9DQp9DQoNCmRmX2MyJHllYXIgICAgPC0gc3VwcHJlc3NXYXJuaW5ncyhhcy5pbnRlZ2VyKGFzLm51bWVyaWMoZGZfYzIkeWVhcikpKQ0KZGZfYzIkd2lucyAgICA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLmludGVnZXIoYXMubnVtZXJpYyhkZl9jMiR3aW5zKSkpDQpkZl9jMiRsb3NzZXMgIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihhcy5udW1lcmljKGRmX2MyJGxvc3NlcykpKQ0KZGZfYzIkd2luX3BjdCA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoZGZfYzIkd2luX3BjdCkpDQpkZl9jMiR3aW5fcGN0IDwtIHJlcGxhY2VfbmEoZGZfYzIkd2luX3BjdCwgMC4wKQ0KZGZfYzIkd2luX3BjdCA8LSBpZmVsc2UoZGZfYzIkd2luX3BjdCA+IDEsIGRmX2MyJHdpbl9wY3QvMTAwLCBkZl9jMiR3aW5fcGN0KQ0KDQpuX2JlZm9yZSA8LSBucm93KGRmX2MyKTsgZGZfYzIgPC0gZGlzdGluY3QoZGZfYzIpDQpjYXQoc3ByaW50ZigiW0hvY2tleV0gQ2xlYW46ICVkIHJvd3MgKGR1cGxpY2F0ZXMgcmVtb3ZlZDogJWQpXG4iLA0KICAgICAgICAgICAgbnJvdyhkZl9jMiksIG5fYmVmb3JlLW5yb3coZGZfYzIpKSkNCmBgYA0KDQpgYGB7ciBjMy1vc2Nhci1jbGVhbn0NCiMgT3NjYXINCmRmX2MzIDwtIGRmX29zY2FyDQoNCmZvciAoayBpbiBjKCJtb3ZpZV90aXRsZSIpKSB7ICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBMT09QDQogIGlmIChrICVpbiUgbmFtZXMoZGZfYzMpKSB7ICAgICAgICAgICAgICAgIyBSRVFVSVJFRCBJRg0KICAgIGRmX2MzW1trXV0gPC0gdHJpbXdzKHN0cl90b190aXRsZShyZXBsYWNlX25hKGRmX2MzW1trXV0sICJVbmtub3duIikpKQ0KICB9DQp9DQoNCmRmX2MzJG5vbWluYXRpb25zIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihhcy5udW1lcmljKGRmX2MzJG5vbWluYXRpb25zKSkpDQpkZl9jMyRhd2FyZHMgICAgICA8LSBzdXBwcmVzc1dhcm5pbmdzKGFzLmludGVnZXIoYXMubnVtZXJpYyhkZl9jMyRhd2FyZHMpKSkNCmRmX2MzJHllYXIgICAgICAgIDwtIHN1cHByZXNzV2FybmluZ3MoYXMuaW50ZWdlcihhcy5udW1lcmljKGRmX2MzJHllYXIpKSkNCmRmX2MzJGJlc3RfcGljdHVyZSA8LSBpZmVsc2UoDQogIHRvbG93ZXIoYXMuY2hhcmFjdGVyKGRmX2MzJGJlc3RfcGljdHVyZSkpICVpbiUgYygieWVzIiwidHJ1ZSIsIjEiKSwgIlllcyIsICJObyINCikNCg0Kbl9iZWZvcmUgPC0gbnJvdyhkZl9jMyk7IGRmX2MzIDwtIGRpc3RpbmN0KGRmX2MzKQ0KY2F0KHNwcmludGYoIltPc2Nhcl0gQ2xlYW46ICVkIHJvd3MgKGR1cGxpY2F0ZXMgcmVtb3ZlZDogJWQpXG4iLA0KICAgICAgICAgICAgbnJvdyhkZl9jMyksIG5fYmVmb3JlLW5yb3coZGZfYzMpKSkNCmBgYA0KDQpgYGB7ciBjNC10dXJ0bGVzLWNsZWFufQ0KIyBUdXJ0bGVzDQpkZl9jNCA8LSBkZl90dXJ0bGVzDQoNCmZvciAoayBpbiBjKCJmYW1pbHlfbmFtZSIsImNvbW1vbl9uYW1lIiwieWVhcl9kaXNjb3ZlcmVkIiwiZGlzY292ZXJlZF9ieSIpKSB7ICAjIFJFUVVJUkVEIExPT1ANCiAgaWYgKGsgJWluJSBuYW1lcyhkZl9jNCkgJiYgaXMuY2hhcmFjdGVyKGRmX2M0W1trXV0pKSB7ICAgICAgICAgICAgICAgICAgICAgICAjIFJFUVVJUkVEIElGDQogICAgZGZfYzRbW2tdXSA8LSB0cmltd3MocmVwbGFjZV9uYShkZl9jNFtba11dLCAiVW5rbm93biIpKQ0KICAgIGRmX2M0W1trXV0gPC0gaWZlbHNlKGRmX2M0W1trXV0gPT0gIiIsICJVbmtub3duIiwgZGZfYzRbW2tdXSkNCiAgICBjYXQoc3ByaW50ZigiICBbT0tdICVzIOKAlCB0cmltbWVkIGFuZCBmaWxsZWRcbiIsIGspKQ0KICB9DQp9DQoNCm5fYmVmb3JlIDwtIG5yb3coZGZfYzQpOyBkZl9jNCA8LSBkaXN0aW5jdChkZl9jNCkNCmNhdChzcHJpbnRmKCIgIER1cGxpY2F0ZXMgcmVtb3ZlZDogJWRcbiIsIG5fYmVmb3JlIC0gbnJvdyhkZl9jNCkpKQ0KY2F0KHNwcmludGYoIltUdXJ0bGVzXSBDbGVhbjogJWQgcm93cyB4ICVkIGNvbHNcbiIsIG5yb3coZGZfYzQpLCBuY29sKGRmX2M0KSkpDQoNCndyaXRlX2NzdihkZl9jMSwgInNjcmFwaW5nX2NvdW50cmllc19jbGVhbi5jc3YiKQ0Kd3JpdGVfY3N2KGRmX2MyLCAic2NyYXBpbmdfaG9ja2V5X2NsZWFuLmNzdiIpDQp3cml0ZV9jc3YoZGZfYzMsICJzY3JhcGluZ19vc2Nhcl9jbGVhbi5jc3YiKQ0Kd3JpdGVfY3N2KGRmX2M0LCAic2NyYXBpbmdfdHVydGxlc19jbGVhbi5jc3YiKQ0KY2F0KCJcbkFsbCBjbGVhbiBkYXRhc2V0cyBzYXZlZCBzdWNjZXNzZnVsbHkuXG4iKQ0KYGBgDQoNCiMjIFNlY3Rpb24gRCDigJQgQ29uZGl0aW9uYWwgTG9naWMNCg0KPGRpdiBjbGFzcz0iaW5mby1ib3giPg0KICA8ZGl2IGNsYXNzPSJib3gtdGl0bGUiPlNlY3Rpb24gRCDigJQgRGF0YSBRdWFsaXR5IEZsYWdnaW5nIHZpYSBOZXN0ZWQgSUY8L2Rpdj4NCiAgPHA+QSA8Y29kZT5kYXRhX3N0YXR1czwvY29kZT4gY29sdW1uIGlzIGFkZGVkIHRvIGVhY2ggc2NyYXBlZCBkYXRhc2V0IGFzIGEgcGVyLXJvdyBjb21wbGV0ZW5lc3MgaW5kaWNhdG9yLiBUaGlzIGlzIGEgZm9ybSBvZiBzaW1wbGUgZGF0YSBxdWFsaXR5IHNjb3Jpbmc6IGVhY2ggcm93IGlzIGV2YWx1YXRlZCBhZ2FpbnN0IGRhdGFzZXQtc3BlY2lmaWMgY29tcGxldGVuZXNzIGNyaXRlcmlhIHJhdGhlciB0aGFuIGEgZ2VuZXJpYyB1bml2ZXJzYWwgc3RhbmRhcmQuPC9wPg0KPC9kaXY+DQoNCmBgYHtyIGQtY29uZGl0aW9uYWwtbXAyfQ0KdGFtYmFoX3N0YXR1cyA8LSBmdW5jdGlvbihkZiwga29sb21fcGVudGluZykgew0KICBkZiAlPiUgcm93d2lzZSgpICU+JQ0KICAgIG11dGF0ZShkYXRhX3N0YXR1cyA9IHsNCiAgICAgIG9rIDwtIFRSVUUNCiAgICAgIGZvciAoayBpbiBrb2xvbV9wZW50aW5nKSB7ICAgICAgICAgICAgICAjIFJFUVVJUkVEIExPT1ANCiAgICAgICAgaWYgKGsgJWluJSBuYW1lcyhkZikpIHsgICAgICAgICAgICAgICMgUkVRVUlSRUQgSUYNCiAgICAgICAgICB2IDwtIGFzLmNoYXJhY3RlcihnZXQoaykpDQogICAgICAgICAgaWYgKGlzLm5hKHYpIHx8IHRyaW13cyh2KSAlaW4lIGMoIiIsIlVua25vd24iLCJuYW4iLCJOb25lIiwiMCIpKSB7DQogICAgICAgICAgICBvayA8LSBGQUxTRTsgYnJlYWsgICAgICAgICAgICAgICAjIFJFUVVJUkVEIE5FU1RFRCBJRg0KICAgICAgICAgIH0NCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgaWYgKG9rKSAiQ29tcGxldGUiIGVsc2UgIkluY29tcGxldGUiICAgIyBSRVFVSVJFRCBJRi1FTFNFDQogICAgfSkgJT4lIHVuZ3JvdXAoKQ0KfQ0KDQpjb25maWcgPC0gbGlzdCgNCiAgbGlzdChkZj1kZl9jMSwga29sPWMoImNvdW50cnlfbmFtZSIsImNhcGl0YWwiLCJwb3B1bGF0aW9uIiksIG5hbWE9IkNvdW50cmllcyIpLA0KICBsaXN0KGRmPWRmX2MyLCBrb2w9YygidGVhbV9uYW1lIiwieWVhciIsIndpbnMiKSwgICAgICAgICAgICAgbmFtYT0iSG9ja2V5IiksDQogIGxpc3QoZGY9ZGZfYzMsIGtvbD1jKCJtb3ZpZV90aXRsZSIsInllYXIiLCJhd2FyZHMiKSwgICAgICAgICBuYW1hPSJPc2NhciIpLA0KICBsaXN0KGRmPWRmX2M0LCBrb2w9YygiZmFtaWx5X25hbWUiLCJjb21tb25fbmFtZSIsInllYXJfZGlzY292ZXJlZCIpLCAgbmFtYT0iVHVydGxlcyIpDQopDQoNCmhhc2lsX3N0YXR1cyA8LSBiaW5kX3Jvd3MobGFwcGx5KGNvbmZpZywgZnVuY3Rpb24oY2ZnKSB7ICAjIFJFUVVJUkVEIExPT1ANCiAgZGZfaCA8LSB0YW1iYWhfc3RhdHVzKGNmZyRkZiwgY2ZnJGtvbCkNCiAgY29tcCA8LSBzdW0oZGZfaCRkYXRhX3N0YXR1cyA9PSAiQ29tcGxldGUiKQ0KICBkYXRhLmZyYW1lKERhdGFzZXQ9Y2ZnJG5hbWEsIENvbXBsZXRlPWNvbXAsDQogICAgICAgICAgICAgSW5jb21wbGV0ZT1ucm93KGRmX2gpLWNvbXAsDQogICAgICAgICAgICAgUGN0X0NvbXBsZXRlPXBhc3RlMChyb3VuZChjb21wL25yb3coZGZfaCkqMTAwLDEpLCIlIiksDQogICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkNCn0pKQ0KDQpkZl9jMSA8LSB0YW1iYWhfc3RhdHVzKGRmX2MxLCBjb25maWdbWzFdXSRrb2wpDQpkZl9jMiA8LSB0YW1iYWhfc3RhdHVzKGRmX2MyLCBjb25maWdbWzJdXSRrb2wpDQpkZl9jMyA8LSB0YW1iYWhfc3RhdHVzKGRmX2MzLCBjb25maWdbWzNdXSRrb2wpDQpkZl9jNCA8LSB0YW1iYWhfc3RhdHVzKGRmX2M0LCBjb25maWdbWzRdXSRrb2wpDQoNCmRhdGF0YWJsZShoYXNpbF9zdGF0dXMsDQogICAgICAgICAgY2FwdGlvbiAgPSAiRGF0YSBRdWFsaXR5IFNjb3JlIOKAlCBkYXRhX3N0YXR1cyBEaXN0cmlidXRpb24gcGVyIERhdGFzZXQiLA0KICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwgcm93bmFtZXM9RkFMU0UpICU+JQ0KICBmb3JtYXRTdHlsZSgiQ29tcGxldGUiLA0KICAgIGJhY2tncm91bmQ9c3R5bGVDb2xvckJhcihoYXNpbF9zdGF0dXMkQ29tcGxldGUsICIjMzRkMzk5IiksDQogICAgYmFja2dyb3VuZFNpemU9IjEwMCUgNzAlIiwgYmFja2dyb3VuZFJlcGVhdD0ibm8tcmVwZWF0IiwNCiAgICBiYWNrZ3JvdW5kUG9zaXRpb249ImNlbnRlciIpICU+JQ0KICBmb3JtYXRTdHlsZSgiUGN0X0NvbXBsZXRlIiwNCiAgICBjb2xvciA9ICIjMTBiOTgxIiwNCiAgICBmb250V2VpZ2h0ID0gImJvbGQiKQ0KYGBgDQoNCiMjIFNlY3Rpb24gRSDigJQgQW5hbHl0aWNhbCBUaGlua2luZw0KDQo8ZGl2IGNsYXNzPSJpbmZvLWJveCI+DQogIDxkaXYgY2xhc3M9ImJveC10aXRsZSI+U2VjdGlvbiBFIOKAlCBFdmFsdWF0aW9uIG9mIFNjcmFwaW5nIFRlY2huaXF1ZXMgYW5kIFN1YnN0YW50aXZlIEluc2lnaHRzPC9kaXY+DQogIDxwPlR3byBhbmFseXRpY2FsIGxheWVycyBhcmUgZXhlY3V0ZWQgaGVyZS4gVGhlIGZpcnN0IGlzIG1ldGEtYW5hbHl0aWM6IGEgY29tcGFyYXRpdmUgZXZhbHVhdGlvbiBvZiB0aGUgZm91ciBzY3JhcGluZyB0ZWNobmlxdWVzIGFjcm9zcyBpbXBsZW1lbnRhdGlvbiBjb21wbGV4aXR5LCBmcmFnaWxpdHkgdG8gd2Vic2l0ZSBjaGFuZ2VzLCBvcGVyYXRpb25hbCByaXNrIChyYXRlIGxpbWl0aW5nLCBJUCBibG9ja2luZyksIGFuZCBvcHRpbWFsIHVzZSBjYXNlcyDigJQgYnVpbGRpbmcgYSBkZWNpc2lvbiBmcmFtZXdvcmsgZm9yIGZ1dHVyZSB0ZWNobmlxdWUgc2VsZWN0aW9uLiBUaGUgc2Vjb25kIGlzIHN1YnN0YW50aXZlOiBleHRyYWN0aW5nIG1lYW5pbmdmdWwgaW5zaWdodHMgZnJvbSB0aGUgY29sbGVjdGVkIGRhdGEsIGRlbW9uc3RyYXRpbmcgdGhhdCB0aGUgc2NyYXBpbmcgcHJvY2VzcyBoYXMgZ2VuZXJhdGVkIGtub3dsZWRnZSB0aGF0IHdhcyBub3QgcHJldmlvdXNseSBhdmFpbGFibGUuPC9wPg0KPC9kaXY+DQoNCiMjIyBFLjEg4oCUIENvbXBhcmlzb24gb2YgNCBTY3JhcGluZyBUZWNobmlxdWVzDQoNCmBgYHtyIGUxLXBlcmJhbmRpbmdhbn0NCnBlcmJhbmRpbmdhbiA8LSBkYXRhLmZyYW1lKA0KICBObyAgICAgICAgICA9IDE6NCwNCiAgVHlwZSAgICAgICAgPSBjKCJTdGF0aWMgSFRNTCIsIlBhZ2luYXRpb24iLCJBSkFYIHRvIEpTT04iLCJpRnJhbWUiKSwNCiAgV2Vic2l0ZSAgICAgPSBjKCJDb3VudHJpZXMiLCJIb2NrZXkiLCJPc2NhciIsIlR1cnRsZXMiKSwNCiAgQ29tcGxleGl0eSAgPSBjKCJMb3ciLCJNZWRpdW0iLCJIaWdoIiwiTWVkaXVtLUhpZ2giKSwNCiAgTWV0aG9kICAgICAgPSBjKCJHRVQgLT4gcmVhZF9odG1sIC0+IGh0bWxfZWxlbWVudHMoKSIsDQogICAgICAgICAgICAgICAgICAgIkxvb3AgP3BhZ2VfbnVtPU4sIGJyZWFrIHdoZW4gZW1wdHkiLA0KICAgICAgICAgICAgICAgICAgICJHRVQgP2FqYXg9dHJ1ZSZ5ZWFyPVlZWVkgLT4gZnJvbUpTT04oKSIsDQogICAgICAgICAgICAgICAgICAgIkFjY2VzcyA/ZnJhbWU9aSBkaXJlY3RseSAtPiBodG1sX2VsZW1lbnRzKCdoMycpIiksDQogIEFkdmFudGFnZXMgID0gYygiU2luZ2xlIHJlcXVlc3QsIGZhc3QsIHJlbGlhYmxlLCBubyBKUyBkZXBlbmRlbmN5IiwNCiAgICAgICAgICAgICAgICAgICAiQXV0b21hdGljYWxseSBzY3JhcGVzIHRob3VzYW5kcyBvZiByb3dzIGFjcm9zcyBkb3plbnMgb2YgcGFnZXMiLA0KICAgICAgICAgICAgICAgICAgICJTdHJ1Y3R1cmVkIEpTT04gaXMgbW9yZSBlZmZpY2llbnQgYW5kIGVhc2llciB0byBwYXJzZSIsDQogICAgICAgICAgICAgICAgICAgIkJ5cGFzc2VzIHBhcmVudCBmcmFtZSBuYXZpZ2F0aW9uIGNvbXBsZXhpdHkiKSwNCiAgTGltaXRhdGlvbnMgPSBjKCJGYWlscyBlbnRpcmVseSBpZiBkYXRhIGlzIHJlbmRlcmVkIGJ5IEphdmFTY3JpcHQiLA0KICAgICAgICAgICAgICAgICAgICJWdWxuZXJhYmxlIHRvIHJhdGUtbGltaXRpbmc7IHBhZ2UgY291bnQgbXVzdCBiZSBrbm93biBvciBkZXRlY3RlZCIsDQogICAgICAgICAgICAgICAgICAgIkhpZGRlbiwgdW5kb2N1bWVudGVkIGVuZHBvaW50IHRoYXQgY2FuIGNoYW5nZSB3aXRob3V0IG5vdGljZSIsDQogICAgICAgICAgICAgICAgICAgIlJlcXVpcmVzIHByaW9yIGZyYW1lIHN0cnVjdHVyZSBhbmFseXNpcyB2aWEgRGV2VG9vbHMiKSwNCiAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFDQopDQoNCmRhdGF0YWJsZShwZXJiYW5kaW5nYW4sDQogICAgICAgICAgY2FwdGlvbiAgPSAiQ29tcGFyaXNvbiBNYXRyaXgg4oCUIDQgV2ViIFNjcmFwaW5nIEFwcHJvYWNoZXMiLA0KICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTEwLCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwNCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFKSAlPiUNCiAgZm9ybWF0U3R5bGUoIkNvbXBsZXhpdHkiLA0KICAgIGNvbG9yID0gc3R5bGVFcXVhbCgNCiAgICAgIGMoIkxvdyIsIk1lZGl1bSIsIk1lZGl1bS1IaWdoIiwiSGlnaCIpLA0KICAgICAgYygiIzEwYjk4MSIsIiNmNTllMGIiLCIjZjk3MzE2IiwiI2Y0M2Y1ZSIpKSwNCiAgICBmb250V2VpZ2h0ID0gImJvbGQiKQ0KYGBgDQoNCjxkaXYgY2xhc3M9Imluc2lnaHQtYm94Ij4NCiAgPGRpdiBjbGFzcz0iYm94LXRpdGxlIj5LZXkgSW5zaWdodCDigJQgVGVjaG5pcXVlIFNlbGVjdGlvbiBpcyBhbiBFbmdpbmVlcmluZyBSZXF1aXJlbWVudCwgTm90IGEgUHJlZmVyZW5jZTwvZGl2Pg0KICA8cD5TdGF0aWMgSFRNTCBzY3JhcGluZyBpcyB0aGUgbW9zdCByZWxpYWJsZSB0ZWNobmlxdWU6IG5vIEphdmFTY3JpcHQgZGVwZW5kZW5jeSwgbm8gcmFjZSBjb25kaXRpb25zLCBhbmQgYSBzaW5nbGUgSFRUUCByZXF1ZXN0IHN1ZmZpY2VzLiBJdCBzaG91bGQgYWx3YXlzIGJlIGF0dGVtcHRlZCBmaXJzdCDigJQgc3VjY2VzcyBlbGltaW5hdGVzIHRoZSBuZWVkIGZvciBtb3JlIGNvbXBsZXggYXBwcm9hY2hlcywgYW5kIGZhaWx1cmUgaXMgYSBzdHJvbmcgc2lnbmFsIHRoYXQgdGhlIHRhcmdldCBzaXRlIHVzZXMgZHluYW1pYyByZW5kZXJpbmcuIEZvciBBSkFYIGVuZHBvaW50cywgdGhlIHByaW1hcnkgcmlzayBpcyB0aGF0IGhpZGRlbiBlbmRwb2ludHMgZGlzY292ZXJlZCB2aWEgRGV2VG9vbHMgYXJlIHVuZG9jdW1lbnRlZCBhbmQgY2FuIGNoYW5nZSB3aXRob3V0IG5vdGljZSwgY2F1c2luZyBzY3JhcGVycyB0byBmYWlsIHNpbGVudGx5LiBNaXRpZ2F0aW9uIHJlcXVpcmVzIHBlcmlvZGljIG1vbml0b3JpbmcgYW5kIHJvYnVzdCBlcnJvciBhbGVydGluZyBpbiBwcm9kdWN0aW9uIHBpcGVsaW5lcy48L3A+DQo8L2Rpdj4NCg0KIyMjIEUuMiDigJQgSW5zaWdodHMgZnJvbSBTY3JhcGVkIERhdGENCg0KYGBge3IgZTItaW5zaWdodC1tcDJ9DQpuZWdfcGFkYXQgPC0gZGZfYzEkY291bnRyeV9uYW1lW3doaWNoLm1heChkZl9jMSRwb3B1bGF0aW9uKV0NCm5lZ19sdWFzICA8LSBkZl9jMSRjb3VudHJ5X25hbWVbd2hpY2gubWF4KGRmX2MxJGFyZWFfa20yKV0NCnBvcF9tYXggICA8LSBtYXgoZGZfYzEkcG9wdWxhdGlvbiwgbmEucm09VFJVRSkNCg0KdGltX3RvcCA8LSBkZl9jMiR0ZWFtX25hbWVbd2hpY2gubWF4KGRmX2MyJHdpbl9wY3QpXQ0Kd3JfbWF4ICA8LSBtYXgoZGZfYzIkd2luX3BjdCwgbmEucm09VFJVRSkNCmF2Z193ciAgPC0gbWVhbihkZl9jMiR3aW5fcGN0LCBuYS5ybT1UUlVFKQ0KDQpmaWxtX3RvcCAgIDwtIGRmX2MzJG1vdmllX3RpdGxlW3doaWNoLm1heChkZl9jMyRhd2FyZHMpXQ0KYXdhcmRzX21heCA8LSBtYXgoZGZfYzMkYXdhcmRzLCBuYS5ybT1UUlVFKQ0KYXZnX25vbSAgICA8LSBtZWFuKGRmX2MzJG5vbWluYXRpb25zLCBuYS5ybT1UUlVFKQ0KcGN0X2JwICAgICA8LSBtZWFuKGRmX2MzJGJlc3RfcGljdHVyZT09IlllcyIsIG5hLnJtPVRSVUUpKjEwMA0KYGBgDQoNCjxkaXYgY2xhc3M9InN0YXQtZ3JpZCI+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCBibHVlIj4NCiAgICA8ZGl2IGNsYXNzPSJ2YWwiPmByIG5yb3coZGZfYzEpYDwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+Q291bnRyaWVzPC9kaXY+DQogIDwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJzdGF0LWNhcmQgdGVhbCI+DQogICAgPGRpdiBjbGFzcz0idmFsIj5gciBucm93KGRmX2MyKWA8L2Rpdj4NCiAgICA8ZGl2IGNsYXNzPSJsYmwiPk5ITCBIb2NrZXkgVGVhbXM8L2Rpdj4NCiAgPC9kaXY+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCBwdXJwbGUiPg0KICAgIDxkaXYgY2xhc3M9InZhbCI+YHIgbnJvdyhkZl9jMylgPC9kaXY+DQogICAgPGRpdiBjbGFzcz0ibGJsIj5Pc2NhciBGaWxtcyAoMjAxMC0xNSk8L2Rpdj4NCiAgPC9kaXY+DQogIDxkaXYgY2xhc3M9InN0YXQtY2FyZCBlbWVyYWxkIj4NCiAgICA8ZGl2IGNsYXNzPSJ2YWwiPmByIG5yb3coZGZfYzQpYDwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+VHVydGxlIEZhbWlsaWVzPC9kaXY+DQogIDwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJzdGF0LWNhcmQgYW1iZXIiPg0KICAgIDxkaXYgY2xhc3M9InZhbCI+YHIgbmVnX3BhZGF0YDwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+TW9zdCBQb3B1bG91cyBDb3VudHJ5PC9kaXY+DQogIDwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJzdGF0LWNhcmQgcm9zZSI+DQogICAgPGRpdiBjbGFzcz0idmFsIj5gciB0aW1fdG9wYDwvZGl2Pg0KICAgIDxkaXYgY2xhc3M9ImxibCI+SGlnaGVzdCBXaW4gUmF0ZSBUZWFtPC9kaXY+DQogIDwvZGl2Pg0KPC9kaXY+DQoNCjxkaXYgY2xhc3M9Imluc2lnaHQtYm94Ij4NCiAgPGRpdiBjbGFzcz0iYm94LXRpdGxlIj5LZXkgRmluZGluZ3MgQWNyb3NzIDQgU2NyYXBlZCBEYXRhc2V0czwvZGl2Pg0KICA8cD4NCiAgICA8c3Ryb25nPltDb3VudHJpZXMg4oCUIEdlb2dyYXBoeSBhbmQgRGVtb2dyYXBoeV08L3N0cm9uZz4gYHIgbmVnX3BhZGF0YCBpcyB0aGUgbW9zdCBwb3B1bG91cyBjb3VudHJ5IGF0IDxzdHJvbmc+YHIgZm9ybWF0KHBvcF9tYXgsYmlnLm1hcms9IiwiKWA8L3N0cm9uZz4gcGVvcGxlLCB3aGlsZSBgciBuZWdfbHVhc2AgaG9sZHMgdGhlIGxhcmdlc3QgbGFuZCBhcmVhLiBUaGUgZmFjdCB0aGF0IHRoZSBtb3N0IHBvcHVsb3VzIGNvdW50cnkgaXMgbm90IHRoZSBsYXJnZXN0IGJ5IGFyZWEgcmVmbGVjdHMgYSBoaWdobHkgdW5ldmVuIGdsb2JhbCBwb3B1bGF0aW9uIGRpc3RyaWJ1dGlvbiBzaGFwZWQgYnkgaGlzdG9yaWNhbCwgY2xpbWF0aWMsIGFuZCBlY29ub21pYyBmYWN0b3JzIOKAlCB3aXRoIGRpcmVjdCBpbXBsaWNhdGlvbnMgZm9yIGluZnJhc3RydWN0dXJlIGJ1cmRlbiwgbWFya2V0IG9wcG9ydHVuaXR5LCBhbmQgZW52aXJvbm1lbnRhbCBwcmVzc3VyZS48YnI+PGJyPg0KICAgIDxzdHJvbmc+W05ITCBIb2NrZXkg4oCUIFRlYW0gUGVyZm9ybWFuY2VdPC9zdHJvbmc+IGByIHRpbV90b3BgIHJlY29yZGVkIHRoZSBoaWdoZXN0IHdpbiByYXRlIGF0IGByIHJvdW5kKHdyX21heCoxMDAsMSlgJSwgc2lnbmlmaWNhbnRseSBhYm92ZSB0aGUgbGVhZ3VlIGF2ZXJhZ2Ugb2YgYHIgcm91bmQoYXZnX3dyKjEwMCwxKWAlLiBJbiBzcG9ydHMgYW5hbHl0aWNzLCB3aW4gcmF0ZSBpcyBhbiBlZmZpY2llbmN5IG1ldHJpYyDigJQgaGlnaCB3aW4tcmF0ZSB0ZWFtcyBkZW1vbnN0cmF0ZSBjb25zaXN0ZW5jeSwgc291bmQgdGFjdGljYWwgc3lzdGVtcywgYW5kIHJvc3RlciBkZXB0aCwgbWFraW5nIGl0IGEgbW9yZSBtZWFuaW5nZnVsIGJlbmNobWFyayB0aGFuIHJhdyB0b3RhbCB3aW5zIHdoaWNoIGNhbiBiZSBza2V3ZWQgYnkgZ2FtZXMgcGxheWVkLjxicj48YnI+DQogICAgPHN0cm9uZz5bT3NjYXIgRmlsbXMgMjAxMC0yMDE1IOKAlCBGaWxtIEluZHVzdHJ5XTwvc3Ryb25nPiAiPGVtPmByIGZpbG1fdG9wYDwvZW0+IiBsZWQgd2l0aCBgciBhd2FyZHNfbWF4YCB3aW5zLiBXaXRoIGFuIGF2ZXJhZ2Ugb2YgYHIgcm91bmQoYXZnX25vbSwxKWAgbm9taW5hdGlvbnMgcGVyIGZpbG0gYnV0IG9ubHkgYHIgcm91bmQocGN0X2JwLDEpYCUgZWFybmluZyBCZXN0IFBpY3R1cmUsIHRoZSBkYXRhIHJldmVhbHMgdGhlIEFjYWRlbXkncyBoaWdoIHNlbGVjdGl2aXR5OiBtYW55IG5vbWluYXRpb25zIGRvIG5vdCBndWFyYW50ZWUgYSB3aW4sIHJlZmxlY3RpbmcgdGhlIGludGVuc2UgY29tcGV0aXRpb24gYW5kIGluaGVyZW50IHN1YmplY3Rpdml0eSBvZiBjcmVhdGl2ZSB3b3JrIGV2YWx1YXRpb24uPGJyPjxicj4NCiAgICA8c3Ryb25nPltUdXJ0bGVzIOKAlCBCaW9kaXZlcnNpdHldPC9zdHJvbmc+IGByIG5yb3coZGZfYzQpYCB0dXJ0bGUgZmFtaWxpZXMgd2VyZSBjYXRhbG9ndWVkIOKAlCBhIHN0cnVjdHVyZWQgcmVmZXJlbmNlIHJlbGV2YW50IHRvIHJlcHRpbGUgY29uc2VydmF0aW9uIHJlc2VhcmNoLiBTY3JhcGluZyBiaW9kaXZlcnNpdHkgZGF0YSBmcm9tIGF1dGhvcml0YXRpdmUgc291cmNlcyBjYW4gc3VwcG9ydCBzcGVjaWVzIHByb3RlY3Rpb24gcHJvZ3JhbXMgYW5kIHB1YmxpYyBlZHVjYXRpb24gaW5pdGlhdGl2ZXMuDQogIDwvcD4NCjwvZGl2Pg0KDQotLS0NCg0KIyBSZWZlcmVuY2VzIHsjcmVmZXJlbnNpfQ0KDQpgYGB7ciByZWZlcmVuc2ktdGFiZWx9DQpyZWZzIDwtIGRhdGEuZnJhbWUoDQogIE5vICAgICA9IDE6NiwNCiAgU291cmNlID0gYygiU2NyYXBlVGhpc1NpdGUuY29tIOKAlCBDb3VudHJpZXMgb2YgdGhlIFdvcmxkIiwNCiAgICAgICAgICAgICAgIlNjcmFwZVRoaXNTaXRlLmNvbSDigJQgSG9ja2V5IFRlYW1zIChQYWdpbmF0aW9uKSIsDQogICAgICAgICAgICAgICJTY3JhcGVUaGlzU2l0ZS5jb20g4oCUIE9zY2FyIFdpbm5pbmcgRmlsbXMgKEFKQVgvSlNPTikiLA0KICAgICAgICAgICAgICAiU2NyYXBlVGhpc1NpdGUuY29tIOKAlCBUdXJ0bGVzIEFsbCB0aGUgV2F5IERvd24gKGlGcmFtZSkiLA0KICAgICAgICAgICAgICAiUiBEb2N1bWVudGF0aW9uIOKAlCB0aWR5dmVyc2UsIHJ2ZXN0LCBodHRyLCB4bWwyLCBEVCIsDQogICAgICAgICAgICAgICJFLUNvbW1lcmNlIERhdGFzZXQg4oCUIE1pZHRlcm0gRXhhbSwgU0QtMTMwNiBJVFNCIiksDQogIFVSTCAgICA9IGMoImh0dHBzOi8vd3d3LnNjcmFwZXRoaXNzaXRlLmNvbS9wYWdlcy9zaW1wbGUvIiwNCiAgICAgICAgICAgICAgImh0dHBzOi8vd3d3LnNjcmFwZXRoaXNzaXRlLmNvbS9wYWdlcy9mb3Jtcy8iLA0KICAgICAgICAgICAgICAiaHR0cHM6Ly93d3cuc2NyYXBldGhpc3NpdGUuY29tL3BhZ2VzL2FqYXgtamF2YXNjcmlwdC8iLA0KICAgICAgICAgICAgICAiaHR0cHM6Ly93d3cuc2NyYXBldGhpc3NpdGUuY29tL3BhZ2VzL2ZyYW1lcy8iLA0KICAgICAgICAgICAgICAiaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZyIsDQogICAgICAgICAgICAgICJDbGFzc3Jvb20gRGF0YXNldCDigJQgSW5zdGl0dXQgVGVrbm9sb2dpIGRhbiBTYWlucyBCYW5kdW5nIiksDQogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQ0KKQ0KDQpkYXRhdGFibGUocmVmcywNCiAgICAgICAgICBjYXB0aW9uICA9ICJSZWZlcmVuY2VzIGFuZCBEYXRhIFNvdXJjZXMiLA0KICAgICAgICAgIGV4dGVuc2lvbnM9J0J1dHRvbnMnLCBvcHRpb25zPWxpc3QoZG9tPSdCZnJ0aXAnLCBwYWdlTGVuZ3RoPTEwLCBzY3JvbGxYPVRSVUUsIGJ1dHRvbnM9bGlzdCgnY3N2JywnZXhjZWwnLCdwcmludCcpKSwgcm93bmFtZXM9RkFMU0UpDQpgYGANCg0KLS0tDQoNCjxkaXYgY2xhc3M9ImZvb3Rlci1ub3RlIj4NCiAgPHN0cm9uZz5EYXRhIFNjaWVuY2UgUHJvZ3JhbW1pbmcgSTwvc3Ryb25nPiAmbmJzcDsmbWlkZG90OyZuYnNwOw0KICBNaW5pIFByb2plY3QgMTogRS1Db21tZXJjZSBBbmFseXNpcyAmbmJzcDt8Jm5ic3A7IE1pbmkgUHJvamVjdCAyOiBXZWIgU2NyYXBpbmcgJm5ic3A7Jm1pZGRvdDsmbmJzcDsNCiAgRGF0YSBTY2llbmNlLCBGYWN1bHR5IG9mIERpZ2l0YWwgRGVzaWduIGFuZCBCdXNpbmVzcyAmbmJzcDsmbWlkZG90OyZuYnNwOw0KICBJbnN0aXR1dCBUZWtub2xvZ2kgZGFuIFNhaW5zIEJhbmR1bmcgJm5ic3A7Jm1pZGRvdDsmbmJzcDsNCiAgMjAyNSAvIDIwMjYNCjwvZGl2Pg0K