Hands-on NGS Analysis in Galaxy and IGV
Tutorial Overview
This tutorial will cover the basics of NGS analysis using Galaxy; a open-source web-based platform for the analysis of biological data. You should gain an appreciation of the tasks involved in a typical NGS analysis and be comfortable with the outputs generated by a sequencing service.You will also use the Integrative Genomics Viewer (IGV) to view the aligned reads in an interactive manner.
Parts of this tutorial are based on the NGS tutorial from the Galaxy Project and the IGV tutorial from the Griffin lab.
The tutorial covers the following steps in our analysis pipeline
Background
Where do the data in this tutorial come from?
The data for this tutorial are publicly-available exome sequencing data downsampled to the BRCA2 region from a fictitious patient. We will use these data throughout the course to call variants, filter and discuss the clinical impact of any mutations.
Section 1: Preparation
Ignore if you have already created a Galaxy account and uploaded the example data in a previous exercise
1. Register as a new user on one of the public Galaxy servers
Make sure you check your email to activate your account
2. Import the data for the workshop.
We can going to import the fastq files for this experiment. This is a standard format for storing raw sequencing reads and their associated quality scores. However, as we will see, the representation of the quality scores has changed over time.
You can import the data by:
- In the tool panel located on the left, under Basic Tools select Get Data > Upload File. Click on the Paste/Fetch data button on the bottom section of the pop-up window.
Upload the sequence data by selecting the files JoeBlogsBRCAPanel_R1.fastq
and JoeBlogsBRCAPanel_R2.fastq
. You don’t need to specify the file type or genome build. Galaxy should be able to make a reasonable guess.
- You should now have these 2 files in your history:
JoeBlogsBRCAPanel_R1.fastq
JoeBlogsBRCAPanel_R2.fastq
Section 3: Quality assessment with FastQC
FastQC is a popular tool from Babraham Institute Bioinformatics Group used for quality assessment of sequencing data. Most Bioinformatics pipelines will use FastQC, or similar tools in the first stage of the analysis. The documentation for FastQC will help you to interpret the plots and stats produced by the tool. A traffic light system is used to alert the user’s attention to possible issues.
- From the left hand tool panel in Galaxy, under GENOMIC FILE MANIPULATION, select FASTQ Quality Control -> FastQC
- Select one of the FASTQ files as input and Execute the tool.
- When the tool finishes running, you should have an HTML file in your History. Click on the eye icon to view the various quality metrics.
The most important image is whether the base quality decreases significantly over the length of the read
Good quality data should look something like:-
Look at the generated FastQC metrics for your uploaded fastq files. This data looks pretty good - high per-base quality scores (most above 30).
All is not lost if we observe poor quality bases towards the end of the read. There are a number of trimming options that we can use for NGS data and some of these are available through Galaxy. Check out the Trimmming Reads section of the Galaxy NGS tutorial if you are interested in how we can trim our reads.
It is also worth bearing in mind that the tool is blind to the particular type of sequencing you are performing (i.e. whole-genome, ChIP-seq, RNA-seq) and the organism being sequenced, so some warnings might be expected due to the nature of your experiment. For instance, there are known sequencing composition biases that can occur at the beginning of RNA-seq reads.
Aggregating QC reports with multiqc
For datasets with large numbers of fastq files, it may be useful to aggregate the individual reports into a single combined report.
- Under GENOMIC FILE MANIPULATION, select FASTQ Quality Control -> MultiQC
- Make sure Software name is set to
FastQC
- In Results file, select the RawData results files that you have just generated
You should then be able to view the fastqc plots for both the fastq files on the same page.
Section 4: Alignment
We don’t really spend much time look at fastq files, as most of our time is spent with aligned reads. i.e. we have used some software to tell us whereabouts in the genome each read belongs to. This will usually be performed for you as part of a sequencing service, but it is good to get an appreciation of the steps involved.
In this section we map the reads in our FASTQ files to a reference genome.
A plethora of different tools have been written to perform this task, and we will not describe it in detail. Links to some key publications are given below:-
Alignment relies on the reference genome being indexed so that the sequencing reads can be located more efficiently. The genome index is a highly-accessible data structure, and Galaxy includes indices for many popular genomes.
1.Align the example files
- Find the tool GENOMICS ANALYSIS -> Mapping -> Bowtie2
- alternatively, type
bowtie
in the search box
- In Is this single-end or Paired-end? Select Paired-end
- Set FastQ file #1 and FastQ file #2 to the two fastq files you uploaded in the previous step
- Make sure the reference genome is set to Human (Homo sapiens):hg19
- Press Execute
- Wait!
The result will be a .bam
file that we will describe in the next section. This file is not human-readable, as it is compressed. But we can convert to a readable format for illustration purposes.
2. View the alignments
- Click on the eye of the resulting file to view the alignments.
The .sam
file
- Sequence Alignment/Map (sam)
- The output from an aligner such as
bwa
- Same format regardless of sequencing protocol (i.e. RNA-seq, ChIP-seq, DNA-seq etc)
- May contain un-mapped reads
- Potentially large size on disk; ~100s of Gb
- Can be manipulated with standard unix tools; e.g. cat, head, grep, more, less….
- Official specification can be obtained online: -
- We normally work on a compressed version called a
.bam
file. See later.
- Header lines starting with an
@
character, followed by tab-delimited lines
- Header gives information about the alignment and references sequences used
The first part of the header lists the names (SN
) of the sequences (chromosomes) used in alignment, their length (LN
) and a md5sum “digital fingerprint” of the .fasta
file used for alignment (M5
).
@HD VN:1.0 SO:coordinate
@SQ SN:chr10 LN:135534747
@SQ SN:chr11 LN:135006516
@SQ SN:chr11_gl000202_random LN:40103
@SQ SN:chr12 LN:133851895
@SQ SN:chr13 LN:115169878
@SQ SN:chr14 LN:107349540
@SQ SN:chr15 LN:102531392
@SQ SN:chr16 LN:90354753
.....
.....
We also have a section where we can record the processing steps used to derive the file
@PG ID:bowtie2 PN:bowtie2 VN:2.3.4.1 CL:"/jetstream/scratch0/main/conda/envs/mulled-v1-65d5efe4f1b69ab7166d1a5a5616adebe902133ea3e4c189d87d7de2e21ddc17/bin/bowtie2-align-s --wrapper basic-0 -p 10 -x /cvmfs/data.galaxyproject.org/byhand/hg19/hg19full/bowtie2_index/hg19full -1 input_f.fastq -2 input_r.fastq"
....
....
Next is a tab-delimited section that describes the alignment of each sequence in detail.
HWI-D00461:188:HVGY2BCXY:1:1109:3430:66266 163 13 32889826 42 108M = 32889969 251 TTGGGACGAGCGCGTCTTCCGTAGTCCCAGTCCAGCGTGGCGGGGGAGCGCCTCACGCCCCGGGTCGCTGCCGCGGCTTCTTGCCCTTTTGTCTCTGCCAACCCCCAC 0D@@?GEHCHHCEHIDHH?1CCHCHI@1<CCCFC@GCCCEHIHCHICHC?HH=GHE1DE<CEHDEHHC<CCH/?HHG/<1<D@11D?G?FGHEHH01D00D;00<DH< AS:i:-5 XN:i:0 XM:i:1 XO:i:0 XG:i:0 NM:i:1 MD:Z:21C86 YS:i:-5 YT:Z:CP
1 |
QNAME |
Sequence ID |
2 |
FLAG |
Sequence quality expressed as a bitwise flag |
3 |
RNAME |
Chromosome |
4 |
POS |
Start Position |
5 |
MAPQ |
Mapping Quality |
6 |
CIGAR |
Describes positions of matches, insertions, deletions w.r.t reference |
7 |
RNEXT |
Ref. name of mate / next read |
8 |
PNEXT |
Position of mate / next read |
9 |
TLEN |
Observed Template length |
10 |
SEQ |
Sequence |
11 |
QUAL |
Base Qualities |
There can also be all manner of optional tags as extra columns introduce by an aligner or downstream analysis tool. A common use is the RG
tag which refers back to the read groups in the header.
Sorting and indexing
You will notice from the 3rd column that the reads are ordered according to their start position; whereas the reads in the fastq
file were arranged in order that they were generated on the flow cell. By default, bowtie2
produces a bam where the reads are in the same order as the fastq
. However, this is rather inconvenient for analysis where we require reads from the same location to be next to each other in the file.
An additional couple of steps have been performed after bowtie2; sorting the file according to genome position and producing an index file. The index file does not provide any useful information for us and cannot be viewed in Galaxy. However, we will need it later on when viewing the data in IGV.
Quality Flags
The “flags” in the sam file can represent useful QC information
- Read is unmapped
- Read is paired / unpaired
- Read failed QC
- Read is a PCR duplicate (see later)
The combination of any of these properties is used to derive a numeric value
For instance, a particular read has a flag of 163
Derivation
There is a set of properties that a read can possess. If a particular property is observed, a corresponding power of 2 is added multiplied by 1. The final value is derived by summing all the powers of 2.
69 (= 1 + 4 + 64) |
The read is paired, is the first read in the pair, and is unmapped. |
77 (= 1 + 4 + 8 + 64) |
The read is paired, is the first read in the pair, both are unmapped. |
83 (= 1 + 2 + 16 + 64) |
The read is paired, mapped in a proper pair, is the first read in the pair, and it is mapped to the reverse strand. |
99 (= 1 + 2 + 32 + 64) |
The read is paired, mapped in a proper pair, is the first read in the pair, and its mate is mapped to the reverse strand. |
133 (= 1 + 4 + 128) |
The read is paired, is the second read in the pair, and it is unmapped. |
137 (= 1 + 8 + 128) |
The read is paired, is the second read in the pair, and it is mapped while its mate is not. |
141 (= 1 + 4 + 8 + 128) |
The read is paired, is the second read in the pair, but both are unmapped. |
147 (= 1 + 2 + 16 + 128) |
The read is paired, mapped in a proper pair, is the second read in the pair, and mapped to the reverse strand. |
163 (= 1 + 2 + 32 + 128) |
The read is paired, mapped in a proper pair, is the second read in the pair, and its mate is mapped to the reverse strand. |
See also
Have a CIGAR!
The CIGAR (Compact Idiosyncratic Gapped Alignment Report) string is a way of encoding the match between a given sequence and the position it has been assigned in the genome. It is comprised by a series of letters and numbers to indicate how many consecutive bases have that mapping.
M |
alignment match |
I |
insertion |
D |
deletion |
N |
skipped |
S |
soft-clipping |
H |
hard-clipping |
e.g.
68M
- 68 bases matching the reference
1S67M
- 1 soft-clipped read followed by 67 matches
15M87N70M90N16M
- 15 matches following by 87 bases skipped followed by 70 matches etc.
3. Check the alignment stats
We will now generate a few basic statistics about the alignment of our data
- Select the tool NGS: SAMtools -> Flagstat
- In the BAM File to Convert box choose the bam file produced by bowtie2.
The tool will also report how many PCR Duplicates have been found in the data. But as we haven’t yet run any software to identify such reads, the flagstat output will show 0 reads.
- Find the tool SAMtools -> Idxstats
- In the BAM file dropdown select the bam file produced by bowtie2
The output of this tool will tell you how many reads aligned to each chromosome in your reference genome. For our example dataset we only have reads from a small region, so shouldn’t expect to see alignments to each chromosome.
About Duplicates
The preparation of a sequencing library requires PCR amplification of your starting material. This can lead to some DNA fragments being over-represented in your data. As our DNA fragments are formed in a random process, and relatively small compared to the number of bases to be sequenced from the genome (3Gb in humans), we tend to think the two DNA fragments that have identical starting and ending position are unlikely to have occurred due to chance. Some software, such as Picard will identify such artefacts and mark them for attention by downstream methods. i.e. they are not completely discarded from the analysis.
4. Mark Duplicates with Picard
- Use the tool GENOMICS TOOLKITS -> Picard -> MarkDuplicates
- In Select SAM/BAM dataset or dataset collection choose the bam file produced by bowtie2.
- What do you notice about the flag values for any reads that have the same start as another read?
- Interpret the meaning of these flags using the online tool
Warning the assumption about reads having the same start location being PCR duplicates falls down when we do sequencing for a very specific region of the genome. e.g. targeted sequencing from a panel of cancer genes. Running a tool to mark PCR duplicates on such data would recommend a high proportion of reads be ignored from further analysis.
5. (Optional) Re-run the alignment statistics
- Select the tool GENOMIC FILE MANIPULATION -> SAM/BAM -> Samtools flagstat
- In the BAM File to Convert box choose the bam file produced by the mark duplicates step
6. Download your bam file
For the next step you will need to download the bam
file that you produced after marking duplicates. To do this, you can click the floppy disk icon.
Make sure that you click both Download dataset and Download bam_index
Section 5. Visualising the aligned reads with IGV
Whilst Bioinformatics tools are very powerful and allow you to perform statistical analyses and test hypotheses, there is no substitute for looking at and exploring the data. A trained-eye can quite quickly get a sense of the data quality before any computational analyses have been run. Furthermore, as the person requesting the sequencing, you probably know a lot about the biological context of the samples and what to expect.
We will load the aligned reads that we have just created into IGV and start to get a feel for the process of variant calling
- Download IGV
You can download IGV for Windows using this link
Extract the zip file that you have downloaded
Double-Click the file igv
to launch IGV
If you are unable to download IGV, you should be able to run a web-app from the Broad Institute website with the same functionality.
https://igv.org/app/
- Load a reference Genome and some Data Tracks
By default, IGV should load with Human genome version hg19 already loaded. It is essential that you use the same genome version that the reads were aligned to. You can check / change the genome by clicking the drop-down menu in the upper-left
We can also load extra tracks into the browser that can help us understand our variant calls. We can load data from dbSNP which will tell us about common mutations that already been identified. These can be loaded via File -> Load from Server.. and selecting dbSNP 1.4.7
from the Variation and Repeats
section
- Navigate around IGV
When IGV loads up we start with a very high-level view of the genome where all chromosomes are visible. Such a view might be useful if we were interested in large copy-number variation across a cohort of samples. However, we are mostly interested in changes at the individual base-level which is not possible to view at this resolution. We need to navigate to a particular region of interest.
Alongside the drop-down menu used to change the genome, there is a drop-down menu to select a particular chromosome and a box where we can enter text. Inside the text box we can enter a particular genome interval of interest
e.g. chr1:10,000-11,000
IGV should now be displaying a region on chromosome 1 from base position 10,000
to 11,000
.
At this resolution, we can start to see the genome sequence. Each DNA base is represented by a different colour (A = green, C = blue) and it seems that this region is highly-repetitive; comprising mostly C
bases. We can zoom further in using the zoom control in the top right of IGV
We can use the zoom control, and also move along the genome by holding down by mouse button and sliding left-and-right, to navigate to whatever genomic location we want. If we known the name of the gene we want to interrogate we can navigate directly there using the text box
The text box should now update to show the coordinates of BRCA1
(chr17:....
). At the bottom of the screen we can now see the gene model for the gene BRCA1
. Genes are represented as lines and boxes. Lines represent intronic regions and boxes represent exonic regions. The arrows indicate the direction / strand of transcription for the gene.
- Load the aligned reads
Choose File > Load from File…, select the bam file that you downloaded from Galaxy, and click OK. Note that the bam and index files must be in the same directory for IGV to load these properly.
The main display of IGV should now update to hold tracks for the aligned reads from this bam file. It may seem like nothing is being displayed. This is because we are zoomed-out too far to be able to see the reads. Use the zoom function and move along the genome until you get to the first exon of BRCA1. After you have zoomed-in far enough you will start to see some grey rectangles. These are the aligned reads. Note that some downsampling may occur meaning that not all reads are displayed to reduce memory requirements.
If you hover over a particular read, how will see columns from the bam file being displayed such as the mapping quality and information about the paired reads.
Coloured-letters within the read indicate bases that are different to the reference genome. The entire read may be coloured differently to grey, which can indicate different things depending on how the display has been configured. For example, it can highlight paired-reads with an insert size different to that expected (see here). The display of aligned reads can be configured through the menus, as described here.
LS0tCnRpdGxlOiAiIgphdXRob3I6ICJNYXJrIER1bm5pbmciCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogICAgdG9jOiB5ZXMKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCgoKIyBIYW5kcy1vbiBOR1MgQW5hbHlzaXMgaW4gR2FsYXh5IGFuZCBJR1YKCiMjIyBTaGVmZmllbGQgQmlvaW5mb3JtYXRpY3MgQ29yZQo8aW1nIHNyYz0ibWVkaWEvbG9nby1zbS5wbmciIGFsaWduPXJpZ2h0PgoKd2ViIDogW3NiYy5zaGVmLmFjLnVrXShodHRwOi8vc2JjLnNoZWYuYWMudWspICAKdHdpdHRlcjogW1NoZWZmQmlvaW5mQ29yZV0oaHR0cHM6Ly90d2l0dGVyLmNvbS9TaGVmZkJpb2luZkNvcmUpICAKZW1haWw6IFtiaW9pbmZvcm1hdGljcy1jb3JlQHNoZWZmaWVsZC5hYy51a10oYmlvaW5mb3JtYXRpY3MtY29yZUBzaGVmZmllbGQuYWMudWspCgotLS0tLQoKIyBUdXRvcmlhbCBPdmVydmlldwoKVGhpcyB0dXRvcmlhbCB3aWxsIGNvdmVyIHRoZSBiYXNpY3Mgb2YgTkdTIGFuYWx5c2lzIHVzaW5nIEdhbGF4eTsgYSBvcGVuLXNvdXJjZSB3ZWItYmFzZWQgcGxhdGZvcm0gZm9yIHRoZSBhbmFseXNpcyBvZiBiaW9sb2dpY2FsIGRhdGEuIFlvdSBzaG91bGQgZ2FpbiBhbiBhcHByZWNpYXRpb24gb2YgdGhlIHRhc2tzIGludm9sdmVkIGluIGEgdHlwaWNhbCBOR1MgYW5hbHlzaXMgYW5kIGJlIGNvbWZvcnRhYmxlIHdpdGggdGhlIG91dHB1dHMgZ2VuZXJhdGVkIGJ5IGEgc2VxdWVuY2luZyBzZXJ2aWNlLllvdSB3aWxsIGFsc28gdXNlIHRoZSBJbnRlZ3JhdGl2ZSBHZW5vbWljcyBWaWV3ZXIgKElHVikgdG8gKnZpZXcqIHRoZSBhbGlnbmVkIHJlYWRzIGluIGFuIGludGVyYWN0aXZlIG1hbm5lci4KClBhcnRzIG9mIHRoaXMgdHV0b3JpYWwgYXJlIGJhc2VkIG9uIHRoZSBOR1MgdHV0b3JpYWwgZnJvbSB0aGUgR2FsYXh5IFByb2plY3QgYW5kIHRoZSBJR1YgdHV0b3JpYWwgZnJvbSB0aGUgR3JpZmZpbiBsYWIuCgotIFtHYWxheHkgTkdTIFR1dG9yaWFsXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL3R1dG9yaWFscy9uZ3MvKQotIFtJR1YgVHV0b3JpYWxdKGh0dHBzOi8vZ2l0aHViLmNvbS9ncmlmZml0aGxhYi9ybmFzZXFfdHV0b3JpYWwvd2lraS9JR1YtVHV0b3JpYWwpCgpUaGUgdHV0b3JpYWwgY292ZXJzIHRoZSBmb2xsb3dpbmcgc3RlcHMgaW4gb3VyIGFuYWx5c2lzIHBpcGVsaW5lCgohW10obWVkaWEvcGlwZWxpbmUucG5nKQoKLS0tLS0KCiMjIEJhY2tncm91bmQKCiMjIyMgV2hlcmUgZG8gdGhlIGRhdGEgaW4gdGhpcyB0dXRvcmlhbCBjb21lIGZyb20/ClRoZSBkYXRhIGZvciB0aGlzIHR1dG9yaWFsIGFyZSBwdWJsaWNseS1hdmFpbGFibGUgZXhvbWUgc2VxdWVuY2luZyBkYXRhICpkb3duc2FtcGxlZCogdG8gdGhlIEJSQ0EyIHJlZ2lvbiBmcm9tIGEgZmljdGl0aW91cyBwYXRpZW50LiBXZSB3aWxsIHVzZSB0aGVzZSBkYXRhIHRocm91Z2hvdXQgdGhlIGNvdXJzZSB0byBjYWxsIHZhcmlhbnRzLCBmaWx0ZXIgYW5kIGRpc2N1c3MgdGhlIGNsaW5pY2FsIGltcGFjdCBvZiBhbnkgbXV0YXRpb25zLiAKCiMgU2VjdGlvbiAxOiBQcmVwYXJhdGlvbiAKCioqSWdub3JlIGlmIHlvdSBoYXZlIGFscmVhZHkgY3JlYXRlZCBhIEdhbGF4eSBhY2NvdW50IGFuZCB1cGxvYWRlZCB0aGUgZXhhbXBsZSBkYXRhIGluIGEgcHJldmlvdXMgZXhlcmNpc2UqKgoKIyMjIyAxLiAgUmVnaXN0ZXIgYXMgYSBuZXcgdXNlciBvbiBvbmUgb2YgdGhlIHB1YmxpYyBHYWxheHkgc2VydmVycwoKLSBodHRwczovL3VzZWdhbGF4eS5vcmcvCi0gaHR0cHM6Ly91c2VnYWxheHkub3JnLmF1Ci0gaHR0cHM6Ly91c2VnYWxheHkuZXUKCioqTWFrZSBzdXJlIHlvdSBjaGVjayB5b3VyIGVtYWlsIHRvIGFjdGl2YXRlIHlvdXIgYWNjb3VudCoqCgojIyMjIDIuICBJbXBvcnQgdGhlIGRhdGEgZm9yIHRoZSB3b3Jrc2hvcC4KCldlIGNhbiBnb2luZyB0byBpbXBvcnQgdGhlIFsqZmFzdHEqIGZpbGVzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GQVNUUV9mb3JtYXQpIGZvciB0aGlzIGV4cGVyaW1lbnQuIFRoaXMgaXMgYSBzdGFuZGFyZCBmb3JtYXQgZm9yIHN0b3JpbmcgcmF3IHNlcXVlbmNpbmcgcmVhZHMgYW5kIHRoZWlyIGFzc29jaWF0ZWQgcXVhbGl0eSBzY29yZXMuIEhvd2V2ZXIsIGFzIHdlIHdpbGwgc2VlLCB0aGUgcmVwcmVzZW50YXRpb24gb2YgdGhlIHF1YWxpdHkgc2NvcmVzIGhhcyBjaGFuZ2VkIG92ZXIgdGltZS4KCllvdSBjYW4gaW1wb3J0IHRoZSBkYXRhIGJ5OgoKMS4gIEluIHRoZSB0b29sIHBhbmVsIGxvY2F0ZWQgb24gdGhlIGxlZnQsIHVuZGVyIEJhc2ljIFRvb2xzIHNlbGVjdCAqKkdldAogICAgRGF0YSA+IFVwbG9hZCBGaWxlKiouIENsaWNrIG9uIHRoZSAqKlBhc3RlL0ZldGNoIGRhdGEqKiBidXR0b24gb24gdGhlCiAgICBib3R0b20gc2VjdGlvbiBvZiB0aGUgcG9wLXVwIHdpbmRvdy4KMi4gIFVwbG9hZCB0aGUgc2VxdWVuY2UgZGF0YSBieSBzZWxlY3RpbmcgdGhlIGZpbGVzIGBKb2VCbG9nc0JSQ0FQYW5lbF9SMS5mYXN0cWAgYW5kIGBKb2VCbG9nc0JSQ0FQYW5lbF9SMi5mYXN0cWAuIFlvdSBkb24ndCBuZWVkIHRvIHNwZWNpZnkgdGhlIGZpbGUgdHlwZSBvciBnZW5vbWUgYnVpbGQuIEdhbGF4eSBzaG91bGQgYmUgYWJsZSB0byBtYWtlIGEgcmVhc29uYWJsZSBndWVzcy4KCgozLiAgWW91IHNob3VsZCBub3cgaGF2ZSB0aGVzZSAyIGZpbGVzIGluIHlvdXIgaGlzdG9yeToKICAgIC0gYEpvZUJsb2dzQlJDQVBhbmVsX1IxLmZhc3RxYAogICAgLSBgSm9lQmxvZ3NCUkNBUGFuZWxfUjIuZmFzdHFgCgoKCiMgU2VjdGlvbiAyOiBGYXN0cSBmaWxlIGZvcm1hdAoKWW91IGNhbiB2aWV3IHRoZSBmaWxlcyB5b3UganVzdCB1cGxvYWRlZCBieSBjbGlja2luZyB0aGUgKipleWUgaWNvbioqIHRoZSBoaXN0b3J5IGl0ZW0uIFRoZSBmaXJzdCBmZXcgbGluZXMgc2hvdWxkIHJlYWQgYXMgZm9sbG93cwoKCioqSm9lQmxvZ3NCUkNBUGFuZWxfUjEuZmFzdHEqKgoKYGBgCkBIV0ktRDAwNDYxOjE4ODpIVkdZMkJDWFk6MToxMTAxOjEzNjM6ODQxNDgvMQpUR1RHVENBVFRUQ1RBVFRBVENUVFRHR0FBQ0FBQ0NBVEdBQVRUQUdUQ0NDVFRHR0dHVFRUVENBQUFUR0NUR0NBQ0FDVEdBQ1RDQUNBQ0FUVFRBVFRUR0dUVENUR1RUVFRUR0NDVFRDQ0NUTk4KKwpERERERElISUlJSUlISUlJSUlJSUlJSUhJSUlJSUlJSUlISUlJSUlJSEhJSUlJSUlJSElJSUhJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUhISURISElIQyMKYGBgCgoqKkpvZUJsb2dzQlJDQVBhbmVsX1IyLmZhc3RxKioKCmBgYApASFdJLUQwMDQ2MToxODg6SFZHWTJCQ1hZOjE6MTEwMToxMzYzOjg0MTQ4LzIKVEdHQUFBR0FDVFRUVEdHR0dHR0dHR0FHVEFUVFRUVENUVEdUVFRDVEdHVFRUVEdHVFRUVFRUVEdBVENDR0dHQUFBR0FUVFRUR1RUVFRUVEdHQUdHVFRHR0FDVFRUVEdHR0dBR0dHR0FBQUFOCisKPDAwPDwxMTExPDE8MTEvMC88Ly8vPC88MDExMURGMTE8PDExMTExPDExMTExPDEvMTwxRDEvLy88PDExPDw8LzwxMTExPDwxMTxERDE8Ly88MTEwPDExLzExPDA8MDwvMDwwPDwtLy88PEZFCmBgYAoKClRoZSBmaXJzdCBsaW5lIGlzIHRoZSB1bmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCBzZXF1ZW5jZWQgcmVhZC4gSXQgY2FuIGJlIHVzZWQgdG8gZW5jb2RlIGluZm9ybWF0aW9uIHN1Y2ggYXMgdGhlICpzZXF1ZW5jaW5nIG1hY2hpbmUqLCAqZmxvdyBjZWxsKiBhbmQgKmxhbmUqIHRoYXQgdGhlIHJlYWQgd2FzIGdlbmVyYXRlZCBmcm9tIGFuZCB0aGUgcGh5c2ljYWwgY29vcmRpbmF0ZXMgb24gdGhlIGxhbmUuICAKClRoZSBxdWFsaXR5IHNjb3JlcyBhcmUgW0FTQ0lJXShodHRwOi8vYXNjaWktY29kZS5jb20vKSByZXByZXNlbnRhdGlvbnMgb2YgaG93IGNvbmZpZGVudCB3ZSBhcmUgdGhhdCBhIHBhcnRpY3VsYXIgYmFzZSBoYXMgYmVlbiBjYWxsZWQgY29ycmVjdGx5LiBMZXR0ZXJzIHRoYXQgYXJlIGZ1cnRoZXIgYWxvbmcgdGhlIGFscGhhYmV0IGluZGljYXRlIGhpZ2hlciBjb25maWRlbmNlLiBUaGlzIGlzIGltcG9ydGFudCB3aGVuIHRyeWluZyB0byBpZGVudGlmeSB0eXBlcyBvZiBnZW5vbWUgdmFyaWF0aW9uIHN1Y2ggYXMgc2luZ2xlIGJhc2UgY2hhbmdlcywgYnV0IGlzIGFsc28gaW5kaWNhdGl2ZSBvZiB0aGUgb3ZlcmFsbCBxdWFsaXR5IG9mIHRoZSBzZXF1ZW5jaW5nLiBEaWZmZXJlbnQgc2NhbGVzIGhhdmUgYmVlbiBlbXBsb3llZCBvdmVyIHRpbWUgKHJlc3VsdGluZyBpbiBhIGRpZmZlcmVudCBzZXQgb2YgY2hhcmFjdGVycyBhcHBlYXJpbmcgaW4gdGhlIGZpbGUpLiAKCgojIyMgRGVyaXZpbmcgdGhlIFF1YWxpdHkgU2NvcmUKCkZpcnN0IG9mIGFsbCwgd2UgY29udmVydCB0aGUgYmFzZS1jYWxsaW5nIHByb2JhYmlsaXR5IChwKSBpbnRvIGEgYFFgIHNjb3JlIHVzaW5nIHRoZSBmb3JtdWxhCgotIFF1YWxpdHkgc2NvcmVzICQkIFEgPSAtMTBsb2dfezEwfXAkJAogICAgKyBRID0gMzAsIHA9MC4wMDEKICAgICsgUSA9IDIwLCBwPTAuMDEKICAgICsgUSA9IDEwLCBwPTAuMQotIFRoZXNlIG51bWVyaWMgcXVhbnRpdGllcyBhcmUgKmVuY29kZWQqIGFzIFsqKkFTQ0lJKipdKGh0dHA6Ly9hc2NpaS1jb2RlLmNvbS8pIGNvZGUKICAgICsgQXQgbGVhc3QgMzMgdG8gZ2V0IHRvIG1lYW5pbmdmdWwgY2hhcmFjdGVycwogICAgKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0ZBU1RRX2Zvcm1hdCkKICAgIAohW10obWVkaWEvcGhyZWQucG5nKSAgICAgIAoKIyMjIFF1YWxpdHkgU2NvcmVzIHRvIHByb2JhYmlsaXRpZXMKCi0gbG9vay11cCB0aGUgQVNDSUkgY29kZSBmb3IgZWFjaCBjaGFyYWN0ZXIKLSBzdWJ0cmFjdCB0aGUgb2Zmc2V0IHRvIGdldCB0aGUgUSBzY29yZQotIGNvbnZlcnQgdG8gYSBwcm9iYWJpbGl0eSB1c2luZyB0aGUgZm9ybXVsYTotCgokJCBwID0gMTBeey1RLzEwfSAkJAoKTGV0J3Mgc2VlIHRoaXMgY2FsY3VsYXRpb24gZm9yIHRoZSBmaXJzdCBmZXcgYmFzZXMgb2YgdGhlIGZpcnN0IHJlYWQgaW4gYEpvZUJsb2dzQlJDQVBhbmVsX1IxLmZhc3RxYDsgYERERERESUhJLi4uLmAKCkNoYXJhY3RlciAgfCBDb2RlIHwgTWludXMgMzMgT2Zmc2V0IHwgUHJvYmFiaWxpdHkKLS0tLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLQpEICB8IDY4IHwgMzUgfCAwLjAwMDMxNjIyNzgKRCAgfCA2OCB8IDM1IHwgMC4wMDAzMTYyMjc4CkQgIHwgNjggfCAzNSB8IDAuMDAwMzE2MjI3OApEICB8IDY4IHwgMzUgfCAwLjAwMDMxNjIyNzgKRCAgfCA2OCB8IDM1IHwgMC4wMDAzMTYyMjc4CkkgIHwgNzMgfCA0MCB8IDAuMDAwMTAwMDAwMApIICB8IDcyIHwgMzkgfCAwLjAwMDEyNTg5MjUKSSAgfCA3MyB8IDQwIHwgMC4wMDAxMDAwMDAwCgpJbiBwcmFjdGljZSwgd2UgZG9uJ3QgaGF2ZSB0byBjb252ZXJ0IHRoZSB2YWx1ZXMgYXMgd2UgaGF2ZSBzb2Z0d2FyZSB0aGF0IHdpbGwgZG8gdGhpcyBhdXRvbWF0aWNhbGx5CgotLS0tLQoKIyBTZWN0aW9uIDM6IFF1YWxpdHkgYXNzZXNzbWVudCB3aXRoIEZhc3RRQwoKW0Zhc3RRQ10oaHR0cHM6Ly93d3cuYmlvaW5mb3JtYXRpY3MuYmFicmFoYW0uYWMudWsvcHJvamVjdHMvZmFzdHFjLykgaXMgYSBwb3B1bGFyIHRvb2wgZnJvbSBbQmFicmFoYW0gSW5zdGl0dXRlIEJpb2luZm9ybWF0aWNzIEdyb3VwXShodHRwczovL3d3dy5iaW9pbmZvcm1hdGljcy5iYWJyYWhhbS5hYy51ay9pbmRleC5odG1sKSB1c2VkIGZvciAqcXVhbGl0eSBhc3Nlc3NtZW50KiBvZiBzZXF1ZW5jaW5nIGRhdGEuIE1vc3QgQmlvaW5mb3JtYXRpY3MgcGlwZWxpbmVzIHdpbGwgdXNlIEZhc3RRQywgb3Igc2ltaWxhciB0b29scyBpbiB0aGUgZmlyc3Qgc3RhZ2Ugb2YgdGhlIGFuYWx5c2lzLiBUaGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LmJpb2luZm9ybWF0aWNzLmJhYnJhaGFtLmFjLnVrL3Byb2plY3RzL2Zhc3RxYy9IZWxwLykgZm9yIEZhc3RRQyB3aWxsIGhlbHAgeW91IHRvIGludGVycHJldCB0aGUgcGxvdHMgYW5kIHN0YXRzIHByb2R1Y2VkIGJ5IHRoZSB0b29sLiBBIHRyYWZmaWMgbGlnaHQgc3lzdGVtIGlzIHVzZWQgdG8gYWxlcnQgdGhlIHVzZXIncyBhdHRlbnRpb24gdG8gcG9zc2libGUgaXNzdWVzLiAKCi0gRnJvbSB0aGUgbGVmdCBoYW5kIHRvb2wgcGFuZWwgaW4gR2FsYXh5LCB1bmRlciAqR0VOT01JQyBGSUxFIE1BTklQVUxBVElPTiosIHNlbGVjdCAqRkFTVFEgUXVhbGl0eSBDb250cm9sIC0+IEZhc3RRQyoKLSBTZWxlY3Qgb25lIG9mIHRoZSBGQVNUUSBmaWxlcyBhcyBpbnB1dCBhbmQgKkV4ZWN1dGUqIHRoZSB0b29sLgotIFdoZW4gdGhlIHRvb2wgZmluaXNoZXMgcnVubmluZywgeW91IHNob3VsZCBoYXZlIGFuIEhUTUwgZmlsZSBpbiB5b3VyIEhpc3RvcnkuIENsaWNrIG9uIHRoZSBleWUgaWNvbiB0byB2aWV3IHRoZSB2YXJpb3VzIHF1YWxpdHkgbWV0cmljcy4KClRoZSBtb3N0IGltcG9ydGFudCBpbWFnZSBpcyB3aGV0aGVyIHRoZSBiYXNlIHF1YWxpdHkgZGVjcmVhc2VzIHNpZ25pZmljYW50bHkgb3ZlciB0aGUgbGVuZ3RoIG9mIHRoZSByZWFkCgohW10obWVkaWEvZmFzdHFjLTJhLnBuZykKCkdvb2QgcXVhbGl0eSBkYXRhIHNob3VsZCBsb29rIHNvbWV0aGluZyBsaWtlOi0KCiFbXShtZWRpYS9mYXN0cWMtMmIucG5nKQoKCgpMb29rIGF0IHRoZSBnZW5lcmF0ZWQgRmFzdFFDIG1ldHJpY3MgZm9yIHlvdXIgdXBsb2FkZWQgZmFzdHEgZmlsZXMuIFRoaXMgZGF0YSBsb29rcyBwcmV0dHkgZ29vZCAtIGhpZ2ggcGVyLWJhc2UgcXVhbGl0eSBzY29yZXMgKG1vc3QgYWJvdmUgMzApLgoKQWxsIGlzIG5vdCBsb3N0IGlmIHdlIG9ic2VydmUgcG9vciBxdWFsaXR5IGJhc2VzIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgcmVhZC4gVGhlcmUgYXJlIGEgbnVtYmVyIG9mICp0cmltbWluZyogb3B0aW9ucyB0aGF0IHdlIGNhbiB1c2UgZm9yIE5HUyBkYXRhIGFuZCBzb21lIG9mIHRoZXNlIGFyZSBhdmFpbGFibGUgdGhyb3VnaCBHYWxheHkuIENoZWNrIG91dCB0aGUgW1RyaW1tbWluZyBSZWFkc10oaHR0cHM6Ly9nYWxheHlwcm9qZWN0Lm9yZy90dXRvcmlhbHMvbmdzLyN0cmltbWluZy1yZWFkcykgc2VjdGlvbiBvZiB0aGUgR2FsYXh5IE5HUyB0dXRvcmlhbCBpZiB5b3UgYXJlIGludGVyZXN0ZWQgaW4gaG93IHdlIGNhbiB0cmltIG91ciByZWFkcy4KCkl0IGlzIGFsc28gd29ydGggYmVhcmluZyBpbiBtaW5kIHRoYXQgdGhlIHRvb2wgaXMgYmxpbmQgdG8gdGhlIHBhcnRpY3VsYXIgdHlwZSBvZiBzZXF1ZW5jaW5nIHlvdSBhcmUgcGVyZm9ybWluZyAoaS5lLiB3aG9sZS1nZW5vbWUsIENoSVAtc2VxLCBSTkEtc2VxKSBhbmQgdGhlIG9yZ2FuaXNtIGJlaW5nIHNlcXVlbmNlZCwgc28gc29tZSB3YXJuaW5ncyBtaWdodCBiZSBleHBlY3RlZCBkdWUgdG8gdGhlIG5hdHVyZSBvZiB5b3VyIGV4cGVyaW1lbnQuIEZvciBpbnN0YW5jZSwgdGhlcmUgYXJlIGtub3duIHNlcXVlbmNpbmcgY29tcG9zaXRpb24gYmlhc2VzIHRoYXQgY2FuIG9jY3VyIGF0IHRoZSBiZWdpbm5pbmcgb2YgUk5BLXNlcSByZWFkcy4gCgojIyBBZ2dyZWdhdGluZyBRQyByZXBvcnRzIHdpdGggbXVsdGlxYwoKRm9yIGRhdGFzZXRzIHdpdGggbGFyZ2UgbnVtYmVycyBvZiBmYXN0cSBmaWxlcywgaXQgbWF5IGJlIHVzZWZ1bCB0byBhZ2dyZWdhdGUgdGhlIGluZGl2aWR1YWwgcmVwb3J0cyBpbnRvIGEgc2luZ2xlIGNvbWJpbmVkIHJlcG9ydC4gCgotIFVuZGVyICpHRU5PTUlDIEZJTEUgTUFOSVBVTEFUSU9OKiwgc2VsZWN0ICpGQVNUUSBRdWFsaXR5IENvbnRyb2wgLT4gTXVsdGlRQyoKLSBNYWtlIHN1cmUgKlNvZnR3YXJlIG5hbWUqIGlzIHNldCB0byBgRmFzdFFDYAotIEluICpSZXN1bHRzIGZpbGUqLCBzZWxlY3QgdGhlICoqUmF3RGF0YSoqIHJlc3VsdHMgZmlsZXMgdGhhdCB5b3UgaGF2ZSBqdXN0IGdlbmVyYXRlZAoKWW91IHNob3VsZCB0aGVuIGJlIGFibGUgdG8gdmlldyB0aGUgZmFzdHFjIHBsb3RzIGZvciBib3RoIHRoZSBmYXN0cSBmaWxlcyBvbiB0aGUgc2FtZSBwYWdlLgoKIyBTZWN0aW9uIDQ6IEFsaWdubWVudAoKV2UgZG9uJ3QgcmVhbGx5IHNwZW5kIG11Y2ggdGltZSBsb29rIGF0ICpmYXN0cSogZmlsZXMsIGFzIG1vc3Qgb2Ygb3VyIHRpbWUgaXMgc3BlbnQgd2l0aCAqYWxpZ25lZCogcmVhZHMuIGkuZS4gd2UgaGF2ZSB1c2VkIHNvbWUgc29mdHdhcmUgdG8gdGVsbCB1cyB3aGVyZWFib3V0cyBpbiB0aGUgZ2Vub21lIGVhY2ggcmVhZCBiZWxvbmdzIHRvLiBUaGlzIHdpbGwgKnVzdWFsbHkqIGJlIHBlcmZvcm1lZCBmb3IgeW91IGFzIHBhcnQgb2YgYSBzZXF1ZW5jaW5nIHNlcnZpY2UsIGJ1dCBpdCBpcyBnb29kIHRvIGdldCBhbiBhcHByZWNpYXRpb24gb2YgdGhlIHN0ZXBzIGludm9sdmVkLgoKSW4gdGhpcyBzZWN0aW9uIHdlIG1hcCB0aGUgcmVhZHMgaW4gb3VyIEZBU1RRIGZpbGVzIHRvIGEgcmVmZXJlbmNlIGdlbm9tZS4gCgpBIHBsZXRob3JhIG9mIGRpZmZlcmVudCB0b29scyBoYXZlIGJlZW4gd3JpdHRlbiB0byBwZXJmb3JtIHRoaXMgdGFzaywgYW5kIHdlIHdpbGwgbm90IGRlc2NyaWJlIGl0IGluIGRldGFpbC4gTGlua3MgdG8gc29tZSBrZXkgcHVibGljYXRpb25zIGFyZSBnaXZlbiBiZWxvdzotCgogICsgMjAwOSBCb3d0aWUgMSAtIFtMYW5nbWVhZCBldCBhbF0oaHR0cDovL2dlbm9tZWJpb2xvZ3kuY29tL2NvbnRlbnQvMTAvMy9SMjUpCiAgKyAyMDEyIEJvd3RpZSAyIC0gW0xhbmdtZWFkIGFuZCBTYWx6YmVyZ10oaHR0cDovL3d3dy5uYXR1cmUuY29tL25tZXRoL2pvdXJuYWwvdjkvbjQvZnVsbC9ubWV0aC4xOTIzLmh0bSkKICArIDIwMDkgQldBIC0gW0xpIGFuZCBEdXJiaW5dKGh0dHA6Ly9iaW9pbmZvcm1hdGljcy5veGZvcmRqb3VybmFscy5vcmcvY29udGVudC8yNS8xNC8xNzU0LmxvbmcpCiAgKyAyMDEwIEJXQSAtIFtMaSBhbmQgRHVyYmluXShodHRwOi8vYmlvaW5mb3JtYXRpY3Mub3hmb3Jkam91cm5hbHMub3JnL2NvbnRlbnQvMjYvNS81ODkpCiAgKyAyMDEzIEJXQS1NRU0gLSBbTGldKGh0dHA6Ly9hcnhpdi5vcmcvYWJzLzEzMDMuMzk5NykKCkFsaWdubWVudCByZWxpZXMgb24gdGhlIHJlZmVyZW5jZSBnZW5vbWUgYmVpbmcgKmluZGV4ZWQqIHNvIHRoYXQgdGhlIHNlcXVlbmNpbmcgcmVhZHMgY2FuIGJlIGxvY2F0ZWQgbW9yZSBlZmZpY2llbnRseS4gVGhlIGdlbm9tZSBpbmRleCBpcyBhIGhpZ2hseS1hY2Nlc3NpYmxlIGRhdGEgc3RydWN0dXJlLCBhbmQgR2FsYXh5IGluY2x1ZGVzIGluZGljZXMgZm9yIG1hbnkgcG9wdWxhciBnZW5vbWVzLiAKCiMjIyMgMS5BbGlnbiB0aGUgZXhhbXBsZSBmaWxlcyAgCgohW10obWVkaWEvYm93dGllMi10b29sLnBuZykKCi0gRmluZCB0aGUgdG9vbCAqR0VOT01JQ1MgQU5BTFlTSVMqIC0+ICpNYXBwaW5nKiAtPiAqQm93dGllMioKICArIGFsdGVybmF0aXZlbHksIHR5cGUgYGJvd3RpZWAgaW4gdGhlIHNlYXJjaCBib3gKLSBJbiAqSXMgdGhpcyBzaW5nbGUtZW5kIG9yIFBhaXJlZC1lbmQ/KiBTZWxlY3QgKipQYWlyZWQtZW5kKioKLSBTZXQgKkZhc3RRIGZpbGUgIzEqIGFuZCAqRmFzdFEgZmlsZSAjMiogdG8gdGhlIHR3byBmYXN0cSBmaWxlcyB5b3UgdXBsb2FkZWQgaW4gdGhlIHByZXZpb3VzIHN0ZXAKLSBNYWtlIHN1cmUgdGhlIHJlZmVyZW5jZSBnZW5vbWUgaXMgc2V0IHRvICoqSHVtYW4gKEhvbW8gc2FwaWVucyk6aGcxOSoqCi0gUHJlc3MgKkV4ZWN1dGUqCi0gV2FpdCEKClRoZSByZXN1bHQgd2lsbCBiZSBhIGAuYmFtYCBmaWxlIHRoYXQgd2Ugd2lsbCBkZXNjcmliZSBpbiB0aGUgbmV4dCBzZWN0aW9uLiBUaGlzIGZpbGUgaXMgbm90IGh1bWFuLXJlYWRhYmxlLCBhcyBpdCBpcyBjb21wcmVzc2VkLiBCdXQgd2UgY2FuIGNvbnZlcnQgdG8gYSByZWFkYWJsZSBmb3JtYXQgZm9yIGlsbHVzdHJhdGlvbiBwdXJwb3Nlcy4KCiMjIyMgMi4gVmlldyB0aGUgYWxpZ25tZW50cwoKMS4gIENsaWNrIG9uIHRoZSBleWUgb2YgdGhlIHJlc3VsdGluZyBmaWxlIHRvIHZpZXcgdGhlIGFsaWdubWVudHMuCgoKIVtdKG1lZGlhL2JhbS1hbGlnbm1lbnRzLnBuZykKCiMjIyBBYm91dCB0aGUgYGJhbWAgZmlsZSBmb3JtYXQKClVubGlrZSBtb3N0IG9mIEJpb2luZm9ybWF0aWNzLCBhICpzaW5nbGUgc3RhbmRhcmQqIGZpbGUgZm9ybWF0IGhhcyBlbWVyZ2VkIGZvciBhbGlnbmVkIHJlYWRzLiBNb3Jlb3ZlciwgdGhpcyBmaWxlIGZvcm1hdCBpcyBjb25zaXN0ZW50IHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB5b3UgaGF2ZSBETkEtc2VxLCBSTkEtc2VxLCBDaElQLXNlcS4uLiBkYXRhLiAKClRoZSBgYmFtYCBmaWxlIGlzIGEgY29tcHJlc3NlZCwgYmluYXJ5LCB2ZXJzaW9uIG9mIGEgYHNhbWAgZmlsZS4KCiMjIyBUaGUgYC5zYW1gIGZpbGUKCi0gKipTKiplcXVlbmNlICoqQSoqbGlnbm1lbnQvKipNKiphcCAoc2FtKSAKLSBUaGUgb3V0cHV0IGZyb20gYW4gYWxpZ25lciBzdWNoIGFzIGBid2FgCi0gU2FtZSBmb3JtYXQgcmVnYXJkbGVzcyBvZiBzZXF1ZW5jaW5nIHByb3RvY29sIChpLmUuIFJOQS1zZXEsIENoSVAtc2VxLCBETkEtc2VxIGV0YykKLSBNYXkgY29udGFpbiB1bi1tYXBwZWQgcmVhZHMKLSBQb3RlbnRpYWxseSBsYXJnZSBzaXplIG9uIGRpc2s7IH4xMDBzIG9mIEdiCiAgICArIENhbiBiZSBtYW5pcHVsYXRlZCB3aXRoIHN0YW5kYXJkIHVuaXggdG9vbHM7IGUuZy4gKmNhdCosICpoZWFkKiwgKmdyZXAqLCAqbW9yZSosICpsZXNzKi4uLi4KLSBPZmZpY2lhbCBzcGVjaWZpY2F0aW9uIGNhbiBiZSBbb2J0YWluZWQgb25saW5lXShodHRwOi8vc2FtdG9vbHMuZ2l0aHViLmlvL2h0cy1zcGVjcy9TQU12MS5wZGYpOiAtCi0gV2Ugbm9ybWFsbHkgd29yayBvbiBhIGNvbXByZXNzZWQgdmVyc2lvbiBjYWxsZWQgYSBgLmJhbWAgZmlsZS4gU2VlIGxhdGVyLgotICpIZWFkZXIqIGxpbmVzIHN0YXJ0aW5nIHdpdGggYW4gYEBgIGNoYXJhY3RlciwgZm9sbG93ZWQgYnkgdGFiLWRlbGltaXRlZCBsaW5lcwogICAgKyBIZWFkZXIgZ2l2ZXMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGFsaWdubWVudCBhbmQgcmVmZXJlbmNlcyBzZXF1ZW5jZXMgdXNlZAoKClRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBoZWFkZXIgbGlzdHMgdGhlIG5hbWVzIChgU05gKSBvZiB0aGUgc2VxdWVuY2VzIChjaHJvbW9zb21lcykgdXNlZCBpbiBhbGlnbm1lbnQsIHRoZWlyIGxlbmd0aCAoYExOYCkgYW5kIGEgKm1kNXN1bSogIltkaWdpdGFsIGZpbmdlcnByaW50XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9NZDVzdW0pIiBvZiB0aGUgYC5mYXN0YWAgZmlsZSB1c2VkIGZvciBhbGlnbm1lbnQgKGBNNWApLgoKYGBgCgpASEQgVk46MS4wIFNPOmNvb3JkaW5hdGUKQFNRIFNOOmNocjEwIExOOjEzNTUzNDc0NwpAU1EgU046Y2hyMTEgTE46MTM1MDA2NTE2CkBTUSBTTjpjaHIxMV9nbDAwMDIwMl9yYW5kb20gTE46NDAxMDMKQFNRIFNOOmNocjEyIExOOjEzMzg1MTg5NQpAU1EgU046Y2hyMTMgTE46MTE1MTY5ODc4CkBTUSBTTjpjaHIxNCBMTjoxMDczNDk1NDAKQFNRIFNOOmNocjE1IExOOjEwMjUzMTM5MgpAU1EgU046Y2hyMTYgTE46OTAzNTQ3NTMKLi4uLi4KLi4uLi4KCmBgYAoKCldlIGFsc28gaGF2ZSBhIHNlY3Rpb24gd2hlcmUgd2UgY2FuIHJlY29yZCB0aGUgcHJvY2Vzc2luZyBzdGVwcyB1c2VkIHRvIGRlcml2ZSB0aGUgZmlsZQpgYGAKQFBHIElEOmJvd3RpZTIgUE46Ym93dGllMiBWTjoyLjMuNC4xIENMOiIvamV0c3RyZWFtL3NjcmF0Y2gwL21haW4vY29uZGEvZW52cy9tdWxsZWQtdjEtNjVkNWVmZTRmMWI2OWFiNzE2NmQxYTVhNTYxNmFkZWJlOTAyMTMzZWEzZTRjMTg5ZDg3ZDdkZTJlMjFkZGMxNy9iaW4vYm93dGllMi1hbGlnbi1zIC0td3JhcHBlciBiYXNpYy0wIC1wIDEwIC14IC9jdm1mcy9kYXRhLmdhbGF4eXByb2plY3Qub3JnL2J5aGFuZC9oZzE5L2hnMTlmdWxsL2Jvd3RpZTJfaW5kZXgvaGcxOWZ1bGwgLTEgaW5wdXRfZi5mYXN0cSAtMiBpbnB1dF9yLmZhc3RxIgouLi4uCi4uLi4KCmBgYAoKTmV4dCBpcyBhICp0YWItZGVsaW1pdGVkKiBzZWN0aW9uIHRoYXQgZGVzY3JpYmVzIHRoZSBhbGlnbm1lbnQgb2YgZWFjaCBzZXF1ZW5jZSBpbiBkZXRhaWwuIAoKYGBgCkhXSS1EMDA0NjE6MTg4OkhWR1kyQkNYWToxOjExMDk6MzQzMDo2NjI2NgkxNjMJMTMJMzI4ODk4MjYJNDIJMTA4TQk9CTMyODg5OTY5CTI1MQlUVEdHR0FDR0FHQ0dDR1RDVFRDQ0dUQUdUQ0NDQUdUQ0NBR0NHVEdHQ0dHR0dHQUdDR0NDVENBQ0dDQ0NDR0dHVENHQ1RHQ0NHQ0dHQ1RUQ1RUR0NDQ1RUVFRHVENUQ1RHQ0NBQUNDQ0NDQUMJMERAQD9HRUhDSEhDRUhJREhIPzFDQ0hDSElAMTxDQ0NGQ0BHQ0NDRUhJSENISUNIQz9ISD1HSEUxREU8Q0VIREVISEM8Q0NILz9ISEcvPDE8REAxMUQ/Rz9GR0hFSEgwMUQwMEQ7MDA8REg8CUFTOmk6LTUgWE46aTowIFhNOmk6MSBYTzppOjAgWEc6aTowIE5NOmk6MSBNRDpaOjIxQzg2IFlTOmk6LTUgWVQ6WjpDUAoKYGBgCgohW10obWVkaWEvc2FtLWVudHJ5LWV4cGxhaW5lZC5wbmcpCgpDb2x1bW4gfCBPZmZpY2lhbCBOYW1lIHwgQnJpZWYKLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLQoxICAgICAgfCBRTkFNRSAgICAgICAgICB8IFNlcXVlbmNlIElECjIgICAgICB8IEZMQUcgICAgICAgICAgIHwgU2VxdWVuY2UgcXVhbGl0eSBleHByZXNzZWQgYXMgYSBiaXR3aXNlIGZsYWcKMyAgICAgIHwgUk5BTUUgICAgICAgICAgfCBDaHJvbW9zb21lCjQgICAgICB8IFBPUyAgICAgICAgICAgIHwgU3RhcnQgUG9zaXRpb24KNSAgICAgIHwgTUFQUSAgICAgICAgICAgfCBNYXBwaW5nIFF1YWxpdHkKNiAgICAgIHwgQ0lHQVIgICAgICAgICAgfCBEZXNjcmliZXMgcG9zaXRpb25zIG9mIG1hdGNoZXMsIGluc2VydGlvbnMsIGRlbGV0aW9ucyB3LnIudCByZWZlcmVuY2UKNyAgICAgIHwgUk5FWFQgICAgICAgICAgfCBSZWYuIG5hbWUgb2YgbWF0ZSAvIG5leHQgcmVhZAo4ICAgICAgfCBQTkVYVCAgICAgICAgICB8IFBvc2l0aW9uIG9mIG1hdGUgLyBuZXh0IHJlYWQKOSAgICAgIHwgVExFTiAgICAgICAgICAgfCBPYnNlcnZlZCBUZW1wbGF0ZSBsZW5ndGgKMTAgICAgIHwgU0VRICAgICAgICAgICAgfCBTZXF1ZW5jZQoxMSAgICAgfCBRVUFMICAgICAgICAgICB8IEJhc2UgUXVhbGl0aWVzCgpUaGVyZSBjYW4gYWxzbyBiZSBhbGwgbWFubmVyIG9mIG9wdGlvbmFsIHRhZ3MgYXMgZXh0cmEgY29sdW1ucyBpbnRyb2R1Y2UgYnkgYW4gYWxpZ25lciBvciBkb3duc3RyZWFtIGFuYWx5c2lzIHRvb2wuIEEgY29tbW9uIHVzZSBpcyB0aGUgYFJHYCB0YWcgd2hpY2ggcmVmZXJzIGJhY2sgdG8gdGhlIHJlYWQgZ3JvdXBzIGluIHRoZSBoZWFkZXIuCgoKIyMjIFNvcnRpbmcgYW5kIGluZGV4aW5nCgpZb3Ugd2lsbCBub3RpY2UgZnJvbSB0aGUgM3JkIGNvbHVtbiB0aGF0IHRoZSByZWFkcyBhcmUgb3JkZXJlZCBhY2NvcmRpbmcgdG8gdGhlaXIgc3RhcnQgcG9zaXRpb247IHdoZXJlYXMgdGhlIHJlYWRzIGluIHRoZSBgZmFzdHFgIGZpbGUgd2VyZSBhcnJhbmdlZCBpbiBvcmRlciB0aGF0IHRoZXkgd2VyZSBnZW5lcmF0ZWQgb24gdGhlIGZsb3cgY2VsbC4gQnkgZGVmYXVsdCwgYGJvd3RpZTJgIHByb2R1Y2VzIGEgYmFtIHdoZXJlIHRoZSByZWFkcyBhcmUgaW4gdGhlIHNhbWUgb3JkZXIgYXMgdGhlIGBmYXN0cWAuIEhvd2V2ZXIsIHRoaXMgaXMgcmF0aGVyIGluY29udmVuaWVudCBmb3IgYW5hbHlzaXMgd2hlcmUgd2UgcmVxdWlyZSByZWFkcyBmcm9tIHRoZSBzYW1lIGxvY2F0aW9uIHRvIGJlIG5leHQgdG8gZWFjaCBvdGhlciBpbiB0aGUgZmlsZS4KCkFuIGFkZGl0aW9uYWwgY291cGxlIG9mIHN0ZXBzIGhhdmUgYmVlbiBwZXJmb3JtZWQgYWZ0ZXIgYm93dGllMjsgc29ydGluZyB0aGUgZmlsZSBhY2NvcmRpbmcgdG8gZ2Vub21lIHBvc2l0aW9uIGFuZCBwcm9kdWNpbmcgYW4gKmluZGV4KiBmaWxlLiBUaGUgaW5kZXggZmlsZSBkb2VzIG5vdCBwcm92aWRlIGFueSB1c2VmdWwgaW5mb3JtYXRpb24gZm9yIHVzIGFuZCBjYW5ub3QgYmUgdmlld2VkIGluIEdhbGF4eS4gSG93ZXZlciwgd2Ugd2lsbCBuZWVkIGl0IGxhdGVyIG9uIHdoZW4gdmlld2luZyB0aGUgZGF0YSBpbiBJR1YuIAoKIyMjIFF1YWxpdHkgRmxhZ3MKClRoZSAqImZsYWdzIiogaW4gdGhlIHNhbSBmaWxlIGNhbiByZXByZXNlbnQgdXNlZnVsIFFDIGluZm9ybWF0aW9uCgogICsgUmVhZCBpcyB1bm1hcHBlZAogICsgUmVhZCBpcyBwYWlyZWQgLyB1bnBhaXJlZAogICsgUmVhZCBmYWlsZWQgUUMKICArIFJlYWQgaXMgYSBQQ1IgZHVwbGljYXRlIChzZWUgbGF0ZXIpCgpUaGUgY29tYmluYXRpb24gb2YgYW55IG9mIHRoZXNlIHByb3BlcnRpZXMgaXMgdXNlZCB0byBkZXJpdmUgYSBudW1lcmljIHZhbHVlCgoKRm9yIGluc3RhbmNlLCBhIHBhcnRpY3VsYXIgcmVhZCBoYXMgYSBmbGFnIG9mIDE2MwoKIVtdKG1lZGlhL2ZsYWctaGlnaGxpZ2h0LnBuZykKCgojIyMgRGVyaXZhdGlvbgoKVGhlcmUgaXMgYSBzZXQgb2YgcHJvcGVydGllcyB0aGF0IGEgcmVhZCBjYW4gcG9zc2Vzcy4gSWYgYSBwYXJ0aWN1bGFyIHByb3BlcnR5IGlzIG9ic2VydmVkLCBhIGNvcnJlc3BvbmRpbmcgcG93ZXIgb2YgMiBpcyBhZGRlZCBtdWx0aXBsaWVkIGJ5IDEuIFRoZSBmaW5hbCB2YWx1ZSBpcyBkZXJpdmVkIGJ5IHN1bW1pbmcgYWxsIHRoZSBwb3dlcnMgb2YgMi4KCiFbXShodHRwczovL2dhbGF4eXByb2plY3Qub3JnL3R1dG9yaWFscy9uZ3Mvc2FtX2ZsYWcucG5nKQoKRmxhZyBWYWx1ZSB8IE1lYW5pbmcKLS0tLS0tLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCjY5ICg9IDEgKyA0ICsgNjQpIAl8IFRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIGZpcnN0IHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBpcyB1bm1hcHBlZC4KNzcgKD0gMSArIDQgKyA4ICsgNjQpIHwJVGhlIHJlYWQgaXMgcGFpcmVkLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYm90aCBhcmUgdW5tYXBwZWQuCjgzICg9IDEgKyAyICsgMTYgKyA2NCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0IGlzIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCjk5ICg9IDEgKyAyICsgMzIgKyA2NCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgZmlyc3QgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0cyBtYXRlIGlzIG1hcHBlZCB0byB0aGUgcmV2ZXJzZSBzdHJhbmQuCjEzMyAoPSAxICsgNCArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYW5kIGl0IGlzIHVubWFwcGVkLgoxMzcgKD0gMSArIDggKyAxMjgpICB8CVRoZSByZWFkIGlzIHBhaXJlZCwgaXMgdGhlIHNlY29uZCByZWFkIGluIHRoZSBwYWlyLCBhbmQgaXQgaXMgbWFwcGVkIHdoaWxlIGl0cyBtYXRlIGlzIG5vdC4KMTQxICg9IDEgKyA0ICsgOCArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIGlzIHRoZSBzZWNvbmQgcmVhZCBpbiB0aGUgcGFpciwgYnV0IGJvdGggYXJlIHVubWFwcGVkLgoxNDcgKD0gMSArIDIgKyAxNiArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgc2Vjb25kIHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBtYXBwZWQgdG8gdGhlIHJldmVyc2Ugc3RyYW5kLgoxNjMgKD0gMSArIDIgKyAzMiArIDEyOCkgfAlUaGUgcmVhZCBpcyBwYWlyZWQsIG1hcHBlZCBpbiBhIHByb3BlciBwYWlyLCBpcyB0aGUgc2Vjb25kIHJlYWQgaW4gdGhlIHBhaXIsIGFuZCBpdHMgbWF0ZSBpcyBtYXBwZWQgdG8gdGhlIHJldmVyc2Ugc3RyYW5kLgoKCgpTZWUgYWxzbwoKLSBodHRwczovL2Jyb2FkaW5zdGl0dXRlLmdpdGh1Yi5pby9waWNhcmQvZXhwbGFpbi1mbGFncy5odG1sCgojIyMgSGF2ZSBhIENJR0FSIQoKCiFbXShtZWRpYS9jaWdhci1oaWdobGlnaHQucG5nKQoKVGhlICoqKkNJR0FSKioqICgqKkMqKm9tcGFjdCAqKkkqKmRpb3N5bmNyYXRpYyAqKkcqKmFwcGVkICoqQWxpZ25tZW50KiogKipSKiplcG9ydCkgc3RyaW5nIGlzIGEgd2F5IG9mIGVuY29kaW5nIHRoZSBtYXRjaCBiZXR3ZWVuIGEgZ2l2ZW4gc2VxdWVuY2UgYW5kIHRoZSBwb3NpdGlvbiBpdCBoYXMgYmVlbiBhc3NpZ25lZCBpbiB0aGUgZ2Vub21lLiBJdCBpcyBjb21wcmlzZWQgYnkgYSBzZXJpZXMgb2YgbGV0dGVycyBhbmQgbnVtYmVycyB0byBpbmRpY2F0ZSBob3cgbWFueSBjb25zZWN1dGl2ZSBiYXNlcyBoYXZlIHRoYXQgbWFwcGluZy4KCgogCiBDb2RlICB8IERlc2NyaXB0aW9uCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tCk0gIHwgYWxpZ25tZW50IG1hdGNoCkkgIHwgaW5zZXJ0aW9uCkQgIHwgZGVsZXRpb24KTiAgfCBza2lwcGVkClMgIHwgc29mdC1jbGlwcGluZwpIICB8IGhhcmQtY2xpcHBpbmcKCgplLmcuCgotIGA2OE1gCiAgICArIDY4IGJhc2VzIG1hdGNoaW5nIHRoZSByZWZlcmVuY2UKLSBgMVM2N01gCiAgICArIDEgc29mdC1jbGlwcGVkIHJlYWQgZm9sbG93ZWQgYnkgNjcgbWF0Y2hlcwotIGAxNU04N043ME05ME4xNk1gCiAgICArIDE1IG1hdGNoZXMgZm9sbG93aW5nIGJ5IDg3IGJhc2VzIHNraXBwZWQgZm9sbG93ZWQgYnkgNzAgbWF0Y2hlcyBldGMuCgoKIyMjIyAzLiBDaGVjayB0aGUgYWxpZ25tZW50IHN0YXRzCgpXZSB3aWxsIG5vdyBnZW5lcmF0ZSBhIGZldyBiYXNpYyBzdGF0aXN0aWNzIGFib3V0IHRoZSBhbGlnbm1lbnQgb2Ygb3VyIGRhdGEKCjEuIFNlbGVjdCB0aGUgdG9vbCAqTkdTOiBTQU10b29scyAtPiBGbGFnc3RhdCogCjIuIEluIHRoZSAqQkFNIEZpbGUgdG8gQ29udmVydCogYm94IGNob29zZSB0aGUgYmFtIGZpbGUgcHJvZHVjZWQgYnkgYm93dGllMi4KCgpUaGUgdG9vbCB3aWxsIGFsc28gcmVwb3J0IGhvdyBtYW55ICoqKlBDUiBEdXBsaWNhdGVzKioqIGhhdmUgYmVlbiBmb3VuZCBpbiB0aGUgZGF0YS4gQnV0IGFzIHdlIGhhdmVuJ3QgeWV0IHJ1biBhbnkgc29mdHdhcmUgdG8gaWRlbnRpZnkgc3VjaCByZWFkcywgdGhlIGZsYWdzdGF0IG91dHB1dCB3aWxsIHNob3cgMCByZWFkcy4KCjEuIEZpbmQgdGhlIHRvb2wgKlNBTXRvb2xzIC0+IElkeHN0YXRzKgoyLiBJbiB0aGUgKkJBTSBmaWxlKiBkcm9wZG93biBzZWxlY3QgdGhlIGJhbSBmaWxlIHByb2R1Y2VkIGJ5IGJvd3RpZTIKClRoZSBvdXRwdXQgb2YgdGhpcyB0b29sIHdpbGwgdGVsbCB5b3UgaG93IG1hbnkgcmVhZHMgYWxpZ25lZCB0byBlYWNoIGNocm9tb3NvbWUgaW4geW91ciByZWZlcmVuY2UgZ2Vub21lLiBGb3Igb3VyIGV4YW1wbGUgZGF0YXNldCB3ZSBvbmx5IGhhdmUgcmVhZHMgZnJvbSBhIHNtYWxsIHJlZ2lvbiwgc28gc2hvdWxkbid0IGV4cGVjdCB0byBzZWUgYWxpZ25tZW50cyB0byBlYWNoIGNocm9tb3NvbWUuCgoKCiMjIyBBYm91dCBEdXBsaWNhdGVzCgpUaGUgcHJlcGFyYXRpb24gb2YgYSBzZXF1ZW5jaW5nIGxpYnJhcnkgcmVxdWlyZXMgKlBDUiogYW1wbGlmaWNhdGlvbiBvZiB5b3VyIHN0YXJ0aW5nIG1hdGVyaWFsLiBUaGlzIGNhbiBsZWFkIHRvIHNvbWUgRE5BIGZyYWdtZW50cyBiZWluZyBvdmVyLXJlcHJlc2VudGVkIGluIHlvdXIgZGF0YS4gQXMgb3VyIEROQSBmcmFnbWVudHMgYXJlIGZvcm1lZCBpbiBhIHJhbmRvbSBwcm9jZXNzLCBhbmQgcmVsYXRpdmVseSBzbWFsbCBjb21wYXJlZCB0byB0aGUgbnVtYmVyIG9mIGJhc2VzIHRvIGJlIHNlcXVlbmNlZCBmcm9tIHRoZSBnZW5vbWUgKDNHYiBpbiBodW1hbnMpLCB3ZSB0ZW5kIHRvIHRoaW5rIHRoZSB0d28gRE5BIGZyYWdtZW50cyB0aGF0IGhhdmUgaWRlbnRpY2FsIHN0YXJ0aW5nIGFuZCBlbmRpbmcgcG9zaXRpb24gYXJlIHVubGlrZWx5IHRvIGhhdmUgb2NjdXJyZWQgZHVlIHRvIGNoYW5jZS4gU29tZSBzb2Z0d2FyZSwgc3VjaCBhcyBbUGljYXJkXShodHRwOi8vYnJvYWRpbnN0aXR1dGUuZ2l0aHViLmlvL3BpY2FyZC8pIHdpbGwgaWRlbnRpZnkgc3VjaCBhcnRlZmFjdHMgYW5kICptYXJrKiB0aGVtIGZvciBhdHRlbnRpb24gYnkgZG93bnN0cmVhbSBtZXRob2RzLiBpLmUuIHRoZXkgYXJlIG5vdCBjb21wbGV0ZWx5IGRpc2NhcmRlZCBmcm9tIHRoZSBhbmFseXNpcy4KCiFbXShtZWRpYS9wY3JfZHVwcy5wbmcpCgojIyMjIDQuIE1hcmsgRHVwbGljYXRlcyB3aXRoIFBpY2FyZAoKMS4gVXNlIHRoZSB0b29sICpHRU5PTUlDUyBUT09MS0lUUyAtPiBQaWNhcmQgLT4gTWFya0R1cGxpY2F0ZXMqCjIuIEluICpTZWxlY3QgU0FNL0JBTSBkYXRhc2V0IG9yIGRhdGFzZXQgY29sbGVjdGlvbiogY2hvb3NlIHRoZSBiYW0gZmlsZSBwcm9kdWNlZCBieSBib3d0aWUyLgozLiBXaGF0IGRvIHlvdSBub3RpY2UgYWJvdXQgdGhlICpmbGFnKiB2YWx1ZXMgZm9yIGFueSByZWFkcyB0aGF0IGhhdmUgdGhlIHNhbWUgKnN0YXJ0KiBhcyBhbm90aGVyIHJlYWQ/IAo0LiBJbnRlcnByZXQgdGhlIG1lYW5pbmcgb2YgdGhlc2UgZmxhZ3MgdXNpbmcgdGhlIG9ubGluZSB0b29sCiAgKyBodHRwczovL2Jyb2FkaW5zdGl0dXRlLmdpdGh1Yi5pby9waWNhcmQvZXhwbGFpbi1mbGFncy5odG1sCgoqKldhcm5pbmcqKiB0aGUgYXNzdW1wdGlvbiBhYm91dCByZWFkcyBoYXZpbmcgdGhlIHNhbWUgc3RhcnQgbG9jYXRpb24gYmVpbmcgUENSIGR1cGxpY2F0ZXMgZmFsbHMgZG93biB3aGVuIHdlIGRvIHNlcXVlbmNpbmcgZm9yIGEgdmVyeSBzcGVjaWZpYyByZWdpb24gb2YgdGhlIGdlbm9tZS4gZS5nLiB0YXJnZXRlZCBzZXF1ZW5jaW5nIGZyb20gYSBwYW5lbCBvZiBjYW5jZXIgZ2VuZXMuIFJ1bm5pbmcgYSB0b29sIHRvIG1hcmsgUENSIGR1cGxpY2F0ZXMgb24gc3VjaCBkYXRhIHdvdWxkIHJlY29tbWVuZCBhIGhpZ2ggcHJvcG9ydGlvbiBvZiByZWFkcyBiZSBpZ25vcmVkIGZyb20gZnVydGhlciBhbmFseXNpcy4KICAKIyMjIyA1LiAoT3B0aW9uYWwpIFJlLXJ1biB0aGUgYWxpZ25tZW50IHN0YXRpc3RpY3MKCjEuIFNlbGVjdCB0aGUgdG9vbCAqR0VOT01JQyBGSUxFIE1BTklQVUxBVElPTiAtPiBTQU0vQkFNIC0+IFNhbXRvb2xzIGZsYWdzdGF0KiAKMi4gSW4gdGhlICpCQU0gRmlsZSB0byBDb252ZXJ0KiBib3ggY2hvb3NlIHRoZSBiYW0gZmlsZSBwcm9kdWNlZCBieSB0aGUgKm1hcmsgZHVwbGljYXRlcyogc3RlcAoKIyMjIyA2LiBEb3dubG9hZCB5b3VyIGJhbSBmaWxlCgpGb3IgdGhlIG5leHQgc3RlcCB5b3Ugd2lsbCBuZWVkIHRvIGRvd25sb2FkIHRoZSBgYmFtYCBmaWxlIHRoYXQgeW91IHByb2R1Y2VkIGFmdGVyICptYXJraW5nIGR1cGxpY2F0ZXMqLiBUbyBkbyB0aGlzLCB5b3UgY2FuIGNsaWNrIHRoZSBmbG9wcHkgZGlzayBpY29uLgoKIVtdKG1lZGlhL2Rvd25sb2FkX2JhbS5wbmcpCgoqKk1ha2Ugc3VyZSB0aGF0IHlvdSBjbGljayBib3RoIERvd25sb2FkIGRhdGFzZXQgYW5kIERvd25sb2FkIGJhbV9pbmRleCoqCgojIFNlY3Rpb24gNS4gVmlzdWFsaXNpbmcgdGhlIGFsaWduZWQgcmVhZHMgd2l0aCBJR1YKCldoaWxzdCBCaW9pbmZvcm1hdGljcyB0b29scyBhcmUgdmVyeSBwb3dlcmZ1bCBhbmQgYWxsb3cgeW91IHRvIHBlcmZvcm0gc3RhdGlzdGljYWwgYW5hbHlzZXMgYW5kIHRlc3QgaHlwb3RoZXNlcywgdGhlcmUgaXMgbm8gc3Vic3RpdHV0ZSBmb3IgKipsb29raW5nIGF0IGFuZCBleHBsb3JpbmcgdGhlIGRhdGEqKi4gQSB0cmFpbmVkLWV5ZSBjYW4gcXVpdGUgcXVpY2tseSBnZXQgYSBzZW5zZSBvZiB0aGUgZGF0YSBxdWFsaXR5IGJlZm9yZSBhbnkgY29tcHV0YXRpb25hbCBhbmFseXNlcyBoYXZlIGJlZW4gcnVuLiBGdXJ0aGVybW9yZSwgYXMgdGhlIHBlcnNvbiByZXF1ZXN0aW5nIHRoZSBzZXF1ZW5jaW5nLCB5b3UgcHJvYmFibHkga25vdyBhIGxvdCBhYm91dCB0aGUgYmlvbG9naWNhbCBjb250ZXh0IG9mIHRoZSBzYW1wbGVzIGFuZCB3aGF0IHRvIGV4cGVjdC4KCldlIHdpbGwgbG9hZCB0aGUgYWxpZ25lZCByZWFkcyB0aGF0IHdlIGhhdmUganVzdCBjcmVhdGVkIGludG8gSUdWIGFuZCBzdGFydCB0byBnZXQgYSBmZWVsIGZvciB0aGUgcHJvY2VzcyBvZiB2YXJpYW50IGNhbGxpbmcKCjEuIERvd25sb2FkIElHVgoKWW91IGNhbiBkb3dubG9hZCBJR1YgZm9yIFdpbmRvd3MgdXNpbmcgdGhpcyBsaW5rIAoKLSBodHRwczovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvZG93bmxvYWQKCipFeHRyYWN0KiB0aGUgemlwIGZpbGUgdGhhdCB5b3UgaGF2ZSBkb3dubG9hZGVkCgoKCiFbXShtZWRpYS9leHRyYWN0X2lndi5QTkcpCgoKCkRvdWJsZS1DbGljayB0aGUgZmlsZSBgaWd2YCB0byBsYXVuY2ggSUdWCgoKCiFbXShtZWRpYS9ydW5faWd2LlBORykKCjxmb250IHNpemU9IjUiPgpJZiB5b3UgYXJlIHVuYWJsZSB0byBkb3dubG9hZCBJR1YsIHlvdSBzaG91bGQgYmUgYWJsZSB0byBydW4gYSB3ZWItYXBwIGZyb20gdGhlIEJyb2FkIEluc3RpdHV0ZSB3ZWJzaXRlIHdpdGggdGhlIHNhbWUgZnVuY3Rpb25hbGl0eS4KCmh0dHBzOi8vaWd2Lm9yZy9hcHAvCgo8L2ZvbnQ+CgoKMi4gTG9hZCBhIHJlZmVyZW5jZSBHZW5vbWUgYW5kIHNvbWUgRGF0YSBUcmFja3MKCkJ5IGRlZmF1bHQsIElHViBzaG91bGQgbG9hZCB3aXRoIEh1bWFuIGdlbm9tZSB2ZXJzaW9uICpoZzE5KiBhbHJlYWR5IGxvYWRlZC4gSXQgaXMgZXNzZW50aWFsIHRoYXQgeW91IHVzZSB0aGUgKipzYW1lIGdlbm9tZSB2ZXJzaW9uKiogdGhhdCB0aGUgcmVhZHMgd2VyZSBhbGlnbmVkIHRvLiBZb3UgY2FuIGNoZWNrIC8gY2hhbmdlIHRoZSBnZW5vbWUgYnkgY2xpY2tpbmcgdGhlIGRyb3AtZG93biBtZW51IGluIHRoZSB1cHBlci1sZWZ0CgohW10obWVkaWEvc2VsZWN0X2dlbm9tZS5QTkcpCgpXZSBjYW4gYWxzbyBsb2FkIGV4dHJhICp0cmFja3MqIGludG8gdGhlIGJyb3dzZXIgdGhhdCBjYW4gaGVscCB1cyB1bmRlcnN0YW5kIG91ciB2YXJpYW50IGNhbGxzLiBXZSBjYW4gbG9hZCBkYXRhIGZyb20gKmRiU05QKiB3aGljaCB3aWxsIHRlbGwgdXMgYWJvdXQgY29tbW9uIG11dGF0aW9ucyB0aGF0IGFscmVhZHkgYmVlbiBpZGVudGlmaWVkLiBUaGVzZSBjYW4gYmUgbG9hZGVkIHZpYSAqRmlsZSogLT4gKkxvYWQgZnJvbSBTZXJ2ZXIuLiogYW5kIHNlbGVjdGluZyBgZGJTTlAgMS40LjdgIGZyb20gdGhlIGBWYXJpYXRpb24gYW5kIFJlcGVhdHNgIHNlY3Rpb24KCiFbXShtZWRpYS9hdmFpbGFibGVfZGF0YXNldHMuUE5HKQoKCjMuIE5hdmlnYXRlIGFyb3VuZCBJR1YKCldoZW4gSUdWIGxvYWRzIHVwIHdlIHN0YXJ0IHdpdGggYSB2ZXJ5IGhpZ2gtbGV2ZWwgdmlldyBvZiB0aGUgZ2Vub21lIHdoZXJlICphbGwqIGNocm9tb3NvbWVzIGFyZSB2aXNpYmxlLiBTdWNoIGEgdmlldyBtaWdodCBiZSB1c2VmdWwgaWYgd2Ugd2VyZSBpbnRlcmVzdGVkIGluIGxhcmdlIGNvcHktbnVtYmVyIHZhcmlhdGlvbiBhY3Jvc3MgYSBjb2hvcnQgb2Ygc2FtcGxlcy4gSG93ZXZlciwgd2UgYXJlIG1vc3RseSBpbnRlcmVzdGVkIGluIGNoYW5nZXMgYXQgdGhlIGluZGl2aWR1YWwgYmFzZS1sZXZlbCB3aGljaCBpcyBub3QgcG9zc2libGUgdG8gdmlldyBhdCB0aGlzIHJlc29sdXRpb24uIFdlIG5lZWQgdG8gbmF2aWdhdGUgdG8gYSBwYXJ0aWN1bGFyIHJlZ2lvbiBvZiBpbnRlcmVzdC4KCkFsb25nc2lkZSB0aGUgZHJvcC1kb3duIG1lbnUgdXNlZCB0byBjaGFuZ2UgdGhlIGdlbm9tZSwgdGhlcmUgaXMgYSBkcm9wLWRvd24gbWVudSB0byBzZWxlY3QgYSBwYXJ0aWN1bGFyIGNocm9tb3NvbWUgYW5kIGEgYm94IHdoZXJlIHdlIGNhbiBlbnRlciB0ZXh0LiBJbnNpZGUgdGhlIHRleHQgYm94IHdlIGNhbiBlbnRlciBhIHBhcnRpY3VsYXIgZ2Vub21lIGludGVydmFsIG9mIGludGVyZXN0CgplLmcuIGBjaHIxOjEwLDAwMC0xMSwwMDBgCgoKSUdWIHNob3VsZCBub3cgYmUgZGlzcGxheWluZyBhIHJlZ2lvbiBvbiBjaHJvbW9zb21lIDEgZnJvbSBiYXNlIHBvc2l0aW9uIGAxMCwwMDBgIHRvIGAxMSwwMDBgLiAKCiFbXShtZWRpYS96b29tX3JlZ2lvbi5QTkcpCgoKQXQgdGhpcyByZXNvbHV0aW9uLCB3ZSBjYW4gc3RhcnQgdG8gc2VlIHRoZSAqZ2Vub21lIHNlcXVlbmNlKi4gRWFjaCBETkEgYmFzZSBpcyByZXByZXNlbnRlZCBieSBhIGRpZmZlcmVudCBjb2xvdXIgKEEgPSBncmVlbiwgQyA9IGJsdWUpIGFuZCBpdCBzZWVtcyB0aGF0IHRoaXMgcmVnaW9uIGlzIGhpZ2hseS1yZXBldGl0aXZlOyBjb21wcmlzaW5nIG1vc3RseSBgQ2AgYmFzZXMuIFdlIGNhbiB6b29tIGZ1cnRoZXIgaW4gdXNpbmcgdGhlIHpvb20gY29udHJvbCBpbiB0aGUgdG9wIHJpZ2h0IG9mIElHVgoKIVtdKG1lZGlhL2hvd190b196b29tLlBORykKCldlIGNhbiB1c2UgdGhlIHpvb20gY29udHJvbCwgYW5kIGFsc28gbW92ZSBhbG9uZyB0aGUgZ2Vub21lIGJ5IGhvbGRpbmcgZG93biBieSBtb3VzZSBidXR0b24gYW5kIHNsaWRpbmcgbGVmdC1hbmQtcmlnaHQsIHRvIG5hdmlnYXRlIHRvIHdoYXRldmVyIGdlbm9taWMgbG9jYXRpb24gd2Ugd2FudC4gSWYgd2Uga25vd24gdGhlIG5hbWUgb2YgdGhlIGdlbmUgd2Ugd2FudCB0byBpbnRlcnJvZ2F0ZSB3ZSBjYW4gbmF2aWdhdGUgZGlyZWN0bHkgdGhlcmUgdXNpbmcgdGhlIHRleHQgYm94CgohW10obWVkaWEvc2VsZWN0X3JlZ2lvbi5QTkcpCgpUaGUgdGV4dCBib3ggc2hvdWxkIG5vdyB1cGRhdGUgdG8gc2hvdyB0aGUgY29vcmRpbmF0ZXMgb2YgYEJSQ0ExYCAoYGNocjE3Oi4uLi5gKS4gQXQgdGhlIGJvdHRvbSBvZiB0aGUgc2NyZWVuIHdlIGNhbiBub3cgc2VlIHRoZSAqZ2VuZSBtb2RlbCogZm9yIHRoZSBnZW5lIGBCUkNBMWAuICBHZW5lcyBhcmUgcmVwcmVzZW50ZWQgYXMgbGluZXMgYW5kIGJveGVzLiBMaW5lcyByZXByZXNlbnQgaW50cm9uaWMgcmVnaW9ucyBhbmQgYm94ZXMgcmVwcmVzZW50IGV4b25pYyByZWdpb25zLiBUaGUgYXJyb3dzIGluZGljYXRlIHRoZSBkaXJlY3Rpb24gLyBzdHJhbmQgb2YgdHJhbnNjcmlwdGlvbiBmb3IgdGhlIGdlbmUuCgohW10obWVkaWEvZ2VuZV9yZWdpb24uUE5HKQoKNC4gTG9hZCB0aGUgYWxpZ25lZCByZWFkcwoKQ2hvb3NlIEZpbGUgPiBMb2FkIGZyb20gRmlsZS4uLiwgc2VsZWN0IHRoZSBiYW0gZmlsZSB0aGF0IHlvdSBkb3dubG9hZGVkIGZyb20gR2FsYXh5LCBhbmQgY2xpY2sgT0suIE5vdGUgdGhhdCB0aGUgYmFtIGFuZCBpbmRleCBmaWxlcyBtdXN0IGJlIGluIHRoZSBzYW1lIGRpcmVjdG9yeSBmb3IgSUdWIHRvIGxvYWQgdGhlc2UgcHJvcGVybHkuCgohW10obWVkaWEvc2VsZWN0X2JhbS5QTkcpCgpUaGUgbWFpbiBkaXNwbGF5IG9mIElHViBzaG91bGQgbm93IHVwZGF0ZSB0byBob2xkIHRyYWNrcyBmb3IgdGhlIGFsaWduZWQgcmVhZHMgZnJvbSB0aGlzIGJhbSBmaWxlLiBJdCBtYXkgc2VlbSBsaWtlIG5vdGhpbmcgaXMgYmVpbmcgZGlzcGxheWVkLiBUaGlzIGlzIGJlY2F1c2Ugd2UgYXJlIHpvb21lZC1vdXQgdG9vIGZhciB0byBiZSBhYmxlIHRvIHNlZSB0aGUgcmVhZHMuICoqVXNlIHRoZSB6b29tIGZ1bmN0aW9uIGFuZCBtb3ZlIGFsb25nIHRoZSBnZW5vbWUgdW50aWwgeW91IGdldCB0byB0aGUgZmlyc3QgZXhvbiBvZiBCUkNBMSoqLiBBZnRlciB5b3UgaGF2ZSB6b29tZWQtaW4gZmFyIGVub3VnaCB5b3Ugd2lsbCBzdGFydCB0byBzZWUgc29tZSBncmV5IHJlY3RhbmdsZXMuICpUaGVzZSBhcmUgdGhlIGFsaWduZWQgcmVhZHMqLiBOb3RlIHRoYXQgc29tZSAqZG93bnNhbXBsaW5nKiBtYXkgb2NjdXIgbWVhbmluZyB0aGF0IG5vdCBhbGwgcmVhZHMgYXJlIGRpc3BsYXllZCB0byByZWR1Y2UgbWVtb3J5IHJlcXVpcmVtZW50cy4KCklmIHlvdSBob3ZlciBvdmVyIGEgcGFydGljdWxhciByZWFkLCBob3cgd2lsbCBzZWUgY29sdW1ucyBmcm9tIHRoZSBiYW0gZmlsZSBiZWluZyBkaXNwbGF5ZWQgc3VjaCBhcyB0aGUgbWFwcGluZyBxdWFsaXR5IGFuZCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgcGFpcmVkIHJlYWRzLgoKQ29sb3VyZWQtbGV0dGVycyB3aXRoaW4gdGhlIHJlYWQgaW5kaWNhdGUgYmFzZXMgdGhhdCBhcmUgZGlmZmVyZW50IHRvIHRoZSByZWZlcmVuY2UgZ2Vub21lLiBUaGUgZW50aXJlIHJlYWQgbWF5IGJlIGNvbG91cmVkIGRpZmZlcmVudGx5IHRvIGdyZXksIHdoaWNoIGNhbiBpbmRpY2F0ZSBkaWZmZXJlbnQgdGhpbmdzIGRlcGVuZGluZyBvbiBob3cgdGhlIGRpc3BsYXkgaGFzIGJlZW4gY29uZmlndXJlZC4gRm9yIGV4YW1wbGUsIGl0IGNhbiBoaWdobGlnaHQgcGFpcmVkLXJlYWRzIHdpdGggYW4gKmluc2VydCBzaXplKiBkaWZmZXJlbnQgdG8gdGhhdCBleHBlY3RlZCAoW3NlZSBoZXJlXShodHRwczovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvaW50ZXJwcmV0aW5nX2luc2VydF9zaXplKSkuIFRoZSBkaXNwbGF5IG9mIGFsaWduZWQgcmVhZHMgY2FuIGJlIGNvbmZpZ3VyZWQgdGhyb3VnaCB0aGUgbWVudXMsIGFzIGRlc2NyaWJlZCBbaGVyZV0oaHR0cDovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9zb2Z0d2FyZS9pZ3YvUHJlZmVyZW5jZXMjQWxpZ25tZW50cykuIAo=