How to manipulate a gene list

The golden rule before we start Always keep a backup of the output from the pipeline, never work on the original data!

There are various tasks you might wish to perform on a gene list

  • Search for our favourite gene
  • Sort / Rank according to statistic or p-value
  • Filter to obtain genes with particular cut-off and fold-change
  • Re-order / re-arrange columns

Our recommended tools to perform such operations would be a programming language such as R / Python so that the operations can be scripted and automated. As a compromise, our Galaxy server provides various operations through an intuitive interface and allows the user to build a workflow to a chain of simple operations.

There is a special reason why you shouldn’t trust Excel as your many means of interrogating the results. Sometimes it can be unhelpful and convert gene identifers into dates. No, really!

Please also bear in mind that over-processing of a results file in Excel may diminish how useful it is to Bioinformatic analysis in the future. Here are some materials you might like to check out

We will only scratch the surface of what is possible with Galaxy. If you are new to the software, you can check out our course:- http://galaxycam.github.io/

Different online tools or GUIs will take different types of input, but will probably involve some combination of the operations mentioned above. Therefore, we will introduce some tools in Galaxy that should allow you to manipulate your data into the required form. Later, we will give examples of workflows for particular gene set enrichment / pathways analysis tools.

In the first generic example, we will show some common manipulations on a gene list using Galaxy:-

Common tasks in Galaxy

Upload the gene list in csv form

The gene list .csv file can be uploaded into Galaxy. In this example we want to choose the file with no p-value cut-offs applied

Get Data -> Upload File

Convert to tabular

Before we can go further, Galaxy needs to convert the data you just uploaded into tabular form by replacing commas with a tab. This can be done using the Text Manipulation -> Convert delimiters to TAB option. Make sure that Commas is selected from the drop-down.

Filter

We can apply filtering using the menu option Filter and Sort -> Filter data on any column using simple expressions. Here we use the condition c7 <0.01 and c3 > 1.5 to require that Column 7 (adjusted p-value) is less than 0.05 and Column 3 (log fold-change) is greater than 1.5.

  • filter on genes on a particular chromosome
  • within a certain range of start and end positions
  • filter by gene name

Selecting columns

If you find the number of columns in the file a bit unwieldy, you can also use the Text Manipulation -> Cut columns from a table to remove some columns, or re-order the existing ones:-

Sorting by a column

We can also sort the table by values in a particular column. e.g. the log\(_2\) fold change which is found in column number 3.

  • can also sort by multiple columns
    • e.g. Chromosome, and then start

Selecting the top “N” genes

We might want to consider the top 100, 200, genes in our list ranked according to p-value. This we can do with Text Manipulation -> Select first lines from a dataset

Creating a Galaxy workflow

The appeal of Galaxy is that these operations can be performed in succession, with each new operation using the output from the previous step. As you get more-advanced, your workflow can be saved, shared and re-used on other datasets. See Anne for more details or attend our Galaxy course

e.g. Import -> Convert -> Filter by fold-change -> Top 100

Shared Data -> Workflows

R workflow

For those keen on R, equivalent operations can be performed with the dplyr package. See our intermediate R course for details.

library(dplyr)
deTable <- read.csv("t47d_Treatment_DEA_Prog-vs-Control_all.csv")
filteredTable <- filter(deTable, padj < 0.05, log2FoldChange > 1.5)
sortedTable <- arrange(filteredTable, log2FoldChange)
reducedTable <- select(filteredTable, X,baseMean,log2FoldChange)

Gene-Ontologies and Pathways

In the early days of microarray analysis, people were happy if they got a handful of differentially-expressed genes that they could validate or follow-up. However, with later technologies (and depending on the experimental setup) we might have thousands of statistically-significant results, which no-one has the time to follow-up. Also, we might be interested in pathways / mechanisms that are altered and not just individual genes.

In this section we move towards discovering if our results are biologically significant. Are the genes that we have picked statistical flukes, or are there some commonalities?

There are two different approaches one might use, and we will highlight the theory behind both

Over-representation analysis

  • “Threshold-based” methods require defintion of a statistical threshold to define list of genes to test (e.g. FDR < 0.01)

Let’s take the set of genes H2AFY, SPRY2, CIB1, WNK1, SPRED1, SPRED2. With the exception of one, they all look to have significant p-value. But is this evidence enough that the whole pathway has been disturbed?

The question we are asking here is;

“Are the number of differentially expressed (DE) genes associated with Theme X significantly greater than what we might expect by chance alone?”

We can answer this question by knowing

  • the total number of DE genes
  • the number of genes in your gene set
  • the number of genes in your gene set that are found to be DE
  • the total number of tested genes

The formula for Fishers exact test is;

\[ p = \frac{\binom{a + b}{a}\binom{c +d}{c}}{\binom{n}{a +c}} = \frac{(a+b)!(c+d)!(a+c)!(b+d)!}{a!b!c!d!n!} \]

with :-

In DE List Not In DE List Total
In Gene Set a b a + b
Not in Gene Set c d c + d
Total a + c b +d a + b + c + d (=n)

In this first test, our genes will be grouped together according to their Gene Ontology (GO) terms:- http://www.geneontology.org/

Software for conducting a over-representation test (goseq)

We will be using goseq, which is a software package available through Bioconductor. However, rather having to write R code, we will be using the package through our institute’s Galaxy server.

This package has been specifically-developed for use with RNA-seq data. Plenty of methods have been applied to microarray data, but the assumptions might not hold for RNA-seq. For instance, goseq will adjust for the length of a gene as long and highly-expressed transcripts are known to be over-represented in lists of DE genes.

Preparing the data for an over-representation test

We need to start with the list that contains results for all genes; Let’s take t47d_Treatment_DEA_Prog-vs-Control_all.csv, which you can download from here

The goal is to obtain a table with two columns; the first containing the gene identifier, and the second being TRUE or FALSE indicating whether the gene is differentially-expressed at a given cut-off (e.g. 0.05). We don’t have to be too rigourous when deciding the p-value cut-off, as we’re using it as a means to filter the data and not the end-point of our analysis.

If you wish to see the R code (using dplyr) for manipulating our data to provide an input file for the gene set analysis, click the ‘Code’ / ‘Hide’ button on the right.

library(dplyr)
deTable <- read.csv("t47d_Treatment_DEA_Prog-vs-Control_all.csv")
mutate(deTable, DE = padj < 0.05) %>% 
  mutate(DE = ifelse(is.na(DE),FALSE,DE)) %>% 
  dplyr:::select(X, DE) -> filteredTable
  write.table(filteredTable,"de-table-for-goseq.txt",quote=FALSE,row.names=FALSE)
filteredTable

Manipulating the file can also be done in Galaxy.

Galaxy Workflow

Import the csv file

Get Data -> Upload Data

Convert to tabular form

Text Manipulation -> Convert delimiters to TAB

Select Commas from drop-down menu

Remove header line

Text Manipulation -> Select last lines from a dataset

Make note of how many lines in file, N and remove N-1 last lines with this tool

Retain columns of interest

Put c1,c2,c3,c4,c5,c6,c7,c12 to retain columns 1,2,3,4,5,6,7 and 12

Text Manipulation -> Cut columns from a table

The cleaned dataset

The output from the previous step will be referred to as our cleaned dataset and we will use it later on for another type of downstream analysis.

We now need to determine if each gene is DE at 0.05 significance level

Adding an extra column

Text Manipulation -> Compute an expression on every row

Use the expression c7<0.05 to test if the adjusted p-value is less than 0.05

Which should give something like this

Extracting the columns needed for goseq

Text Manipulation -> Cut columns from a table Choose c1,c9 as the columns to cut; the ensembl ID and the column created in the previous step

Which should give the following

Running goseq

NGS:RNA-seq -> goseq

Select Genome version hg19 in this case. You could also specify which type of identifiers can be found in the first column. Ensembl ID is the default and correct for our dataset.

After a while, you should notification that your analyis has completed and you can download the results by clicking the floppy disk icon.

Things to try:

  • Filter the output from the goseq analysis to gene sets with p-value less than 0.05

The differentially-expressed genes that we identified could either by up- or down-regulated. Sometimes we might want to look for over-represented genes in the up- or down-regulated genes only

  • Let’s suppose we want to analyse the up-regulated genes only
  • Consider what changes you would need to make to the workflow and perform the analysis

Threshold-free analysis

For these tests, we don’t have to specify a statistical threshold and use the test statistics from all genes as the input to the test. The popular Gene Set Enrichment Analysis (GSEA) method uses this approach. These tests can be used to detect differential expression for a group of genes, even when the effects are too small or there is too little data to detect the genes individually.

Let’s say that we have 10 genes “of interest”. We can look-up their results from the table. For a threshold-free analysis we deal with test statistics or fold-change values that have directionality, as we typically want to identify gene sets that change expression in the same direction (i.e. all up- or down-regulated).

Some of the statistics look high, but how do they compare to the rest of the genes? Are they towards the top of the list, or scattered randomly? This is what GSEA tries to determine. We are not making any claims about any particular gene in the list being DE, only that the set as a whole is altered.

We typically visualise the results of the analysis as a barcode plot. Firstly, all the test statistics are ranked from highest to lowest. We then draw a vertical line at every point where a gene in our list of interest is observed. We then determine where the peak of the distribution is, and consequently whether the genes are towards to top or bottom of the ranked list.

Here is the plot for our set:-

Indeed, it looks as though the statistics are concentrated at the top of our gene list.

The case where we have a down-regulated pathway might look something like:-

Or in the case of no enrichment, there is no particular pattern to where the genes occur in the ranked list

The Broad institute provides a version of GSEA that can be run via a java application. The input to GSEA is matrix of expression values and a file describing which covariate each sample belongs to. However, whether or not the method can be applied directly to RNA-seq data is under debate. According to the GSEA faq

The GSEA team has yet to determine whether any of these ranking statistics, originally selected for their effectiveness when used with expression data derived from DNA Microarray experiments, are appropriate for use with expression data derived from RNA-seq experiments. We hopefully will be able to devote some time to investigating this, but in the mean time, we are recommending use of the GSEAPreranked tool for conducting gene set enrichment analysis of data derived from RNA-seq experiments.

The GSEAPreranked tool mentioned is available through the Broad insitute’s GenePattern analysis suite. However, we don’t want to introduce yet another analysis suite, so we will focus on how to perform this analysis in Galaxy.

GSEA uses a set of pre-defined gene sets in their analysis which come under the following categories:-

  • H hallmark gene sets
  • C1 positional gene sets
  • C2 curated gene sets
  • C3 motif gene sets
  • C4 computational gene sets
  • C5 GO gene sets
  • C6 oncogenic signatures
  • C7 immunologic signatures

You can find out more about these gene sets on the msigdb website. However, it is important to note that these gene sets have Human gene symbols only.

e.g. C6 oncogenic signatures, which were used in the original GSEA analysis of this dataset

Gene sets represent signatures of cellular pathways which are often dis-regulated in cancer. The majority of signatures were generated directly from microarray data from NCBI GEO or from internal unpublished profiling experiments which involved perturbation of known cancer genes. In addition, a small number of oncogenic signatures were curated from scientific publications.

Preparing the gene set for a GSEA analysis

In order to perform the GSEAPreRanked analysis, one needs to create file with two columns; the first containing the gene symbol, and the second is the (ranked) statistic for the gene. For those interested, here is the R code to produce a file suitable for GSEA analysis:-

library(dplyr)
deTable <- read.csv("t47d_Treatment_DEA_Prog-vs-Control_all.csv")
deTable %>% arrange(desc(stat)) %>% 
  dplyr:::select(symbol, stat) %>% 
  filter(!is.na(symbol)) -> orderedTable
orderedTable

Now lets walkthrough how to do that in Galaxy:-

Ranking the genes

Make sure your cleaned dataset is selected (converted to tabular, removed header and cut columns), sort on column 5 (the test statistic)

Filter and Sort -> Sort data in ascending or descending order

Giving the output:-

We now have all the information we need, but the GSEA tool expects only two columns; gene symbol and ranked statistic

Cutting the columns

Extract columns 8 (gene symbol) followed by test statistic; c8,c5

Text Manipulation -> Cut columns from a table

Running a GSEA analysis

Using the fGSEA tool

fGSEA is a Bioconductor package that implements the pre-ranked GSEA analysis. It also happens to be a faster implementation, as described in their pre-print

You can find the tool under NGS: RNA-seq Analysis

With this tool, three different outputs are produced

  • a results table
  • a summary graphic of the top pathways
  • enrichment plots for the top pathways

Things to try:

  • Can you identify pathways that are significant at 0.05 level?
  • What pathways are over- and under-represented?

MetaCore

“Your GPS in Systems Biology”

The institute has a license for Metacore by Thomson Reuters. You must first obtain a login (email Ashley Sawle in the Bioinformatics Core), and then book time to use the site (our license only permits one user to be logged-in at a time). Not only does Metacore provide a smart interface, but they have invested a lot of time manually-curating results from the literature. Consequently, their database and gene networks are proprietary and what the license fee is paying for.

Preparing for Metacore in Galaxy

Text Manipulation -> Cut columns for a table

Select Ensembl IDs, log2FoldChange and adjusted p-value (columns 1, 3 and 7).

Or, in R:-

read.csv("t47d_Treatment_DEA_Prog-vs-Control_all.csv") %>% #head
  dplyr:::select(X,log2FoldChange, padj) %>% 
    write.table("t47d_Treatment_DEA_Prog-vs-Control_all_forMetacore.txt",sep="\t",quote=FALSE,row.names=FALSE)

You are then ready to load the data into Metacore:-

Upload -> Upload Experiments with Gene or Protein IDs

Specify types of data in each column

LS0tCnRpdGxlOiAiQmV5b25kIHRoZSBHZW5lIExpc3QiCmF1dGhvcjogIk1hcmsgRHVubmluZzsgbWFyayAnZG90JyBkdW5uaW5nICdhdCcgY3J1ay5jYW0uYWMudWsiCmRhdGU6ICdgciBmb3JtYXQoU3lzLnRpbWUoKSwgIkxhc3QgbW9kaWZpZWQ6ICVkICViICVZIilgJwpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0UsZWNobz1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBGQUxTRSkKYGBgCgojIEhvdyB0byBtYW5pcHVsYXRlIGEgZ2VuZSBsaXN0CgpUaGUgZ29sZGVuIHJ1bGUgYmVmb3JlIHdlIHN0YXJ0ICoqKkFsd2F5cyBrZWVwIGEgYmFja3VwIG9mIHRoZSBvdXRwdXQgZnJvbSB0aGUgcGlwZWxpbmUsIG5ldmVyIHdvcmsgb24gdGhlIG9yaWdpbmFsIGRhdGEqKiohCgpUaGVyZSBhcmUgdmFyaW91cyB0YXNrcyB5b3UgbWlnaHQgd2lzaCB0byBwZXJmb3JtIG9uIGEgZ2VuZSBsaXN0CgotIFNlYXJjaCBmb3Igb3VyIGZhdm91cml0ZSBnZW5lCi0gU29ydCAvIFJhbmsgYWNjb3JkaW5nIHRvIHN0YXRpc3RpYyBvciBwLXZhbHVlCi0gRmlsdGVyIHRvIG9idGFpbiBnZW5lcyB3aXRoIHBhcnRpY3VsYXIgY3V0LW9mZiBhbmQgZm9sZC1jaGFuZ2UKLSBSZS1vcmRlciAvIHJlLWFycmFuZ2UgY29sdW1ucwoKT3VyIHJlY29tbWVuZGVkIHRvb2xzIHRvIHBlcmZvcm0gc3VjaCBvcGVyYXRpb25zIHdvdWxkIGJlIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugc3VjaCBhcyBSIC8gUHl0aG9uIHNvIHRoYXQgdGhlIG9wZXJhdGlvbnMgY2FuIGJlIHNjcmlwdGVkIGFuZCBhdXRvbWF0ZWQuIEFzIGEgY29tcHJvbWlzZSwgb3VyIEdhbGF4eSBzZXJ2ZXIgcHJvdmlkZXMgdmFyaW91cyBvcGVyYXRpb25zIHRocm91Z2ggYW4gaW50dWl0aXZlIGludGVyZmFjZSBhbmQgYWxsb3dzIHRoZSB1c2VyIHRvIGJ1aWxkIGEgd29ya2Zsb3cgdG8gYSBjaGFpbiBvZiBzaW1wbGUgb3BlcmF0aW9ucy4KClRoZXJlIGlzIGEgc3BlY2lhbCByZWFzb24gd2h5IHlvdSBzaG91bGRuJ3QgdHJ1c3QgRXhjZWwgYXMgeW91ciBtYW55IG1lYW5zIG9mIGludGVycm9nYXRpbmcgdGhlIHJlc3VsdHMuIFNvbWV0aW1lcyBpdCBjYW4gYmUgdW5oZWxwZnVsIGFuZCBjb252ZXJ0IGdlbmUgaWRlbnRpZmVycyBpbnRvIGRhdGVzLiBbTm8sIHJlYWxseSFdKGh0dHBzOi8vZ2Vub21lYmlvbG9neS5iaW9tZWRjZW50cmFsLmNvbS9hcnRpY2xlcy8xMC4xMTg2L3MxMzA1OS0wMTYtMTA0NC03KQoKUGxlYXNlIGFsc28gYmVhciBpbiBtaW5kIHRoYXQgb3Zlci1wcm9jZXNzaW5nIG9mIGEgcmVzdWx0cyBmaWxlIGluIEV4Y2VsIG1heSBkaW1pbmlzaCBob3cgdXNlZnVsIGl0IGlzIHRvIEJpb2luZm9ybWF0aWMgYW5hbHlzaXMgaW4gdGhlIGZ1dHVyZS4gSGVyZSBhcmUgc29tZSBtYXRlcmlhbHMgeW91IG1pZ2h0IGxpa2UgdG8gY2hlY2sgb3V0CgotIFtBdm9pZGluZyBEYXRhIERpc2FzdGVyc10oaHR0cDovL2Jpb2luZm9ybWF0aWNzLWNvcmUtc2hhcmVkLXRyYWluaW5nLmdpdGh1Yi5pby8vYXZvaWQtZGF0YS1kaXNhc3Rlci8pCi0gW0RhdGEgQ2FycGVudHJ5IGxlc3NvbnMgb24gU3ByZWFkc2hlZXRzXShodHRwOi8vd3d3LmRhdGFjYXJwZW50cnkub3JnL3NwcmVhZHNoZWV0LWVjb2xvZ3ktbGVzc29uLzAxLWZvcm1hdC1kYXRhLykKLSBbRGF0YSBPcmdhbmlzYXRpb24gdHV0b3JpYWwgYnkgS2FybCBCcm9tYW5dKGh0dHA6Ly9rYnJvbWFuLm9yZy9kYXRhb3JnLykKCldlIHdpbGwgb25seSBzY3JhdGNoIHRoZSBzdXJmYWNlIG9mIHdoYXQgaXMgcG9zc2libGUgd2l0aCBHYWxheHkuIElmIHlvdSBhcmUgbmV3IHRvIHRoZSBzb2Z0d2FyZSwgeW91IGNhbiBjaGVjayBvdXQgb3VyIGNvdXJzZTotIFtodHRwOi8vZ2FsYXh5Y2FtLmdpdGh1Yi5pby9dKGh0dHA6Ly9nYWxheHljYW0uZ2l0aHViLmlvLykKCkRpZmZlcmVudCBvbmxpbmUgdG9vbHMgb3IgR1VJcyB3aWxsIHRha2UgZGlmZmVyZW50IHR5cGVzIG9mIGlucHV0LCBidXQgd2lsbCBwcm9iYWJseSBpbnZvbHZlIHNvbWUgY29tYmluYXRpb24gb2YgdGhlIG9wZXJhdGlvbnMgbWVudGlvbmVkIGFib3ZlLiBUaGVyZWZvcmUsIHdlIHdpbGwgaW50cm9kdWNlIHNvbWUgdG9vbHMgaW4gR2FsYXh5IHRoYXQgc2hvdWxkIGFsbG93IHlvdSB0byBtYW5pcHVsYXRlIHlvdXIgZGF0YSBpbnRvIHRoZSByZXF1aXJlZCBmb3JtLiBMYXRlciwgd2Ugd2lsbCBnaXZlIGV4YW1wbGVzIG9mIHdvcmtmbG93cyBmb3IgcGFydGljdWxhciBnZW5lIHNldCBlbnJpY2htZW50IC8gcGF0aHdheXMgYW5hbHlzaXMgdG9vbHMuCgpJbiB0aGUgZmlyc3QgZ2VuZXJpYyBleGFtcGxlLCB3ZSB3aWxsIHNob3cgc29tZSBjb21tb24gbWFuaXB1bGF0aW9ucyBvbiBhIGdlbmUgbGlzdCB1c2luZyBHYWxheHk6LQoKIyMgQ29tbW9uIHRhc2tzIGluIEdhbGF4eQoKIyMjIFVwbG9hZCB0aGUgZ2VuZSBsaXN0IGluIGNzdiBmb3JtCgpUaGUgZ2VuZSBsaXN0IGAuY3N2YCBmaWxlIGNhbiBiZSB1cGxvYWRlZCBpbnRvIEdhbGF4eS4gSW4gdGhpcyBleGFtcGxlIHdlIHdhbnQgdG8gY2hvb3NlIHRoZSBmaWxlIHdpdGggbm8gcC12YWx1ZSBjdXQtb2ZmcyBhcHBsaWVkCgoqKipHZXQgRGF0YSoqKiAtPiAqKipVcGxvYWQgRmlsZSoqKgoKIVtdKGltYWdlcy9maWx0ZXIxLnBuZykKCiMjIyBDb252ZXJ0IHRvIHRhYnVsYXIKCkJlZm9yZSB3ZSBjYW4gZ28gZnVydGhlciwgR2FsYXh5IG5lZWRzIHRvIGNvbnZlcnQgdGhlIGRhdGEgeW91IGp1c3QgdXBsb2FkZWQgaW50byAqdGFidWxhciogZm9ybSBieSByZXBsYWNpbmcgY29tbWFzIHdpdGggYSB0YWIuIFRoaXMgY2FuIGJlIGRvbmUgdXNpbmcgdGhlICoqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKkNvbnZlcnQgZGVsaW1pdGVycyB0byBUQUIqKiogb3B0aW9uLiBNYWtlIHN1cmUgdGhhdCAqQ29tbWFzKiBpcyBzZWxlY3RlZCBmcm9tIHRoZSBkcm9wLWRvd24uCgohW10oaW1hZ2VzL2ZpbHRlcjIucG5nKQoKIyMjIEZpbHRlcgoKV2UgY2FuIGFwcGx5IGZpbHRlcmluZyB1c2luZyB0aGUgbWVudSBvcHRpb24gKioqRmlsdGVyIGFuZCBTb3J0KioqIC0+ICoqKkZpbHRlciBkYXRhIG9uIGFueSBjb2x1bW4gdXNpbmcgc2ltcGxlIGV4cHJlc3Npb25zKioqLiBIZXJlIHdlIHVzZSB0aGUgY29uZGl0aW9uIGBjNyA8MC4wMSBhbmQgYzMgPiAxLjVgIHRvIHJlcXVpcmUgdGhhdCBDb2x1bW4gNyAoYWRqdXN0ZWQgcC12YWx1ZSkgaXMgbGVzcyB0aGFuIDAuMDUgKmFuZCogQ29sdW1uIDMgKGxvZyBmb2xkLWNoYW5nZSkgaXMgZ3JlYXRlciB0aGFuIDEuNS4KCgohW10oaW1hZ2VzL2ZpbHRlcjMucG5nKQoKLSBmaWx0ZXIgb24gZ2VuZXMgb24gYSBwYXJ0aWN1bGFyIGNocm9tb3NvbWUgCi0gd2l0aGluIGEgY2VydGFpbiByYW5nZSBvZiBzdGFydCBhbmQgZW5kIHBvc2l0aW9ucwotIGZpbHRlciBieSBnZW5lIG5hbWUKCiMjIFNlbGVjdGluZyBjb2x1bW5zCgpJZiB5b3UgZmluZCB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIGZpbGUgYSBiaXQgdW53aWVsZHksIHlvdSBjYW4gYWxzbyB1c2UgdGhlICoqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKkN1dCBjb2x1bW5zIGZyb20gYSB0YWJsZSoqKiB0byByZW1vdmUgc29tZSBjb2x1bW5zLCBvciByZS1vcmRlciB0aGUgZXhpc3Rpbmcgb25lczotCgohW10oaW1hZ2VzL2ZpbHRlcjQucG5nKQoKIyMgU29ydGluZyBieSBhIGNvbHVtbgoKV2UgY2FuIGFsc28gc29ydCB0aGUgdGFibGUgYnkgdmFsdWVzIGluIGEgcGFydGljdWxhciBjb2x1bW4uIGUuZy4gdGhlIGxvZyRfMiQgZm9sZCBjaGFuZ2Ugd2hpY2ggaXMgZm91bmQgaW4gY29sdW1uIG51bWJlciAzLgohW10oaW1hZ2VzL2ZpbHRlcjUucG5nKQoKLSBjYW4gYWxzbyBzb3J0IGJ5IG11bHRpcGxlIGNvbHVtbnMKICAgICsgZS5nLiBDaHJvbW9zb21lLCBhbmQgdGhlbiBzdGFydAoKIyMgU2VsZWN0aW5nIHRoZSB0b3AgIk4iIGdlbmVzCgpXZSBtaWdodCB3YW50IHRvIGNvbnNpZGVyIHRoZSB0b3AgMTAwLCAyMDAsIGdlbmVzIGluIG91ciBsaXN0IHJhbmtlZCBhY2NvcmRpbmcgdG8gcC12YWx1ZS4gVGhpcyB3ZSBjYW4gZG8gd2l0aCAqKipUZXh0IE1hbmlwdWxhdGlvbioqKiAtPiAqKipTZWxlY3QgZmlyc3QgbGluZXMgZnJvbSBhIGRhdGFzZXQqKioKCiFbXShpbWFnZXMvZ2FsYXh5LXNlbGVjdC1maXJzdC5wbmcpCiAKIyMgQ3JlYXRpbmcgYSBHYWxheHkgd29ya2Zsb3cKClRoZSBhcHBlYWwgb2YgR2FsYXh5IGlzIHRoYXQgdGhlc2Ugb3BlcmF0aW9ucyBjYW4gYmUgcGVyZm9ybWVkIGluIHN1Y2Nlc3Npb24sIHdpdGggZWFjaCBuZXcgb3BlcmF0aW9uIHVzaW5nIHRoZSBvdXRwdXQgZnJvbSB0aGUgcHJldmlvdXMgc3RlcC4gQXMgeW91IGdldCBtb3JlLWFkdmFuY2VkLCB5b3VyIHdvcmtmbG93IGNhbiBiZSBzYXZlZCwgc2hhcmVkIGFuZCByZS11c2VkIG9uIG90aGVyIGRhdGFzZXRzLiBTZWUgQW5uZSBmb3IgbW9yZSBkZXRhaWxzIG9yIGF0dGVuZCBvdXIgW0dhbGF4eSBjb3Vyc2VdKGh0dHA6Ly9nYWxheHljYW0uZ2l0aHViLmlvLykKCmUuZy4gSW1wb3J0IC0+IENvbnZlcnQgLT4gRmlsdGVyIGJ5IGZvbGQtY2hhbmdlIC0+IFRvcCAxMDAKIAoqKipTaGFyZWQgRGF0YSoqKiAtPiAgKioqV29ya2Zsb3dzKioqCgohW10oaW1hZ2VzL2dhbGF4eS13b3JrZmxvdy5wbmcpCgojIyBSIHdvcmtmbG93CgpGb3IgdGhvc2Uga2VlbiBvbiBSLCBlcXVpdmFsZW50IG9wZXJhdGlvbnMgY2FuIGJlIHBlcmZvcm1lZCB3aXRoIHRoZSBgZHBseXJgIHBhY2thZ2UuIFNlZSBvdXIgW2ludGVybWVkaWF0ZSBSXShodHRwOi8vYmlvaW5mb3JtYXRpY3MtY29yZS1zaGFyZWQtdHJhaW5pbmcuZ2l0aHViLmlvL3ItaW50ZXJtZWRpYXRlLykgY291cnNlIGZvciBkZXRhaWxzLiAKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoZHBseXIpCmRlVGFibGUgPC0gcmVhZC5jc3YoInQ0N2RfVHJlYXRtZW50X0RFQV9Qcm9nLXZzLUNvbnRyb2xfYWxsLmNzdiIpCmZpbHRlcmVkVGFibGUgPC0gZmlsdGVyKGRlVGFibGUsIHBhZGogPCAwLjA1LCBsb2cyRm9sZENoYW5nZSA+IDEuNSkKc29ydGVkVGFibGUgPC0gYXJyYW5nZShmaWx0ZXJlZFRhYmxlLCBsb2cyRm9sZENoYW5nZSkKcmVkdWNlZFRhYmxlIDwtIHNlbGVjdChmaWx0ZXJlZFRhYmxlLCBYLGJhc2VNZWFuLGxvZzJGb2xkQ2hhbmdlKQpgYGAKCiMgR2VuZS1PbnRvbG9naWVzIGFuZCBQYXRod2F5cwoKCkluIHRoZSBlYXJseSBkYXlzIG9mIG1pY3JvYXJyYXkgYW5hbHlzaXMsIHBlb3BsZSB3ZXJlIGhhcHB5IGlmIHRoZXkgZ290IGEgaGFuZGZ1bCBvZiBkaWZmZXJlbnRpYWxseS1leHByZXNzZWQgZ2VuZXMgdGhhdCB0aGV5IGNvdWxkIHZhbGlkYXRlIG9yIGZvbGxvdy11cC4gSG93ZXZlciwgd2l0aCBsYXRlciB0ZWNobm9sb2dpZXMgKGFuZCBkZXBlbmRpbmcgb24gdGhlIGV4cGVyaW1lbnRhbCBzZXR1cCkgd2UgbWlnaHQgaGF2ZSB0aG91c2FuZHMgb2Ygc3RhdGlzdGljYWxseS1zaWduaWZpY2FudCByZXN1bHRzLCB3aGljaCBuby1vbmUgaGFzIHRoZSB0aW1lIHRvIGZvbGxvdy11cC4gQWxzbywgd2UgbWlnaHQgYmUgaW50ZXJlc3RlZCBpbiBwYXRod2F5cyAvIG1lY2hhbmlzbXMgdGhhdCBhcmUgYWx0ZXJlZCBhbmQgbm90IGp1c3QgaW5kaXZpZHVhbCBnZW5lcy4KCkluIHRoaXMgc2VjdGlvbiB3ZSBtb3ZlIHRvd2FyZHMgZGlzY292ZXJpbmcgaWYgb3VyIHJlc3VsdHMgYXJlICoqKmJpb2xvZ2ljYWxseSBzaWduaWZpY2FudCoqKi4gQXJlIHRoZSBnZW5lcyB0aGF0IHdlIGhhdmUgcGlja2VkIHN0YXRpc3RpY2FsIGZsdWtlcywgb3IgYXJlIHRoZXJlIHNvbWUgY29tbW9uYWxpdGllcz8KClRoZXJlIGFyZSB0d28gZGlmZmVyZW50IGFwcHJvYWNoZXMgb25lIG1pZ2h0IHVzZSwgYW5kIHdlIHdpbGwgaGlnaGxpZ2h0IHRoZSB0aGVvcnkgYmVoaW5kIGJvdGgKCiMjICBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzCgotICJUaHJlc2hvbGQtYmFzZWQiIG1ldGhvZHMgcmVxdWlyZSBkZWZpbnRpb24gb2YgYSBzdGF0aXN0aWNhbCB0aHJlc2hvbGQgdG8gZGVmaW5lIGxpc3Qgb2YgZ2VuZXMgdG8gdGVzdCAoZS5nLiBGRFIgPCAwLjAxKQoKYGBge3IgbWVzc2FnZT1GQUxTRSxlY2hvPUZBTFNFfQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMobGlicmFyeShvcmcuSHMuZWcuZGIpKQpyZXN1bHQgPC0gc2VsZWN0KG9yZy5Icy5lZy5kYiwga2V5cz0iR086MDAzMDI5MSIsa2V5dHlwZSA9ICJHTyIsY29sdW1ucz0iU1lNQk9MIikKbXlnZW5lcyA8LSByZXN1bHQkU1lNQk9MCmBgYAoKTGV0J3MgdGFrZSB0aGUgc2V0IG9mIGdlbmVzIGByIHBhc3RlKG15Z2VuZXMsIGNvbGxhcHNlPSIsICIpYC4gV2l0aCB0aGUgZXhjZXB0aW9uIG9mIG9uZSwgdGhleSBhbGwgbG9vayB0byBoYXZlIHNpZ25pZmljYW50IHAtdmFsdWUuIEJ1dCBpcyB0aGlzIGV2aWRlbmNlIGVub3VnaCB0aGF0IHRoZSB3aG9sZSBwYXRod2F5IGhhcyBiZWVuIGRpc3R1cmJlZD8KCmBgYHtyIGVjaG89RkFMU0V9CmRwbHlyOjo6ZmlsdGVyKGRlVGFibGUsIHN5bWJvbCAlaW4lIG15Z2VuZXMpCmBgYAoKVGhlIHF1ZXN0aW9uIHdlIGFyZSBhc2tpbmcgaGVyZSBpczsKCj4gKioqIkFyZSB0aGUgbnVtYmVyIG9mIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCAoREUpIGdlbmVzIGFzc29jaWF0ZWQgd2l0aCBUaGVtZSBYIHNpZ25pZmljYW50bHkgZ3JlYXRlciB0aGFuIHdoYXQgd2UgbWlnaHQgZXhwZWN0IGJ5IGNoYW5jZSBhbG9uZT8iKioqCgpXZSBjYW4gYW5zd2VyIHRoaXMgcXVlc3Rpb24gYnkga25vd2luZwoKLSB0aGUgdG90YWwgbnVtYmVyIG9mIERFIGdlbmVzCi0gdGhlIG51bWJlciBvZiBnZW5lcyBpbiB5b3VyIGdlbmUgc2V0Ci0gdGhlIG51bWJlciBvZiBnZW5lcyBpbiB5b3VyIGdlbmUgc2V0IHRoYXQgYXJlIGZvdW5kIHRvIGJlIERFCi0gdGhlIHRvdGFsIG51bWJlciBvZiB0ZXN0ZWQgZ2VuZXMKClRoZSBmb3JtdWxhIGZvciBGaXNoZXJzIGV4YWN0IHRlc3QgaXM7CgokJCBwID0gXGZyYWN7XGJpbm9te2EgKyBifXthfVxiaW5vbXtjICtkfXtjfX17XGJpbm9te259e2EgK2N9fSA9IFxmcmFjeyhhK2IpIShjK2QpIShhK2MpIShiK2QpIX17YSFiIWMhZCFuIX0gJCQKCndpdGggOi0KCnwgIHwgSW4gREUgTGlzdCB8IE5vdCBJbiBERSBMaXN0ICB8IFRvdGFsCi0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgIC0tLS0tLS0tLS0tLS0gfCAtLS0tLS0tLS0tLS0tIHwgCkluIEdlbmUgU2V0IHwgYSB8IGIgfCBhICArICBiIHwKTm90IGluIEdlbmUgU2V0ICB8IGMgfCBkIHwgYyArIGQgfApUb3RhbCB8IGEgKyBjIHwgYiArZCB8IGEgKyBiICsgYyArIGQgKD1uKSB8CgpJbiB0aGlzIGZpcnN0IHRlc3QsIG91ciBnZW5lcyB3aWxsIGJlIGdyb3VwZWQgdG9nZXRoZXIgYWNjb3JkaW5nIHRvIHRoZWlyIEdlbmUgT250b2xvZ3kgKCpHTyopIHRlcm1zOi0gW2h0dHA6Ly93d3cuZ2VuZW9udG9sb2d5Lm9yZy9dKGh0dHA6Ly93d3cuZ2VuZW9udG9sb2d5Lm9yZy8pCgojIyBTb2Z0d2FyZSBmb3IgY29uZHVjdGluZyBhIG92ZXItcmVwcmVzZW50YXRpb24gdGVzdCAoZ29zZXEpCgpXZSB3aWxsIGJlIHVzaW5nIFtgZ29zZXFgXShodHRwczovL3d3dy5iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2UvYmlvYy9odG1sL2dvc2VxLmh0bWwpLCB3aGljaCBpcyBhIHNvZnR3YXJlIHBhY2thZ2UgYXZhaWxhYmxlIHRocm91Z2ggW0Jpb2NvbmR1Y3Rvcl0od3d3LmJpb2NvbmR1Y3Rvci5vcmcvKS4gSG93ZXZlciwgcmF0aGVyIGhhdmluZyB0byB3cml0ZSBSIGNvZGUsIHdlIHdpbGwgYmUgdXNpbmcgdGhlIHBhY2thZ2UgdGhyb3VnaCBvdXIgaW5zdGl0dXRlJ3MgR2FsYXh5IHNlcnZlci4KClRoaXMgcGFja2FnZSBoYXMgYmVlbiAqc3BlY2lmaWNhbGx5LWRldmVsb3BlZCogZm9yIHVzZSB3aXRoIFJOQS1zZXEgZGF0YS4gUGxlbnR5IG9mIG1ldGhvZHMgaGF2ZSBiZWVuIGFwcGxpZWQgdG8gbWljcm9hcnJheSBkYXRhLCBidXQgdGhlIGFzc3VtcHRpb25zIG1pZ2h0IG5vdCBob2xkIGZvciBSTkEtc2VxLiBGb3IgaW5zdGFuY2UsIGBnb3NlcWAgd2lsbCBbYWRqdXN0IGZvciB0aGUgbGVuZ3RoIG9mIGEgZ2VuZV0oaHR0cDovL2dlbm9tZWJpb2xvZ3kuYmlvbWVkY2VudHJhbC5jb20vYXJ0aWNsZXMvMTAuMTE4Ni9nYi0yMDEwLTExLTItcjE0KSBhcyBsb25nIGFuZCBoaWdobHktZXhwcmVzc2VkIHRyYW5zY3JpcHRzIGFyZSBrbm93biB0byBiZSBvdmVyLXJlcHJlc2VudGVkIGluIGxpc3RzIG9mIERFIGdlbmVzLgoKIyMgUHJlcGFyaW5nIHRoZSBkYXRhIGZvciBhbiBvdmVyLXJlcHJlc2VudGF0aW9uIHRlc3QKCldlIG5lZWQgdG8gc3RhcnQgd2l0aCB0aGUgbGlzdCB0aGF0IGNvbnRhaW5zIHJlc3VsdHMgZm9yICphbGwqIGdlbmVzOyBMZXQncyB0YWtlIGB0NDdkX1RyZWF0bWVudF9ERUFfUHJvZy12cy1Db250cm9sX2FsbC5jc3ZgLCB3aGljaCB5b3UgY2FuIFtkb3dubG9hZCBmcm9tIGhlcmVdKGh0dHBzOi8vYmlvaW5mb3JtYXRpY3MtY29yZS1zaGFyZWQtdHJhaW5pbmcuZ2l0aHViLmlvL3JuYXNlcS1waXBlbGluZS90NDdkX1RyZWF0bWVudF9ERUFfUHJvZy12cy1Db250cm9sX2FsbC5jc3YpCgoKVGhlIGdvYWwgaXMgdG8gb2J0YWluIGEgdGFibGUgd2l0aCB0d28gY29sdW1uczsgdGhlIGZpcnN0IGNvbnRhaW5pbmcgdGhlIGdlbmUgaWRlbnRpZmllciwgYW5kIHRoZSBzZWNvbmQgYmVpbmcgYFRSVUVgIG9yIGBGQUxTRWAgaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBnZW5lIGlzIGRpZmZlcmVudGlhbGx5LWV4cHJlc3NlZCBhdCBhIGdpdmVuIGN1dC1vZmYgKGUuZy4gYDAuMDVgKS4gV2UgZG9uJ3QgaGF2ZSB0byBiZSB0b28gcmlnb3Vyb3VzIHdoZW4gZGVjaWRpbmcgdGhlIHAtdmFsdWUgY3V0LW9mZiwgYXMgd2UncmUgdXNpbmcgaXQgYXMgYSBtZWFucyB0byBmaWx0ZXIgdGhlIGRhdGEgYW5kIG5vdCB0aGUgZW5kLXBvaW50IG9mIG91ciBhbmFseXNpcy4KCklmIHlvdSB3aXNoIHRvIHNlZSB0aGUgUiBjb2RlICh1c2luZyBgZHBseXJgKSBmb3IgbWFuaXB1bGF0aW5nIG91ciBkYXRhIHRvIHByb3ZpZGUgYW4gaW5wdXQgZmlsZSBmb3IgdGhlIGdlbmUgc2V0IGFuYWx5c2lzLCBjbGljayB0aGUgJ0NvZGUnIC8gJ0hpZGUnIGJ1dHRvbiBvbiB0aGUgcmlnaHQuCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KGRwbHlyKQpkZVRhYmxlIDwtIHJlYWQuY3N2KCJ0NDdkX1RyZWF0bWVudF9ERUFfUHJvZy12cy1Db250cm9sX2FsbC5jc3YiKQptdXRhdGUoZGVUYWJsZSwgREUgPSBwYWRqIDwgMC4wNSkgJT4lIAogIG11dGF0ZShERSA9IGlmZWxzZShpcy5uYShERSksRkFMU0UsREUpKSAlPiUgCiAgZHBseXI6OjpzZWxlY3QoWCwgREUpIC0+IGZpbHRlcmVkVGFibGUKICB3cml0ZS50YWJsZShmaWx0ZXJlZFRhYmxlLCJkZS10YWJsZS1mb3ItZ29zZXEudHh0IixxdW90ZT1GQUxTRSxyb3cubmFtZXM9RkFMU0UpCmZpbHRlcmVkVGFibGUKYGBgCgpNYW5pcHVsYXRpbmcgdGhlIGZpbGUgY2FuIGFsc28gYmUgZG9uZSBpbiBHYWxheHkuCgojIyBHYWxheHkgV29ya2Zsb3cKCiMjIyBJbXBvcnQgdGhlIGNzdiBmaWxlCgoqKipHZXQgRGF0YSoqKiAtPiAqKipVcGxvYWQgRGF0YSoqKgoKIVtdKGltYWdlcy9nYWxheHktMS5wbmcpCgojIyMgQ29udmVydCB0byB0YWJ1bGFyIGZvcm0KCioqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKkNvbnZlcnQgZGVsaW1pdGVycyB0byBUQUIqKioKClNlbGVjdCAqQ29tbWFzKiBmcm9tIGRyb3AtZG93biBtZW51CgohW10oaW1hZ2VzL2dhbGF4eS0yLnBuZykKCiMjIyBSZW1vdmUgaGVhZGVyIGxpbmUKCioqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKlNlbGVjdCBsYXN0IGxpbmVzIGZyb20gYSBkYXRhc2V0KioqCgpNYWtlIG5vdGUgb2YgaG93IG1hbnkgbGluZXMgaW4gZmlsZSwgKk4qIGFuZCByZW1vdmUgKk4tMSogbGFzdCBsaW5lcyB3aXRoIHRoaXMgdG9vbAohW10oaW1hZ2VzL2dhbGF4eS0zLnBuZykKCiMjIyBSZXRhaW4gY29sdW1ucyBvZiBpbnRlcmVzdAoKUHV0ICpjMSxjMixjMyxjNCxjNSxjNixjNyxjMTIqIHRvIHJldGFpbiBjb2x1bW5zIDEsMiwzLDQsNSw2LDcgYW5kIDEyCgoqKipUZXh0IE1hbmlwdWxhdGlvbioqKiAtPiAqKipDdXQgY29sdW1ucyBmcm9tIGEgdGFibGUqKioKCiFbXShpbWFnZXMvZ2FsYXh5LTQucG5nKQoKIyMjIFRoZSBjbGVhbmVkIGRhdGFzZXQKClRoZSBvdXRwdXQgZnJvbSB0aGUgcHJldmlvdXMgc3RlcCB3aWxsIGJlIHJlZmVycmVkIHRvIGFzIG91ciAqY2xlYW5lZCBkYXRhc2V0KiBhbmQgd2Ugd2lsbCB1c2UgaXQgbGF0ZXIgb24gZm9yIGFub3RoZXIgdHlwZSBvZiBkb3duc3RyZWFtIGFuYWx5c2lzLgoKIVtdKGltYWdlcy9nYWxheHktNS5wbmcpCgoKV2Ugbm93IG5lZWQgdG8gZGV0ZXJtaW5lIGlmIGVhY2ggZ2VuZSBpcyBERSBhdCAwLjA1IHNpZ25pZmljYW5jZSBsZXZlbAoKIyMjIEFkZGluZyBhbiBleHRyYSBjb2x1bW4KCioqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKkNvbXB1dGUgYW4gZXhwcmVzc2lvbiBvbiBldmVyeSByb3cqKioKClVzZSB0aGUgZXhwcmVzc2lvbiBgYzc8MC4wNWAgdG8gdGVzdCBpZiB0aGUgYWRqdXN0ZWQgcC12YWx1ZSBpcyBsZXNzIHRoYW4gMC4wNQoKIVtdKGltYWdlcy9nYWxheHktNi5wbmcpCgpXaGljaCBzaG91bGQgZ2l2ZSBzb21ldGhpbmcgbGlrZSB0aGlzCgohW10oaW1hZ2VzL2dhbGF4eS03LnBuZykKCiMjIyBFeHRyYWN0aW5nIHRoZSBjb2x1bW5zIG5lZWRlZCBmb3IgZ29zZXEKCioqKlRleHQgTWFuaXB1bGF0aW9uKioqIC0+ICoqKkN1dCBjb2x1bW5zIGZyb20gYSB0YWJsZSoqKgpDaG9vc2UgYGMxLGM5YCBhcyB0aGUgY29sdW1ucyB0byBjdXQ7IHRoZSBlbnNlbWJsIElEIGFuZCB0aGUgY29sdW1uIGNyZWF0ZWQgaW4gdGhlIHByZXZpb3VzIHN0ZXAKCiFbXShpbWFnZXMvZ2FsYXh5LTgucG5nKQoKV2hpY2ggc2hvdWxkIGdpdmUgdGhlIGZvbGxvd2luZwoKIVtdKGltYWdlcy9nYWxheHktOS5wbmcpCgojIyMgUnVubmluZyBnb3NlcQoKKioqTkdTOlJOQS1zZXEqKiogLT4gKioqZ29zZXEqKioKClNlbGVjdCBHZW5vbWUgdmVyc2lvbiAqaGcxOSogaW4gdGhpcyBjYXNlLiBZb3UgY291bGQgYWxzbyBzcGVjaWZ5IHdoaWNoIHR5cGUgb2YgaWRlbnRpZmllcnMgY2FuIGJlIGZvdW5kIGluIHRoZSBmaXJzdCBjb2x1bW4uICpFbnNlbWJsKiBJRCBpcyB0aGUgZGVmYXVsdCBhbmQgY29ycmVjdCBmb3Igb3VyIGRhdGFzZXQuCgohW10oaW1hZ2VzL2dhbGF4eS1nb3NlcS5wbmcpCgpBZnRlciBhIHdoaWxlLCB5b3Ugc2hvdWxkIG5vdGlmaWNhdGlvbiB0aGF0IHlvdXIgYW5hbHlpcyBoYXMgY29tcGxldGVkIGFuZCB5b3UgY2FuIGRvd25sb2FkIHRoZSByZXN1bHRzIGJ5IGNsaWNraW5nIHRoZSBmbG9wcHkgZGlzayBpY29uLgoKIVtdKGltYWdlcy9nYWxheHktZ29zZXEtc2F2ZS5wbmcpCgoKIyMjIFRoaW5ncyB0byB0cnk6CgotIEZpbHRlciB0aGUgb3V0cHV0IGZyb20gdGhlIGdvc2VxIGFuYWx5c2lzIHRvIGdlbmUgc2V0cyB3aXRoIHAtdmFsdWUgbGVzcyB0aGFuIDAuMDUKClRoZSBkaWZmZXJlbnRpYWxseS1leHByZXNzZWQgZ2VuZXMgdGhhdCB3ZSBpZGVudGlmaWVkIGNvdWxkIGVpdGhlciBieSB1cC0gb3IgZG93bi1yZWd1bGF0ZWQuIFNvbWV0aW1lcyB3ZSBtaWdodCB3YW50IHRvIGxvb2sgZm9yIG92ZXItcmVwcmVzZW50ZWQgZ2VuZXMgaW4gdGhlIHVwLSBvciBkb3duLXJlZ3VsYXRlZCBnZW5lcyBvbmx5CgotIExldCdzIHN1cHBvc2Ugd2Ugd2FudCB0byBhbmFseXNlIHRoZSB1cC1yZWd1bGF0ZWQgZ2VuZXMgb25seQotIENvbnNpZGVyIHdoYXQgY2hhbmdlcyB5b3Ugd291bGQgbmVlZCB0byBtYWtlIHRvIHRoZSB3b3JrZmxvdyBhbmQgcGVyZm9ybSB0aGUgYW5hbHlzaXMKCiMjIFRocmVzaG9sZC1mcmVlIGFuYWx5c2lzCgpGb3IgdGhlc2UgdGVzdHMsIHdlIGRvbid0IGhhdmUgdG8gc3BlY2lmeSBhIHN0YXRpc3RpY2FsIHRocmVzaG9sZCBhbmQgdXNlIHRoZSB0ZXN0IHN0YXRpc3RpY3MgZnJvbSAqYWxsKiBnZW5lcyBhcyB0aGUgaW5wdXQgdG8gdGhlIHRlc3QuIFRoZSBwb3B1bGFyICpHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSogbWV0aG9kIHVzZXMgdGhpcyBhcHByb2FjaC4gVGhlc2UgdGVzdHMgY2FuIGJlIHVzZWQgdG8gZGV0ZWN0IGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGZvciBhIGdyb3VwIG9mIGdlbmVzLCBldmVuIHdoZW4gdGhlIGVmZmVjdHMgYXJlIHRvbyBzbWFsbCBvciB0aGVyZSBpcyB0b28gbGl0dGxlIGRhdGEgdG8gZGV0ZWN0IHRoZSBnZW5lcyBpbmRpdmlkdWFsbHkuCgpMZXQncyBzYXkgdGhhdCB3ZSBoYXZlIDEwIGdlbmVzICJvZiBpbnRlcmVzdCIuIFdlIGNhbiBsb29rLXVwIHRoZWlyIHJlc3VsdHMgZnJvbSB0aGUgdGFibGUuIEZvciBhIHRocmVzaG9sZC1mcmVlIGFuYWx5c2lzIHdlIGRlYWwgd2l0aCB0ZXN0IHN0YXRpc3RpY3Mgb3IgZm9sZC1jaGFuZ2UgdmFsdWVzIHRoYXQgaGF2ZSBkaXJlY3Rpb25hbGl0eSwgYXMgd2UgdHlwaWNhbGx5IHdhbnQgdG8gaWRlbnRpZnkgZ2VuZSBzZXRzIHRoYXQgY2hhbmdlIGV4cHJlc3Npb24gaW4gdGhlIHNhbWUgZGlyZWN0aW9uIChpLmUuIGFsbCB1cC0gb3IgZG93bi1yZWd1bGF0ZWQpLgpgYGB7ciBlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkobGltbWEpCmRlVGFibGUgPC0gcmVhZC5jc3YoInQ0N2RfVHJlYXRtZW50X0RFQV9Qcm9nLXZzLUNvbnRyb2xfYWxsLmNzdiIpCnN0YXRzIDwtIGRlVGFibGUkc3RhdApzdGF0c09yZGVyIDwtIG9yZGVyKHN0YXRzLGRlY3JlYXNpbmcgPSBUUlVFKQpteUluZGV4IDwtICBjKHNhbXBsZShzdGF0c09yZGVyWzE6NTAwXSw1KSxzYW1wbGUoNTAxOmxlbmd0aChzdGF0cyksNSkpCmRhdGEuZnJhbWUoR2VuZSA9IGRlVGFibGUkc3ltYm9sW215SW5kZXhdLCBTdGF0aXN0aWMgPSBzdGF0c1tteUluZGV4XSkKYGBgCgpTb21lIG9mIHRoZSBzdGF0aXN0aWNzIGxvb2sgaGlnaCwgYnV0IGhvdyBkbyB0aGV5IGNvbXBhcmUgdG8gdGhlIHJlc3Qgb2YgdGhlIGdlbmVzPyBBcmUgdGhleSB0b3dhcmRzIHRoZSB0b3Agb2YgdGhlIGxpc3QsIG9yIHNjYXR0ZXJlZCByYW5kb21seT8gVGhpcyBpcyB3aGF0IEdTRUEgdHJpZXMgdG8gZGV0ZXJtaW5lLiBXZSBhcmUgbm90IG1ha2luZyBhbnkgY2xhaW1zIGFib3V0IGFueSBwYXJ0aWN1bGFyIGdlbmUgaW4gdGhlIGxpc3QgYmVpbmcgREUsIG9ubHkgdGhhdCB0aGUgc2V0IGFzIGEgd2hvbGUgaXMgYWx0ZXJlZC4KCldlIHR5cGljYWxseSB2aXN1YWxpc2UgdGhlIHJlc3VsdHMgb2YgdGhlIGFuYWx5c2lzIGFzIGEgYmFyY29kZSBwbG90LiBGaXJzdGx5LCBhbGwgdGhlIHRlc3Qgc3RhdGlzdGljcyBhcmUgcmFua2VkIGZyb20gaGlnaGVzdCB0byBsb3dlc3QuIFdlIHRoZW4gZHJhdyBhIHZlcnRpY2FsIGxpbmUgYXQgZXZlcnkgcG9pbnQgd2hlcmUgYSBnZW5lIGluIG91ciBsaXN0IG9mIGludGVyZXN0IGlzIG9ic2VydmVkLiBXZSB0aGVuIGRldGVybWluZSB3aGVyZSB0aGUgKnBlYWsqIG9mIHRoZSBkaXN0cmlidXRpb24gaXMsIGFuZCBjb25zZXF1ZW50bHkgd2hldGhlciB0aGUgZ2VuZXMgYXJlIHRvd2FyZHMgdG8gdG9wIG9yIGJvdHRvbSBvZiB0aGUgcmFua2VkIGxpc3QuCgpIZXJlIGlzIHRoZSBwbG90IGZvciBvdXIgc2V0Oi0KCmBgYHtyIGVjaG89RkFMU0V9CmJhcmNvZGVwbG90KHN0YXRzLCBteUluZGV4KQpgYGAKCkluZGVlZCwgaXQgbG9va3MgYXMgdGhvdWdoIHRoZSBzdGF0aXN0aWNzIGFyZSBjb25jZW50cmF0ZWQgYXQgdGhlIHRvcCBvZiBvdXIgZ2VuZSBsaXN0LgoKVGhlIGNhc2Ugd2hlcmUgd2UgaGF2ZSBhIGRvd24tcmVndWxhdGVkIHBhdGh3YXkgbWlnaHQgbG9vayBzb21ldGhpbmcgbGlrZTotCgpgYGB7ciBlY2hvPUZBTFNFfQpzdGF0c1Jldk9yZGVyIDwtIG9yZGVyKHN0YXRzLGRlY3JlYXNpbmcgPSBGQUxTRSkKbXlSZXZJbmRleCA8LSAgYyhzYW1wbGUoc3RhdHNSZXZPcmRlclsxOjUwMF0sNSksc2FtcGxlKDUwMTpsZW5ndGgoc3RhdHMpLDUpKQpiYXJjb2RlcGxvdChzdGF0cywgbXlSZXZJbmRleCkKYGBgCgpPciBpbiB0aGUgY2FzZSBvZiBubyBlbnJpY2htZW50LCB0aGVyZSBpcyBubyBwYXJ0aWN1bGFyIHBhdHRlcm4gdG8gd2hlcmUgdGhlIGdlbmVzIG9jY3VyIGluIHRoZSByYW5rZWQgbGlzdAoKYGBge3IgZWNobz1GQUxTRX0KYmFyY29kZXBsb3Qoc3RhdHMsIHNhbXBsZSgxOmxlbmd0aChzdGF0cyksMTAwKSkKYGBgCgoKVGhlIEJyb2FkIGluc3RpdHV0ZSBwcm92aWRlcyBbYSB2ZXJzaW9uIG9mIEdTRUFdKGh0dHA6Ly9zb2Z0d2FyZS5icm9hZGluc3RpdHV0ZS5vcmcvZ3NlYS9pbmRleC5qc3ApIHRoYXQgY2FuIGJlIHJ1biB2aWEgYSBqYXZhIGFwcGxpY2F0aW9uLiBUaGUgaW5wdXQgdG8gR1NFQSBpcyBtYXRyaXggb2YgZXhwcmVzc2lvbiB2YWx1ZXMgYW5kIGEgZmlsZSBkZXNjcmliaW5nIHdoaWNoIGNvdmFyaWF0ZSBlYWNoIHNhbXBsZSBiZWxvbmdzIHRvLiBIb3dldmVyLCB3aGV0aGVyIG9yIG5vdCB0aGUgbWV0aG9kIGNhbiBiZSBhcHBsaWVkIGRpcmVjdGx5IHRvIFJOQS1zZXEgZGF0YSBpcyB1bmRlciBkZWJhdGUuIEFjY29yZGluZyB0byB0aGUgW0dTRUEgZmFxXShodHRwOi8vc29mdHdhcmUuYnJvYWRpbnN0aXR1dGUub3JnL2NhbmNlci9zb2Z0d2FyZS9nc2VhL3dpa2kvaW5kZXgucGhwL0ZBUSNDYW5fSV91c2VfR1NFQV90b19hbmFseXplX1NOUC4yQ19TQUdFLjJDX0NoSVAtU2VxX29yX1JOQS1TZXFfZGF0YS4zRikKCj4gVGhlIEdTRUEgdGVhbSBoYXMgeWV0IHRvIGRldGVybWluZSB3aGV0aGVyIGFueSBvZiB0aGVzZSByYW5raW5nIHN0YXRpc3RpY3MsIG9yaWdpbmFsbHkgc2VsZWN0ZWQgZm9yIHRoZWlyIGVmZmVjdGl2ZW5lc3Mgd2hlbiB1c2VkIHdpdGggZXhwcmVzc2lvbiBkYXRhIGRlcml2ZWQgZnJvbSBETkEgTWljcm9hcnJheSBleHBlcmltZW50cywgYXJlIGFwcHJvcHJpYXRlIGZvciB1c2Ugd2l0aCBleHByZXNzaW9uIGRhdGEgZGVyaXZlZCBmcm9tIFJOQS1zZXEgZXhwZXJpbWVudHMuIFdlIGhvcGVmdWxseSB3aWxsIGJlIGFibGUgdG8gZGV2b3RlIHNvbWUgdGltZSB0byBpbnZlc3RpZ2F0aW5nIHRoaXMsIGJ1dCBpbiB0aGUgbWVhbiB0aW1lLCB3ZSBhcmUgcmVjb21tZW5kaW5nIHVzZSBvZiB0aGUgR1NFQVByZXJhbmtlZCB0b29sIGZvciBjb25kdWN0aW5nIGdlbmUgc2V0IGVucmljaG1lbnQgYW5hbHlzaXMgb2YgZGF0YSBkZXJpdmVkIGZyb20gUk5BLXNlcSBleHBlcmltZW50cy4KClRoZSBHU0VBUHJlcmFua2VkIHRvb2wgbWVudGlvbmVkIGlzIGF2YWlsYWJsZSB0aHJvdWdoIHRoZSBCcm9hZCBpbnNpdHV0ZSdzIFtHZW5lUGF0dGVybl0oaHR0cHM6Ly9nZW5lcGF0dGVybi5icm9hZGluc3RpdHV0ZS5vcmcpIGFuYWx5c2lzIHN1aXRlLiBIb3dldmVyLCB3ZSBkb24ndCB3YW50IHRvIGludHJvZHVjZSB5ZXQgYW5vdGhlciBhbmFseXNpcyBzdWl0ZSwgc28gd2Ugd2lsbCBmb2N1cyBvbiBob3cgdG8gcGVyZm9ybSB0aGlzIGFuYWx5c2lzIGluIEdhbGF4eS4KCkdTRUEgdXNlcyBhIHNldCBvZiBwcmUtZGVmaW5lZCBnZW5lIHNldHMgaW4gdGhlaXIgYW5hbHlzaXMgd2hpY2ggY29tZSB1bmRlciB0aGUgZm9sbG93aW5nIGNhdGVnb3JpZXM6LQoKLSBIIGhhbGxtYXJrIGdlbmUgc2V0cwotIEMxIHBvc2l0aW9uYWwgZ2VuZSBzZXRzCi0gQzIgY3VyYXRlZCBnZW5lIHNldHMKLSBDMyBtb3RpZiBnZW5lIHNldHMKLSBDNCBjb21wdXRhdGlvbmFsIGdlbmUgc2V0cwotIEM1IEdPIGdlbmUgc2V0cwotIEM2IG9uY29nZW5pYyBzaWduYXR1cmVzCi0gQzcgaW1tdW5vbG9naWMgc2lnbmF0dXJlcwoKWW91IGNhbiBmaW5kIG91dCBtb3JlIGFib3V0IHRoZXNlIGdlbmUgc2V0cyBvbiB0aGUgW21zaWdkYl0oaHR0cDovL3NvZnR3YXJlLmJyb2FkaW5zdGl0dXRlLm9yZy9nc2VhL21zaWdkYikgd2Vic2l0ZS4gSG93ZXZlciwgaXQgaXMgaW1wb3J0YW50IHRvIG5vdGUgdGhhdCB0aGVzZSBnZW5lIHNldHMgaGF2ZSAqKkh1bWFuIGdlbmUgc3ltYm9scyoqIG9ubHkuCgplLmcuIEM2IG9uY29nZW5pYyBzaWduYXR1cmVzLCB3aGljaCB3ZXJlIHVzZWQgaW4gdGhlIG9yaWdpbmFsIEdTRUEgYW5hbHlzaXMgb2YgdGhpcyBkYXRhc2V0Cgo+IEdlbmUgc2V0cyByZXByZXNlbnQgc2lnbmF0dXJlcyBvZiBjZWxsdWxhciBwYXRod2F5cyB3aGljaCBhcmUgb2Z0ZW4gZGlzLXJlZ3VsYXRlZCBpbiBjYW5jZXIuIFRoZSBtYWpvcml0eSBvZiBzaWduYXR1cmVzIHdlcmUgZ2VuZXJhdGVkIGRpcmVjdGx5IGZyb20gbWljcm9hcnJheSBkYXRhIGZyb20gTkNCSSBHRU8gb3IgZnJvbSBpbnRlcm5hbCB1bnB1Ymxpc2hlZCBwcm9maWxpbmcgZXhwZXJpbWVudHMgd2hpY2ggaW52b2x2ZWQgcGVydHVyYmF0aW9uIG9mIGtub3duIGNhbmNlciBnZW5lcy4gSW4gYWRkaXRpb24sIGEgc21hbGwgbnVtYmVyIG9mIG9uY29nZW5pYyBzaWduYXR1cmVzIHdlcmUgY3VyYXRlZCBmcm9tIHNjaWVudGlmaWMgcHVibGljYXRpb25zLgoKIyMgUHJlcGFyaW5nIHRoZSBnZW5lIHNldCBmb3IgYSBHU0VBIGFuYWx5c2lzCgpJbiBvcmRlciB0byBwZXJmb3JtIHRoZSBHU0VBUHJlUmFua2VkIGFuYWx5c2lzLCBvbmUgbmVlZHMgdG8gY3JlYXRlIGZpbGUgd2l0aCB0d28gY29sdW1uczsgdGhlIGZpcnN0IGNvbnRhaW5pbmcgdGhlIGdlbmUgc3ltYm9sLCBhbmQgdGhlIHNlY29uZCBpcyB0aGUgKHJhbmtlZCkgc3RhdGlzdGljIGZvciB0aGUgZ2VuZS4gRm9yIHRob3NlIGludGVyZXN0ZWQsIGhlcmUgaXMgdGhlIFIgY29kZSB0byBwcm9kdWNlIGEgZmlsZSBzdWl0YWJsZSBmb3IgR1NFQSBhbmFseXNpczotCgpgYGB7cn0KbGlicmFyeShkcGx5cikKZGVUYWJsZSA8LSByZWFkLmNzdigidDQ3ZF9UcmVhdG1lbnRfREVBX1Byb2ctdnMtQ29udHJvbF9hbGwuY3N2IikKZGVUYWJsZSAlPiUgYXJyYW5nZShkZXNjKHN0YXQpKSAlPiUgCiAgZHBseXI6OjpzZWxlY3Qoc3ltYm9sLCBzdGF0KSAlPiUgCiAgZmlsdGVyKCFpcy5uYShzeW1ib2wpKSAtPiBvcmRlcmVkVGFibGUKb3JkZXJlZFRhYmxlCmBgYAoKTm93IGxldHMgd2Fsa3Rocm91Z2ggaG93IHRvIGRvIHRoYXQgaW4gR2FsYXh5Oi0KCiMjIyBSYW5raW5nIHRoZSBnZW5lcwoKTWFrZSBzdXJlIHlvdXIgKioqY2xlYW5lZCBkYXRhc2V0KioqIGlzIHNlbGVjdGVkIChjb252ZXJ0ZWQgdG8gdGFidWxhciwgcmVtb3ZlZCBoZWFkZXIgYW5kIGN1dCBjb2x1bW5zKSwgc29ydCBvbiBjb2x1bW4gNSAodGhlIHRlc3Qgc3RhdGlzdGljKQoKKioqRmlsdGVyIGFuZCBTb3J0KioqIC0+ICoqKlNvcnQgZGF0YSBpbiBhc2NlbmRpbmcgb3IgZGVzY2VuZGluZyBvcmRlcioqKgoKIVtdKGltYWdlcy9nYWxheHktMTAucG5nKQoKR2l2aW5nIHRoZSBvdXRwdXQ6LQoKIVtdKGltYWdlcy9nYWxheHktMTEucG5nKQoKV2Ugbm93IGhhdmUgYWxsIHRoZSBpbmZvcm1hdGlvbiB3ZSBuZWVkLCBidXQgdGhlIEdTRUEgdG9vbCBleHBlY3RzIG9ubHkgdHdvIGNvbHVtbnM7IGdlbmUgc3ltYm9sIGFuZCByYW5rZWQgc3RhdGlzdGljCgojIyMgQ3V0dGluZyB0aGUgY29sdW1ucwoKRXh0cmFjdCBjb2x1bW5zIDggKGdlbmUgc3ltYm9sKSBmb2xsb3dlZCBieSB0ZXN0IHN0YXRpc3RpYzsgYGM4LGM1YAoKKioqVGV4dCBNYW5pcHVsYXRpb24qKiogLT4gKioqQ3V0IGNvbHVtbnMgZnJvbSBhIHRhYmxlKioqCgohW10oaW1hZ2VzL2dhbGF4eS0xMi5wbmcpCgoKIyMgUnVubmluZyBhIEdTRUEgYW5hbHlzaXMKCiMjIyBVc2luZyB0aGUgZkdTRUEgdG9vbAoKYGZHU0VBYCBpcyBhIEJpb2NvbmR1Y3RvciBwYWNrYWdlIHRoYXQgaW1wbGVtZW50cyB0aGUgcHJlLXJhbmtlZCBHU0VBIGFuYWx5c2lzLiBJdCBhbHNvIGhhcHBlbnMgdG8gYmUgYSBmYXN0ZXIgaW1wbGVtZW50YXRpb24sIGFzIGRlc2NyaWJlZCBpbiB0aGVpciBbcHJlLXByaW50XShodHRwOi8vYmlvcnhpdi5vcmcvY29udGVudC9lYXJseS8yMDE2LzA2LzIwLzA2MDAxMikKCllvdSBjYW4gZmluZCB0aGUgdG9vbCB1bmRlciAqKipOR1M6IFJOQS1zZXEgQW5hbHlzaXMqKioKCiFbXShpbWFnZXMvZ2FsYXh5LTEzLnBuZykKCldpdGggdGhpcyB0b29sLCB0aHJlZSBkaWZmZXJlbnQgb3V0cHV0cyBhcmUgcHJvZHVjZWQKCi0gYSByZXN1bHRzIHRhYmxlCi0gYSBzdW1tYXJ5IGdyYXBoaWMgb2YgdGhlIHRvcCBwYXRod2F5cwotIGVucmljaG1lbnQgcGxvdHMgZm9yIHRoZSB0b3AgcGF0aHdheXMKCiMjIFRoaW5ncyB0byB0cnk6CgotIENhbiB5b3UgaWRlbnRpZnkgcGF0aHdheXMgdGhhdCBhcmUgc2lnbmlmaWNhbnQgYXQgMC4wNSBsZXZlbD8KLSBXaGF0IHBhdGh3YXlzIGFyZSBvdmVyLSBhbmQgdW5kZXItcmVwcmVzZW50ZWQ/CgoKIyBNZXRhQ29yZQoKPiAiWW91ciBHUFMgaW4gU3lzdGVtcyBCaW9sb2d5IgoKVGhlIGluc3RpdHV0ZSBoYXMgYSBsaWNlbnNlIGZvciBbTWV0YWNvcmVdKGh0dHBzOi8vcG9ydGFsLmdlbmVnby5jb20vKSBieSBUaG9tc29uIFJldXRlcnMuIFlvdSBtdXN0IGZpcnN0IG9idGFpbiBhIGxvZ2luIChlbWFpbCAqQXNobGV5IFNhd2xlKiBpbiB0aGUgQmlvaW5mb3JtYXRpY3MgQ29yZSksIGFuZCB0aGVuIGJvb2sgdGltZSB0byB1c2UgdGhlIHNpdGUgKG91ciBsaWNlbnNlIG9ubHkgcGVybWl0cyBvbmUgdXNlciB0byBiZSBsb2dnZWQtaW4gYXQgYSB0aW1lKS4gTm90IG9ubHkgZG9lcyBNZXRhY29yZSBwcm92aWRlIGEgc21hcnQgaW50ZXJmYWNlLCBidXQgdGhleSBoYXZlIGludmVzdGVkIGEgbG90IG9mIHRpbWUgbWFudWFsbHktY3VyYXRpbmcgcmVzdWx0cyBmcm9tIHRoZSBsaXRlcmF0dXJlLiBDb25zZXF1ZW50bHksIHRoZWlyIGRhdGFiYXNlIGFuZCBnZW5lIG5ldHdvcmtzIGFyZSBwcm9wcmlldGFyeSBhbmQgd2hhdCB0aGUgbGljZW5zZSBmZWUgaXMgcGF5aW5nIGZvci4KCi0gKGZvciBDUlVLIHVzZSBvbmx5KSBbVHJhaW5pbmcgTWF0ZXJpYWxzXShodHRwczovL3NoYXJlcG9pbnQuY3JpLmNhbXJlcy5vcmcvc2l0ZXMvYmlvaW5mb3JtYXRpY3MvUHVibGljL01ldGFjb3JlL0NSVUslMjBDYW1icmlkZ2UlMjBUcmFpbmluZyUyMDA2MDMyMDE1LnBkZikKCgojIyBQcmVwYXJpbmcgZm9yIE1ldGFjb3JlIGluIEdhbGF4eQoKKioqVGV4dCBNYW5pcHVsYXRpb24qKiogLT4gKioqQ3V0IGNvbHVtbnMgZm9yIGEgdGFibGUqKiogCgpTZWxlY3QgRW5zZW1ibCBJRHMsIGxvZzJGb2xkQ2hhbmdlIGFuZCBhZGp1c3RlZCBwLXZhbHVlIChjb2x1bW5zIDEsIDMgYW5kIDcpLgoKIVtdKGltYWdlcy9nYWxheHktdG8tbWV0YWNvcmUucG5nKQoKT3IsIGluIFI6LQoKYGBge3J9CnJlYWQuY3N2KCJ0NDdkX1RyZWF0bWVudF9ERUFfUHJvZy12cy1Db250cm9sX2FsbC5jc3YiKSAlPiUgI2hlYWQKICBkcGx5cjo6OnNlbGVjdChYLGxvZzJGb2xkQ2hhbmdlLCBwYWRqKSAlPiUgCiAgICB3cml0ZS50YWJsZSgidDQ3ZF9UcmVhdG1lbnRfREVBX1Byb2ctdnMtQ29udHJvbF9hbGxfZm9yTWV0YWNvcmUudHh0IixzZXA9Ilx0IixxdW90ZT1GQUxTRSxyb3cubmFtZXM9RkFMU0UpCmBgYAoKCllvdSBhcmUgdGhlbiByZWFkeSB0byBsb2FkIHRoZSBkYXRhIGludG8gTWV0YWNvcmU6LQoKIVtdKGltYWdlcy9tZXRhY29yZS1ob21lLnBuZykKCioqKlVwbG9hZCoqKiAtPiAqKipVcGxvYWQgRXhwZXJpbWVudHMgd2l0aCBHZW5lIG9yIFByb3RlaW4gSURzKioqCgoKU3BlY2lmeSB0eXBlcyBvZiBkYXRhIGluIGVhY2ggY29sdW1uCgohW10oaW1hZ2VzL21ldGFjb3JlLWNvbHVtbnMucG5nKQoK