From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 8B60E261EB for ; Thu, 28 Jun 2018 08:54:37 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VRA5QKbRBP2v for ; Thu, 28 Jun 2018 08:54:37 -0400 (EDT) Received: from mail-lj1-f193.google.com (mail-lj1-f193.google.com [209.85.208.193]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id E7208261EA for ; Thu, 28 Jun 2018 08:54:36 -0400 (EDT) Received: by mail-lj1-f193.google.com with SMTP id t7-v6so4414017ljj.6 for ; Thu, 28 Jun 2018 05:54:36 -0700 (PDT) MIME-Version: 1.0 References: <1530190036-10105-1-git-send-email-hollow653@gmail.com> In-Reply-To: <1530190036-10105-1-git-send-email-hollow653@gmail.com> From: Hollow111 Date: Thu, 28 Jun 2018 15:54:24 +0300 Message-ID: Subject: [tarantool-patches] Re: [PATCH] sql: LIKE & GLOB pattern comparison issue Content-Type: multipart/alternative; boundary="000000000000b8a865056fb33bb1" Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: alexander.turenko@tarantool.org --000000000000b8a865056fb33bb1 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Branch: https://github.com/tarantool/tarantool/tree/N_Tatunov/gh-3251-where-like-ha= nging Issue: https://github.com/tarantool/tarantool/issues/3251 Issue: https://github.com/tarantool/tarantool/issues/3334 =D1=87=D1=82, 28 =D0=B8=D1=8E=D0=BD. 2018 =D0=B3. =D0=B2 15:47, N.Tatunov <= hollow653@gmail.com>: > Currently function that compares pattern and > string for GLOB & LIKE operators doesn't work properly. > It uses ICU reading function which perhaps was working > differently before and the implementation for the > comparison ending isn't paying attention to some > special cases, hence in those cases it works improperly. > Now the checks for comparison should work fine. > > =D0=A1loses: #3251 > =D0=A1loses: #3334 > --- > src/box/sql/func.c | 25 ++++---- > test/sql-tap/like1.test.lua | 152 > ++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 165 insertions(+), 12 deletions(-) > create mode 100755 test/sql-tap/like1.test.lua > > diff --git a/src/box/sql/func.c b/src/box/sql/func.c > index c06e3bd..dcbd7e0 100644 > --- a/src/box/sql/func.c > +++ b/src/box/sql/func.c > @@ -643,6 +643,7 @@ static const struct compareInfo likeInfoAlt =3D { '%'= , > '_', 0, 0 }; > #define SQLITE_MATCH 0 > #define SQLITE_NOMATCH 1 > #define SQLITE_NOWILDCARDMATCH 2 > +#define SQL_NO_SYMBOLS_LEFT 65535 > > /* > * Compare two UTF-8 strings for equality where the first string is > @@ -698,29 +699,28 @@ patternCompare(const char * pattern, /* The > glob pattern */ > const char * string_end =3D string + strlen(string); > UErrorCode status =3D U_ZERO_ERROR; > > - while (pattern < pattern_end){ > - c =3D Utf8Read(pattern, pattern_end); > + while ((c =3D Utf8Read(pattern, pattern_end)) !=3D > SQL_NO_SYMBOLS_LEFT) { > if (c =3D=3D matchAll) { /* Match "*" */ > /* Skip over multiple "*" characters in the > pattern. If there > * are also "?" characters, skip those as well, > but consume a > * single character of the input string for each > "?" skipped > */ > - while (pattern < pattern_end){ > - c =3D Utf8Read(pattern, pattern_end); > + while ((c =3D Utf8Read(pattern, pattern_end)) != =3D > + SQL_NO_SYMBOLS_LEFT) { > if (c !=3D matchAll && c !=3D matchOne) > break; > - if (c =3D=3D matchOne > - && Utf8Read(string, string_end) =3D= =3D 0) { > + if (c =3D=3D matchOne && > + Utf8Read(string, string_end) =3D=3D > + SQL_NO_SYMBOLS_LEFT) > return SQLITE_NOWILDCARDMATCH; > - } > } > /* "*" at the end of the pattern matches */ > - if (pattern =3D=3D pattern_end) > + if (c =3D=3D SQL_NO_SYMBOLS_LEFT) > return SQLITE_MATCH; > if (c =3D=3D matchOther) { > if (pInfo->matchSet =3D=3D 0) { > c =3D Utf8Read(pattern, pattern_e= nd); > - if (c =3D=3D 0) > + if (c =3D=3D SQL_NO_SYMBOLS_LEFT) > return > SQLITE_NOWILDCARDMATCH; > } else { > /* "[...]" immediately follows th= e > "*". We have to do a slow > @@ -782,7 +782,7 @@ patternCompare(const char * pattern, /* The > glob pattern */ > if (c =3D=3D matchOther) { > if (pInfo->matchSet =3D=3D 0) { > c =3D Utf8Read(pattern, pattern_end); > - if (c =3D=3D 0) > + if (c =3D=3D SQL_NO_SYMBOLS_LEFT) > return SQLITE_NOMATCH; > zEscaped =3D pattern; > } else { > @@ -802,7 +802,7 @@ patternCompare(const char * pattern, /* The > glob pattern */ > seen =3D 1; > c2 =3D Utf8Read(pattern, > pattern_end); > } > - while (c2 && c2 !=3D ']') { > + while (c2 !=3D SQL_NO_SYMBOLS_LEFT && c2 = !=3D > ']') { > if (c2 =3D=3D '-' && pattern[0] != =3D ']' > && pattern < pattern_end > && prior_c > 0) { > @@ -839,7 +839,8 @@ patternCompare(const char * pattern, /* The > glob pattern */ > c =3D=3D u_tolower(c2)) > continue; > } > - if (c =3D=3D matchOne && pattern !=3D zEscaped && c2 !=3D= 0) > + if (c =3D=3D matchOne && pattern !=3D zEscaped && > + c2 !=3D SQL_NO_SYMBOLS_LEFT) > continue; > return SQLITE_NOMATCH; > } > diff --git a/test/sql-tap/like1.test.lua b/test/sql-tap/like1.test.lua > new file mode 100755 > index 0000000..42b4d43 > --- /dev/null > +++ b/test/sql-tap/like1.test.lua > @@ -0,0 +1,152 @@ > +#!/usr/bin/env tarantool > +test =3D require("sqltester") > +test:plan(13) > + > +test:do_catchsql_test( > + "like-test-1.1", > + [[ > + CREATE TABLE t2 (column1 INTEGER, > + column2 VARCHAR(100), > + column3 BLOB, > + column4 FLOAT, > + PRIMARY KEY (column1, column2)); > + INSERT INTO t2 VALUES (1, 'AB', X'4142', 5.5); > + INSERT INTO t2 VALUES (1, 'CD', X'2020', 1E4); > + INSERT INTO t2 VALUES (2, 'AB', X'2020', 12.34567); > + INSERT INTO t2 VALUES (-1000, '', X'', 0.0); > + CREATE TABLE t1 (a INT PRIMARY KEY, str VARCHAR(100)); > + INSERT INTO t1 VALUES (1, 'ab'); > + INSERT INTO t1 VALUES (2, 'abCDF'); > + INSERT INTO t1 VALUES (3, 'CDF'); > + CREATE TABLE t (s1 char(2) primary key, s2 char(2)); > + INSERT INTO t VALUES ('AB', 'AB'); > + ]], { > + -- > + 0 > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.2", > + [[ > + SELECT column1, column2, column1 * column4 FROM t2 WHERE > column2 LIKE '_B'; > + ]], { > + -- > + 1, 'AB', 5.5, 2, 'AB', 24.69134 > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.3", > + [[ > + SELECT column1, column2 FROM t2 WHERE column2 LIKE '%B'; > + ]], { > + -- > + 1, 'AB', 2, 'AB' > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.4", > + [[ > + SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A__'; > + ]], { > + -- > + > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.5", > + [[ > + SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A_'; > + ]], { > + -- > + 1, 'AB', 2, 'AB' > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.6", > + [[ > + SELECT column1, column2 FROM t2 WHERE column2 LIKE 'A'; > + ]], { > + -- > + > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.7", > + [[ > + SELECT column1, column2 FROM t2 WHERE column2 LIKE '_'; > + ]], { > + -- > + > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.8", > + [[ > + SELECT * FROM t WHERE s1 LIKE '%A'; > + ]], { > + -- > + > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.9", > + [[ > + SELECT * FROM t WHERE s1 LIKE '%C'; > + ]], { > + -- > + > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.10", > + [[ > + SELECT * FROM t1 WHERE str LIKE '%df'; > + ]], { > + -- > + 2, 'abCDF', 3, 'CDF' > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.11", > + [[ > + SELECT * FROM t1 WHERE str LIKE 'a_'; > + ]], { > + -- > + 1, 'ab' > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.12", > + [[ > + select column1, column2 from t2 where column2 like '__'; > + ]], { > + -- > + 1, 'AB', 1, 'CD', 2, 'AB' > + -- > + }) > + > +test:do_execsql_test( > + "like-test-1.13", > + [[ > + DROP TABLE t1; > + DROP TABLE t2; > + DROP TABLE t; > + ]], { > + -- > + > + -- > + }) > + > + > +test:finish_test() > -- > 2.7.4 > > --000000000000b8a865056fb33bb1 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PGRpdj5CcmFuY2g6IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS90 YXJhbnRvb2wvdGFyYW50b29sL3RyZWUvTl9UYXR1bm92L2doLTMyNTEtd2hlcmUtbGlrZS1oYW5n aW5nIj5odHRwczovL2dpdGh1Yi5jb20vdGFyYW50b29sL3RhcmFudG9vbC90cmVlL05fVGF0dW5v di9naC0zMjUxLXdoZXJlLWxpa2UtaGFuZ2luZzwvYT48L2Rpdj48ZGl2Pklzc3VlOiA8YSBocmVm PSJodHRwczovL2dpdGh1Yi5jb20vdGFyYW50b29sL3RhcmFudG9vbC9pc3N1ZXMvMzI1MSI+aHR0 cHM6Ly9naXRodWIuY29tL3RhcmFudG9vbC90YXJhbnRvb2wvaXNzdWVzLzMyNTE8L2E+PC9kaXY+ PGRpdj5Jc3N1ZTogPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL3RhcmFudG9vbC90YXJhbnRv b2wvaXNzdWVzLzMzMzQiPmh0dHBzOi8vZ2l0aHViLmNvbS90YXJhbnRvb2wvdGFyYW50b29sL2lz c3Vlcy8zMzM0PC9hPjwvZGl2PjxkaXY+PGJyPjwvZGl2PjwvZGl2Pjxicj48ZGl2IGNsYXNzPSJn bWFpbF9xdW90ZSI+PGRpdiBkaXI9Imx0ciI+0YfRgiwgMjgg0LjRjtC9LiAyMDE4INCzLiDQsiAx NTo0NywgTi5UYXR1bm92ICZsdDs8YSBocmVmPSJtYWlsdG86aG9sbG93NjUzQGdtYWlsLmNvbSI+ aG9sbG93NjUzQGdtYWlsLmNvbTwvYT4mZ3Q7Ojxicj48L2Rpdj48YmxvY2txdW90ZSBjbGFzcz0i Z21haWxfcXVvdGUiIHN0eWxlPSJtYXJnaW46MCAwIDAgLjhleDtib3JkZXItbGVmdDoxcHggI2Nj YyBzb2xpZDtwYWRkaW5nLWxlZnQ6MWV4Ij5DdXJyZW50bHkgZnVuY3Rpb24gdGhhdCBjb21wYXJl cyBwYXR0ZXJuIGFuZDxicj4NCnN0cmluZyBmb3IgR0xPQiAmYW1wOyBMSUtFIG9wZXJhdG9ycyBk b2VzbiYjMzk7dCB3b3JrIHByb3Blcmx5Ljxicj4NCkl0IHVzZXMgSUNVIHJlYWRpbmcgZnVuY3Rp b24gd2hpY2ggcGVyaGFwcyB3YXMgd29ya2luZzxicj4NCmRpZmZlcmVudGx5IGJlZm9yZSBhbmQg dGhlIGltcGxlbWVudGF0aW9uIGZvciB0aGU8YnI+DQpjb21wYXJpc29uIGVuZGluZyBpc24mIzM5 O3QgcGF5aW5nIGF0dGVudGlvbiB0byBzb21lPGJyPg0Kc3BlY2lhbCBjYXNlcywgaGVuY2UgaW4g dGhvc2UgY2FzZXMgaXQgd29ya3MgaW1wcm9wZXJseS48YnI+DQpOb3cgdGhlIGNoZWNrcyBmb3Ig Y29tcGFyaXNvbiBzaG91bGQgd29yayBmaW5lLjxicj4NCjxicj4NCtChbG9zZXM6ICMzMjUxPGJy Pg0K0KFsb3NlczogIzMzMzQ8YnI+DQotLS08YnI+DQrCoHNyYy9ib3gvc3FsL2Z1bmMuY8KgIMKg IMKgIMKgIMKgIHzCoCAyNSArKysrLS0tLTxicj4NCsKgdGVzdC9zcWwtdGFwL2xpa2UxLnRlc3Qu bHVhIHwgMTUyICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrPGJy Pg0KwqAyIGZpbGVzIGNoYW5nZWQsIDE2NSBpbnNlcnRpb25zKCspLCAxMiBkZWxldGlvbnMoLSk8 YnI+DQrCoGNyZWF0ZSBtb2RlIDEwMDc1NSB0ZXN0L3NxbC10YXAvbGlrZTEudGVzdC5sdWE8YnI+ DQo8YnI+DQpkaWZmIC0tZ2l0IGEvc3JjL2JveC9zcWwvZnVuYy5jIGIvc3JjL2JveC9zcWwvZnVu Yy5jPGJyPg0KaW5kZXggYzA2ZTNiZC4uZGNiZDdlMCAxMDA2NDQ8YnI+DQotLS0gYS9zcmMvYm94 L3NxbC9mdW5jLmM8YnI+DQorKysgYi9zcmMvYm94L3NxbC9mdW5jLmM8YnI+DQpAQCAtNjQzLDYg KzY0Myw3IEBAIHN0YXRpYyBjb25zdCBzdHJ1Y3QgY29tcGFyZUluZm8gbGlrZUluZm9BbHQgPSB7 ICYjMzk7JSYjMzk7LCAmIzM5O18mIzM5OywgMCwgMCB9Ozxicj4NCsKgI2RlZmluZSBTUUxJVEVf TUFUQ0jCoCDCoCDCoCDCoCDCoCDCoCDCoDA8YnI+DQrCoCNkZWZpbmUgU1FMSVRFX05PTUFUQ0jC oCDCoCDCoCDCoCDCoCDCoDE8YnI+DQrCoCNkZWZpbmUgU1FMSVRFX05PV0lMRENBUkRNQVRDSMKg IMKgMjxicj4NCisjZGVmaW5lIFNRTF9OT19TWU1CT0xTX0xFRlTCoCDCoCDCoCA2NTUzNTxicj4N Cjxicj4NCsKgLyo8YnI+DQrCoCAqIENvbXBhcmUgdHdvIFVURi04IHN0cmluZ3MgZm9yIGVxdWFs aXR5IHdoZXJlIHRoZSBmaXJzdCBzdHJpbmcgaXM8YnI+DQpAQCAtNjk4LDI5ICs2OTksMjggQEAg cGF0dGVybkNvbXBhcmUoY29uc3QgY2hhciAqIHBhdHRlcm4swqAgwqAgwqAgLyogVGhlIGdsb2Ig cGF0dGVybiAqLzxicj4NCsKgIMKgIMKgIMKgIGNvbnN0IGNoYXIgKiBzdHJpbmdfZW5kID0gc3Ry aW5nICsgc3RybGVuKHN0cmluZyk7PGJyPg0KwqAgwqAgwqAgwqAgVUVycm9yQ29kZSBzdGF0dXMg PSBVX1pFUk9fRVJST1I7PGJyPg0KPGJyPg0KLcKgIMKgIMKgIMKgd2hpbGUgKHBhdHRlcm4gJmx0 OyBwYXR0ZXJuX2VuZCl7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYyA9IFV0ZjhSZWFk KHBhdHRlcm4sIHBhdHRlcm5fZW5kKTs8YnI+DQorwqAgwqAgwqAgwqB3aGlsZSAoKGMgPSBVdGY4 UmVhZChwYXR0ZXJuLCBwYXR0ZXJuX2VuZCkpICE9IFNRTF9OT19TWU1CT0xTX0xFRlQpIHs8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoYyA9PSBtYXRjaEFsbCkge8KgIMKgIC8qIE1h dGNoICZxdW90OyomcXVvdDsgKi88YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCAvKiBTa2lwIG92ZXIgbXVsdGlwbGUgJnF1b3Q7KiZxdW90OyBjaGFyYWN0ZXJzIGluIHRo ZSBwYXR0ZXJuLsKgIElmIHRoZXJlPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAqIGFyZSBhbHNvICZxdW90Oz8mcXVvdDsgY2hhcmFjdGVycywgc2tpcCB0aG9zZSBh cyB3ZWxsLCBidXQgY29uc3VtZSBhPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAqIHNpbmdsZSBjaGFyYWN0ZXIgb2YgdGhlIGlucHV0IHN0cmluZyBmb3IgZWFjaCAm cXVvdDs/JnF1b3Q7IHNraXBwZWQ8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgd2hpbGUg KHBhdHRlcm4gJmx0OyBwYXR0ZXJuX2VuZCl7PGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYyA9IFV0ZjhSZWFkKHBhdHRlcm4sIHBhdHRlcm5fZW5k KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB3aGlsZSAoKGMgPSBV dGY4UmVhZChwYXR0ZXJuLCBwYXR0ZXJuX2VuZCkpICE9PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIFNRTF9OT19TWU1CT0xTX0xFRlQpIHs8YnI+DQrC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoYyAhPSBt YXRjaEFsbCAmYW1wOyZhbXA7IGMgIT0gbWF0Y2hPbmUpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYnJlYWs7PGJyPg0KLcKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGMgPT0gbWF0 Y2hPbmU8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAmYW1wOyZhbXA7IFV0ZjhSZWFkKHN0cmluZywgc3RyaW5nX2VuZCkgPT0gMCkgezxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChj ID09IG1hdGNoT25lICZhbXA7JmFtcDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBVdGY4UmVhZChzdHJpbmcsIHN0cmluZ19lbmQpID09 PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgU1FMX05PX1NZTUJPTFNfTEVGVCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gU1FMSVRFX05PV0lMRENBUkRN QVRDSDs8YnI+DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqB9PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgfTxicj4NCsKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8qICZxdW90OyomcXVvdDsgYXQgdGhlIGVu ZCBvZiB0aGUgcGF0dGVybiBtYXRjaGVzICovPGJyPg0KLcKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgaWYgKHBhdHRlcm4gPT0gcGF0dGVybl9lbmQpPGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgaWYgKGMgPT0gU1FMX05PX1NZTUJPTFNfTEVGVCk8YnI+ DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4g U1FMSVRFX01BVENIOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIGlm IChjID09IG1hdGNoT3RoZXIpIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCBpZiAocEluZm8tJmd0O21hdGNoU2V0ID09IDApIHs8YnI+DQrCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBj ID0gVXRmOFJlYWQocGF0dGVybiwgcGF0dGVybl9lbmQpOzxicj4NCi3CoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChjID09IDApPGJy Pg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgaWYgKGMgPT0gU1FMX05PX1NZTUJPTFNfTEVGVCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBy ZXR1cm4gU1FMSVRFX05PV0lMRENBUkRNQVRDSDs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9IGVsc2Ugezxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIC8qICZxdW90O1suLi5d JnF1b3Q7IGltbWVkaWF0ZWx5IGZvbGxvd3MgdGhlICZxdW90OyomcXVvdDsuwqAgV2UgaGF2ZSB0 byBkbyBhIHNsb3c8YnI+DQpAQCAtNzgyLDcgKzc4Miw3IEBAIHBhdHRlcm5Db21wYXJlKGNvbnN0 IGNoYXIgKiBwYXR0ZXJuLMKgIMKgIMKgIMKgIC8qIFRoZSBnbG9iIHBhdHRlcm4gKi88YnI+DQrC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoYyA9PSBtYXRjaE90aGVyKSB7PGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgaWYgKHBJbmZvLSZndDttYXRjaFNldCA9PSAw KSB7PGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg YyA9IFV0ZjhSZWFkKHBhdHRlcm4sIHBhdHRlcm5fZW5kKTs8YnI+DQotwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoYyA9PSAwKTxicj4NCivCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoGlmIChjID09IFNRTF9OT19T WU1CT0xTX0xFRlQpPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgcmV0dXJuIFNRTElURV9OT01BVENIOzxicj4NCsKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHpFc2NhcGVkID0gcGF0dGVy bjs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCB9IGVsc2Ugezxicj4N CkBAIC04MDIsNyArODAyLDcgQEAgcGF0dGVybkNvbXBhcmUoY29uc3QgY2hhciAqIHBhdHRlcm4s wqAgwqAgwqAgwqAgLyogVGhlIGdsb2IgcGF0dGVybiAqLzxicj4NCsKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIHNl ZW4gPSAxOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIMKgIGMyID0gVXRmOFJlYWQocGF0dGVybiwgcGF0dGVybl9lbmQpOzxicj4N CsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+DQot wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqB3aGlsZSAoYzIg JmFtcDsmYW1wOyBjMiAhPSAmIzM5O10mIzM5Oykgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoHdoaWxlIChjMiAhPSBTUUxfTk9fU1lNQk9MU19M RUZUICZhbXA7JmFtcDsgYzIgIT0gJiMzOTtdJiMzOTspIHs8YnI+DQrCoCDCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCBpZiAoYzIgPT0gJiMz OTstJiMzOTsgJmFtcDsmYW1wOyBwYXR0ZXJuWzBdICE9ICYjMzk7XSYjMzk7PGJyPg0KwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgJmFtcDsmYW1wOyBwYXR0ZXJuICZsdDsgcGF0dGVybl9lbmQ8YnI+DQrCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCAmYW1w OyZhbXA7IHByaW9yX2MgJmd0OyAwKSB7PGJyPg0KQEAgLTgzOSw3ICs4MzksOCBAQCBwYXR0ZXJu Q29tcGFyZShjb25zdCBjaGFyICogcGF0dGVybizCoCDCoCDCoCDCoCAvKiBUaGUgZ2xvYiBwYXR0 ZXJuICovPGJyPg0KwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgYyA9 PSB1X3RvbG93ZXIoYzIpKTxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIMKgIGNvbnRpbnVlOzxicj4NCsKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIH08YnI+ DQotwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBpZiAoYyA9PSBtYXRjaE9uZSAmYW1wOyZhbXA7IHBh dHRlcm4gIT0gekVzY2FwZWQgJmFtcDsmYW1wOyBjMiAhPSAwKTxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoGlmIChjID09IG1hdGNoT25lICZhbXA7JmFtcDsgcGF0dGVybiAhPSB6RXNjYXBl ZCAmYW1wOyZhbXA7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgYzIgIT0gU1FM X05PX1NZTUJPTFNfTEVGVCk8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCDC oCBjb250aW51ZTs8YnI+DQrCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoCByZXR1cm4gU1FMSVRFX05P TUFUQ0g7PGJyPg0KwqAgwqAgwqAgwqAgfTxicj4NCmRpZmYgLS1naXQgYS90ZXN0L3NxbC10YXAv bGlrZTEudGVzdC5sdWEgYi90ZXN0L3NxbC10YXAvbGlrZTEudGVzdC5sdWE8YnI+DQpuZXcgZmls ZSBtb2RlIDEwMDc1NTxicj4NCmluZGV4IDAwMDAwMDAuLjQyYjRkNDM8YnI+DQotLS0gL2Rldi9u dWxsPGJyPg0KKysrIGIvdGVzdC9zcWwtdGFwL2xpa2UxLnRlc3QubHVhPGJyPg0KQEAgLTAsMCAr MSwxNTIgQEA8YnI+DQorIyEvdXNyL2Jpbi9lbnYgdGFyYW50b29sPGJyPg0KK3Rlc3QgPSByZXF1 aXJlKCZxdW90O3NxbHRlc3RlciZxdW90Oyk8YnI+DQordGVzdDpwbGFuKDEzKTxicj4NCis8YnI+ DQordGVzdDpkb19jYXRjaHNxbF90ZXN0KDxicj4NCivCoCDCoCDCoCDCoCZxdW90O2xpa2UtdGVz dC0xLjEmcXVvdDssPGJyPg0KK8KgIMKgIMKgIMKgW1s8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBDUkVBVEUgVEFCTEUgdDIgKGNvbHVtbjEgSU5URUdFUiw8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY29sdW1uMiBWQVJDSEFS KDEwMCksPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKgIMKg IMKgIMKgIMKgIGNvbHVtbjMgQkxPQiw8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgY29sdW1uNCBGTE9BVCw8YnI+DQorwqAgwqAgwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAgUFJJTUFSWSBLRVkg KGNvbHVtbjEsIGNvbHVtbjIpKTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBJTlNFUlQg SU5UTyB0MiBWQUxVRVMgKDEsICYjMzk7QUImIzM5OywgWCYjMzk7NDE0MiYjMzk7LCA1LjUpOzxi cj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOU0VSVCBJTlRPIHQyIFZBTFVFUyAoMSwgJiMz OTtDRCYjMzk7LCBYJiMzOTsyMDIwJiMzOTssIDFFNCk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgSU5TRVJUIElOVE8gdDIgVkFMVUVTICgyLCAmIzM5O0FCJiMzOTssIFgmIzM5OzIwMjAm IzM5OywgMTIuMzQ1NjcpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOU0VSVCBJTlRP IHQyIFZBTFVFUyAoLTEwMDAsICYjMzk7JiMzOTssIFgmIzM5OyYjMzk7LCAwLjApOzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoENSRUFURSBUQUJMRSB0MSAoYSBJTlQgUFJJTUFSWSBLRVks IHN0ciBWQVJDSEFSKDEwMCkpOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoElOU0VSVCBJ TlRPIHQxIFZBTFVFUyAoMSwgJiMzOTthYiYjMzk7KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAgwqBJTlNFUlQgSU5UTyB0MSBWQUxVRVMgKDIsICYjMzk7YWJDREYmIzM5Oyk7PGJyPg0KK8Kg IMKgIMKgIMKgIMKgIMKgIMKgIMKgSU5TRVJUIElOVE8gdDEgVkFMVUVTICgzLCAmIzM5O0NERiYj Mzk7KTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBDUkVBVEUgVEFCTEUgdCAoczEgY2hh cigyKSBwcmltYXJ5IGtleSwgczIgY2hhcigyKSk7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg IMKgSU5TRVJUIElOVE8gdCBWQUxVRVMgKCYjMzk7QUImIzM5OywgJiMzOTtBQiYjMzk7KTs8YnI+ DQorwqAgwqAgwqAgwqBdXSwgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoC0tICZsdDts aWtlLXRlc3QtMS4xJmd0Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoDA8YnI+DQorwqAg wqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuMSZndDs8YnI+DQorwqAgwqAg wqAgwqB9KTxicj4NCis8YnI+DQordGVzdDpkb19leGVjc3FsX3Rlc3QoPGJyPg0KK8KgIMKgIMKg IMKgJnF1b3Q7bGlrZS10ZXN0LTEuMiZxdW90Oyw8YnI+DQorwqAgwqAgwqAgwqBbWzxicj4NCivC oCDCoCDCoCDCoCDCoCDCoCDCoCDCoFNFTEVDVCBjb2x1bW4xLCBjb2x1bW4yLCBjb2x1bW4xICog Y29sdW1uNCBGUk9NIHQyIFdIRVJFIGNvbHVtbjIgTElLRSAmIzM5O19CJiMzOTs7PGJyPg0KK8Kg IMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10 ZXN0LTEuMiZndDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqAxLCAmIzM5O0FCJiMzOTss IDUuNSwgMiwgJiMzOTtBQiYjMzk7LCAyNC42OTEzNDxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoC0tICZsdDtsaWtlLXRlc3QtMS4yJmd0Ozxicj4NCivCoCDCoCDCoCDCoH0pPGJyPg0KKzxi cj4NCit0ZXN0OmRvX2V4ZWNzcWxfdGVzdCg8YnI+DQorwqAgwqAgwqAgwqAmcXVvdDtsaWtlLXRl c3QtMS4zJnF1b3Q7LDxicj4NCivCoCDCoCDCoCDCoFtbPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgU0VMRUNUIGNvbHVtbjEsIGNvbHVtbjIgRlJPTSB0MiBXSEVSRSBjb2x1bW4yIExJS0Ug JiMzOTslQiYjMzk7Ozxicj4NCivCoCDCoCDCoCDCoF1dLCB7PGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgLS0gJmx0O2xpa2UtdGVzdC0xLjMmZ3Q7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg MSwgJiMzOTtBQiYjMzk7LCAyLCAmIzM5O0FCJiMzOTs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAtLSAmbHQ7bGlrZS10ZXN0LTEuMyZndDs8YnI+DQorwqAgwqAgwqAgwqB9KTxicj4NCis8YnI+ DQordGVzdDpkb19leGVjc3FsX3Rlc3QoPGJyPg0KK8KgIMKgIMKgIMKgJnF1b3Q7bGlrZS10ZXN0 LTEuNCZxdW90Oyw8YnI+DQorwqAgwqAgwqAgwqBbWzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDC oCDCoFNFTEVDVCBjb2x1bW4xLCBjb2x1bW4yIEZST00gdDIgV0hFUkUgY29sdW1uMiBMSUtFICYj Mzk7QV9fJiMzOTs7PGJyPg0KK8KgIMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuNCZndDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgLS0gJmx0O2xpa2UtdGVzdC0xLjQmZ3Q7PGJyPg0KK8KgIMKgIMKgIMKgfSk8YnI+DQor PGJyPg0KK3Rlc3Q6ZG9fZXhlY3NxbF90ZXN0KDxicj4NCivCoCDCoCDCoCDCoCZxdW90O2xpa2Ut dGVzdC0xLjUmcXVvdDssPGJyPg0KK8KgIMKgIMKgIMKgW1s8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBTRUxFQ1QgY29sdW1uMSwgY29sdW1uMiBGUk9NIHQyIFdIRVJFIGNvbHVtbjIgTElL RSAmIzM5O0FfJiMzOTs7PGJyPg0KK8KgIMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuNSZndDs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAg wqAxLCAmIzM5O0FCJiMzOTssIDIsICYjMzk7QUImIzM5Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDC oCDCoC0tICZsdDtsaWtlLXRlc3QtMS41Jmd0Ozxicj4NCivCoCDCoCDCoCDCoH0pPGJyPg0KKzxi cj4NCit0ZXN0OmRvX2V4ZWNzcWxfdGVzdCg8YnI+DQorwqAgwqAgwqAgwqAmcXVvdDtsaWtlLXRl c3QtMS42JnF1b3Q7LDxicj4NCivCoCDCoCDCoCDCoFtbPGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKg IMKgIMKgU0VMRUNUIGNvbHVtbjEsIGNvbHVtbjIgRlJPTSB0MiBXSEVSRSBjb2x1bW4yIExJS0Ug JiMzOTtBJiMzOTs7PGJyPg0KK8KgIMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuNiZndDs8YnI+DQorPGJyPg0KK8KgIMKgIMKgIMKgIMKg IMKgIMKgLS0gJmx0O2xpa2UtdGVzdC0xLjYmZ3Q7PGJyPg0KK8KgIMKgIMKgIMKgfSk8YnI+DQor PGJyPg0KK3Rlc3Q6ZG9fZXhlY3NxbF90ZXN0KDxicj4NCivCoCDCoCDCoCDCoCZxdW90O2xpa2Ut dGVzdC0xLjcmcXVvdDssPGJyPg0KK8KgIMKgIMKgIMKgW1s8YnI+DQorwqAgwqAgwqAgwqAgwqAg wqAgwqAgwqBTRUxFQ1QgY29sdW1uMSwgY29sdW1uMiBGUk9NIHQyIFdIRVJFIGNvbHVtbjIgTElL RSAmIzM5O18mIzM5Ozs8YnI+DQorwqAgwqAgwqAgwqBdXSwgezxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoC0tICZsdDtsaWtlLXRlc3QtMS43Jmd0Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAg wqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuNyZndDs8YnI+DQorwqAgwqAgwqAgwqB9KTxicj4N Cis8YnI+DQordGVzdDpkb19leGVjc3FsX3Rlc3QoPGJyPg0KK8KgIMKgIMKgIMKgJnF1b3Q7bGlr ZS10ZXN0LTEuOCZxdW90Oyw8YnI+DQorwqAgwqAgwqAgwqBbWzxicj4NCivCoCDCoCDCoCDCoCDC oCDCoCDCoCDCoFNFTEVDVCAqIEZST00gdCBXSEVSRSBzMSBMSUtFICYjMzk7JUEmIzM5Ozs8YnI+ DQorwqAgwqAgwqAgwqBdXSwgezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoC0tICZsdDtsaWtl LXRlc3QtMS44Jmd0Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlr ZS10ZXN0LTEuOCZndDs8YnI+DQorwqAgwqAgwqAgwqB9KTxicj4NCis8YnI+DQordGVzdDpkb19l eGVjc3FsX3Rlc3QoPGJyPg0KK8KgIMKgIMKgIMKgJnF1b3Q7bGlrZS10ZXN0LTEuOSZxdW90Oyw8 YnI+DQorwqAgwqAgwqAgwqBbWzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoFNFTEVDVCAq IEZST00gdCBXSEVSRSBzMSBMSUtFICYjMzk7JUMmIzM5Ozs8YnI+DQorwqAgwqAgwqAgwqBdXSwg ezxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoC0tICZsdDtsaWtlLXRlc3QtMS45Jmd0Ozxicj4N Cis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuOSZndDs8YnI+ DQorwqAgwqAgwqAgwqB9KTxicj4NCis8YnI+DQordGVzdDpkb19leGVjc3FsX3Rlc3QoPGJyPg0K K8KgIMKgIMKgIMKgJnF1b3Q7bGlrZS10ZXN0LTEuMTAmcXVvdDssPGJyPg0KK8KgIMKgIMKgIMKg W1s8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBTRUxFQ1QgKiBGUk9NIHQxIFdIRVJFIHN0 ciBMSUtFICYjMzk7JWRmJiMzOTs7PGJyPg0KK8KgIMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAg wqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0LTEuMTAmZ3Q7PGJyPg0KK8KgIMKgIMKgIMKg IMKgIMKgIMKgMiwgJiMzOTthYkNERiYjMzk7LCAzLCAmIzM5O0NERiYjMzk7PGJyPg0KK8KgIMKg IMKgIMKgIMKgIMKgIMKgLS0gJmx0O2xpa2UtdGVzdC0xLjEwJmd0Ozxicj4NCivCoCDCoCDCoCDC oH0pPGJyPg0KKzxicj4NCit0ZXN0OmRvX2V4ZWNzcWxfdGVzdCg8YnI+DQorwqAgwqAgwqAgwqAm cXVvdDtsaWtlLXRlc3QtMS4xMSZxdW90Oyw8YnI+DQorwqAgwqAgwqAgwqBbWzxicj4NCivCoCDC oCDCoCDCoCDCoCDCoCDCoCDCoFNFTEVDVCAqIEZST00gdDEgV0hFUkUgc3RyIExJS0UgJiMzOTth XyYjMzk7Ozxicj4NCivCoCDCoCDCoCDCoF1dLCB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKg LS0gJmx0O2xpa2UtdGVzdC0xLjExJmd0Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoDEsICYj Mzk7YWImIzM5Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoC0tICZsdDtsaWtlLXRlc3QtMS4x MSZndDs8YnI+DQorwqAgwqAgwqAgwqB9KTxicj4NCis8YnI+DQordGVzdDpkb19leGVjc3FsX3Rl c3QoPGJyPg0KK8KgIMKgIMKgIMKgJnF1b3Q7bGlrZS10ZXN0LTEuMTImcXVvdDssPGJyPg0KK8Kg IMKgIMKgIMKgW1s8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAgwqBzZWxlY3QgY29sdW1uMSwg Y29sdW1uMiBmcm9tIHQyIHdoZXJlIGNvbHVtbjIgbGlrZSAmIzM5O19fJiMzOTs7PGJyPg0KK8Kg IMKgIMKgIMKgXV0sIHs8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0 LTEuMTImZ3Q7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgMSwgJiMzOTtBQiYjMzk7LCAxLCAm IzM5O0NEJiMzOTssIDIsICYjMzk7QUImIzM5Ozxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoC0t ICZsdDtsaWtlLXRlc3QtMS4xMiZndDs8YnI+DQorwqAgwqAgwqAgwqB9KTxicj4NCis8YnI+DQor dGVzdDpkb19leGVjc3FsX3Rlc3QoPGJyPg0KK8KgIMKgIMKgIMKgJnF1b3Q7bGlrZS10ZXN0LTEu MTMmcXVvdDssPGJyPg0KK8KgIMKgIMKgIMKgW1s8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAg wqBEUk9QIFRBQkxFIHQxOzxicj4NCivCoCDCoCDCoCDCoCDCoCDCoCDCoCDCoERST1AgVEFCTEUg dDI7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgIMKgRFJPUCBUQUJMRSB0Ozxicj4NCivCoCDC oCDCoCDCoF1dLCB7PGJyPg0KK8KgIMKgIMKgIMKgIMKgIMKgIMKgLS0gJmx0O2xpa2UtdGVzdC0x LjEzJmd0Ozxicj4NCis8YnI+DQorwqAgwqAgwqAgwqAgwqAgwqAgwqAtLSAmbHQ7bGlrZS10ZXN0 LTEuMTMmZ3Q7PGJyPg0KK8KgIMKgIMKgIMKgfSk8YnI+DQorPGJyPg0KKzxicj4NCit0ZXN0OmZp bmlzaF90ZXN0KCk8YnI+DQotLSA8YnI+DQoyLjcuNDxicj4NCjxicj4NCjwvYmxvY2txdW90ZT48 L2Rpdj4NCg== --000000000000b8a865056fb33bb1--