From 41324142062d92d421fb3325d614717984b6cfd7 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 26 Jul 2022 15:47:50 +0100 Subject: [PATCH] Protect against deeply malformed JSON map keys Fixes gh-31869 --- .../boot/json/BasicJsonParser.java | 27 ++++++++++--------- .../boot/json/AbstractJsonParserTests.java | 7 +++++ .../boot/json/YamlJsonParserTests.java | 5 ++++ .../boot/json/large-malformed-json.txt | 1 + 4 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/large-malformed-json.txt diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java index 333c0b4b78b8..5e1c260b34d9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/json/BasicJsonParser.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; /** @@ -86,6 +87,20 @@ private Object parseInternal(int nesting, String json) { return json; } + private Map parseMapInternal(String json) { + Map map = new LinkedHashMap<>(); + json = trimLeadingCharacter(trimTrailingCharacter(json, '}'), '{').trim(); + for (String pair : tokenize(json)) { + String[] values = StringUtils.trimArrayElements(StringUtils.split(pair, ":")); + Assert.state(values[0].startsWith("\"") && values[0].endsWith("\""), + "Expecting double-quotes around field names"); + String key = trimLeadingCharacter(trimTrailingCharacter(values[0], '"'), '"'); + Object value = parseInternal(0, values[1]); + map.put(key, value); + } + return map; + } + private static String trimTrailingCharacter(String string, char c) { if (!string.isEmpty() && string.charAt(string.length() - 1) == c) { return string.substring(0, string.length() - 1); @@ -100,18 +115,6 @@ private static String trimLeadingCharacter(String string, char c) { return string; } - private Map parseMapInternal(String json) { - Map map = new LinkedHashMap<>(); - json = trimLeadingCharacter(trimTrailingCharacter(json, '}'), '{').trim(); - for (String pair : tokenize(json)) { - String[] values = StringUtils.trimArrayElements(StringUtils.split(pair, ":")); - String key = trimLeadingCharacter(trimTrailingCharacter(values[0], '"'), '"'); - Object value = parseInternal(0, values[1]); - map.put(key, value); - } - return map; - } - private List tokenize(String json) { List list = new ArrayList<>(); int index = 0; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java index 3320fb7e8f10..2ef4b49c57c6 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/AbstractJsonParserTests.java @@ -198,4 +198,11 @@ void listWithRepeatedOpenArray() throws IOException { .withMessageContaining("too deeply nested"); } + @Test // gh-31869 + void largeMalformed() throws IOException { + String input = StreamUtils.copyToString( + AbstractJsonParserTests.class.getResourceAsStream("large-malformed-json.txt"), StandardCharsets.UTF_8); + assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input)); + } + } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java index bb6cf19820e9..d51b3e51c445 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/json/YamlJsonParserTests.java @@ -61,4 +61,9 @@ void listWithRepeatedOpenArray() throws IOException { super.listWithRepeatedOpenArray(); } + @Override + @Disabled("SnakeYaml does not protect against malformed keys") + void largeMalformed() throws IOException { + } + } diff --git a/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/large-malformed-json.txt b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/large-malformed-json.txt new file mode 100644 index 000000000000..16bfcf377d25 --- /dev/null +++ b/spring-boot-project/spring-boot/src/test/resources/org/springframework/boot/json/large-malformed-json.txt @@ -0,0 +1 @@ +[[{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{/t:{{:{t:{[:{{:{4:{{t:{{:{[:{{:{t:{:{t:{{:{t:{:{t{t:{{{:{t?{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{/t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt:{:{[{ty/t:{{:{t:{[:{{:{4:{{t:{{:{[:{{:{t:{:{t:{{:{t:{:{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{/t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t:{:{:{:{{:{t:{t{s:{t:{tt:{{:{[",[[{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{/t:{{:{t:{[:{{:{4:{{t:{{:{[:{{:{t:{:{t:{{:{t:{:{t{t:{{{:{t?{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{/t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt:{:{[{ty/t:{{:{t:{[:{{:{4:{{t:{{:{[:{{:{t:{:{t:{{:{t:{:{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t{t{t:{{{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{:{:{t:{{t:{{:{t:{:{t:{{:{t:{:{t:{{:{t:{[:{{:{t:{{t:{{:{[:{{:{tt:[{tt{:{t:{{t:{{:{t:{:{t:{{:{t:{:{:{:{{:{t:{t{s:{t:{tt:{{:{[", \ No newline at end of file